Patch: enumerate all live blocks
Benoit Jacob
jacob.benoit.1 at gmail.com
Sat Oct 6 11:42:02 PDT 2012
2012/10/6 Justin Lebar <justin.lebar at gmail.com>:
>> It is equivalent, as long as you can ensure that _all_ allocations go
>> through your wrappered malloc.
>
> For the purposes of the live-block-walker, does it matter if we miss
> the occasional malloc()/free()?
It matters for just being able to run at all without crashing: a
mismatch between wrappered and non-wrappered functions would cause a
crash or corruption like allocator mismatches typically do.
Benoit
>
> On Sat, Oct 6, 2012 at 11:51 AM, Benoit Jacob <jacob.benoit.1 at gmail.com> wrote:
>> It is equivalent, as long as you can ensure that _all_ allocations go
>> through your wrappered malloc. The terror of anyone making such a
>> wrappered malloc is that some allocations might escape it, such as:
>> allocations made by libraries that your application uses, etc. Not
>> being familiar with the field, I just found it easier to be confident
>> that all allocations would be correctly wrappered by doing it in the
>> memory allocator itself, since if any allocation did not go through
>> it, we would have allocator mismatches anyway.
>>
>> Here is an example of what scared me away from trying to do it in the
>> application: this is a comment in jemalloc 3.0's src/jemalloc.c:
>>
>> #if ((is_malloc(je_malloc) == 1) && defined(__GLIBC__) && !defined(__UCLIBC__))
>> /*
>> * glibc provides the RTLD_DEEPBIND flag for dlopen which can make it possible
>> * to inconsistently reference libc's malloc(3)-compatible functions
>> * (https://bugzilla.mozilla.org/show_bug.cgi?id=493541).
>> *
>> * These definitions interpose hooks in glibc. The functions are actually
>> * passed an extra argument for the caller return address, which will be
>> * ignored.
>> */
>> JEMALLOC_EXPORT void (* const __free_hook)(void *ptr) = je_free;
>> JEMALLOC_EXPORT void *(* const __malloc_hook)(size_t size) = je_malloc;
>> JEMALLOC_EXPORT void *(* const __realloc_hook)(void *ptr, size_t size) =
>> je_realloc;
>> JEMALLOC_EXPORT void *(* const __memalign_hook)(size_t alignment, size_t size) =
>> je_memalign;
>> #endif
>>
>> Benoit
>>
>> 2012/10/6 Salvatore Sanfilippo <antirez at gmail.com>:
>>> Hello,
>>>
>>> what is the advantage of this approach compared to doing it entirely
>>> in the application code just wrapping malloc/realloc/free?
>>> Basically wrappered_malloc() allocates a bit more space accordingly to
>>> the metadata to store, store this metadata at the start of the block,
>>> and then returns the pointer advanced to the start of the empty space.
>>>
>>> Doing it in the context of the application makes it
>>> malloc-implementation agnostic that can be an advantage.
>>>
>>> Regards,
>>> Salvatore
>>>
>>> On Sat, Oct 6, 2012 at 7:28 AM, Benoit Jacob <jacob.benoit.1 at gmail.com> wrote:
>>>> Hello,
>>>>
>>>> The attached patch instruments jemalloc 3.0, adding the ability to
>>>> enumerate all live blocks.
>>>>
>>>> Currently, the only information stored about blocks is their (payload)
>>>> address and size, but the plan is to also store their allocation call
>>>> stack.
>>>>
>>>> This is achieved by allocating larger blocks than requested, and using
>>>> the extra space to store doubly linked list elements.
>>>>
>>>> This is provided just in case it might be useful to anyone, not
>>>> considered ready for inclusion in jemalloc. It's been tested for 15
>>>> minutes in a Firefox build.
>>>>
>>>> Details about the overhead, and how it could be reduced:
>>>> * Memory overhead is, per block: 32 bytes on 32-bit systems, 48 bytes
>>>> on 64-bit systems (assuming size_t == uintptr_t). Could easily be
>>>> reduced to 16 bytes in both cases (by using a XOR linked list and
>>>> assuming that no block exceeds 4G).
>>>> * Slowness overhead is essentially an additional mutex to lock on
>>>> every malloc/free call. Could be solved in various ways, either
>>>> copying what jemalloc does internally, or by using a lock-free list.
>>>>
>>>> If you want to test it out, currently the only built-in way to output
>>>> the list of blocks is to call je_dump_list_of_blocks(void) e.g. from
>>>> your debugger. See its code to see the relevant calls. Sample output
>>>> from Firefox:
>>>>
>>>> ...snip...
>>>> Block 193965: real block = 0x7fffba218580, payload = 0x7fffba2185b0,
>>>> payload size = 64
>>>> Block 193966: real block = 0x7fffc02dd000, payload = 0x7fffc02dd030,
>>>> payload size = 1024
>>>> Block 193967: real block = 0x7fffc2053ce0, payload = 0x7fffc2053d10,
>>>> payload size = 24
>>>> Block 193968: real block = 0x7fffc5b4ed80, payload = 0x7fffc5b4edb0,
>>>> payload size = 80
>>>> Block 193969: real block = 0x7fffd119e240, payload = 0x7fffd119e270,
>>>> payload size = 64
>>>> Block 193970: real block = 0x7fffcfb4aa60, payload = 0x7fffcfb4aa90,
>>>> payload size = 24
>>>> Block 193971: real block = 0x7fffbb85e1f0, payload = 0x7fffbb85e220,
>>>> payload size = 24
>>>> Block 193972: real block = 0x7fffe20a62e0, payload = 0x7fffe20a6310,
>>>> payload size = 32
>>>>
>>>> End enumeration of 193973 jemalloc blocks.
>>>>
>>>> Cheers,
>>>> Benoit
>>>>
>>>> _______________________________________________
>>>> jemalloc-discuss mailing list
>>>> jemalloc-discuss at canonware.com
>>>> http://www.canonware.com/mailman/listinfo/jemalloc-discuss
>>>>
>>>
>>>
>>>
>>> --
>>> Salvatore 'antirez' Sanfilippo
>>> open source developer - VMware
>>> http://invece.org
>>>
>>> Beauty is more important in computing than anywhere else in technology
>>> because software is so complicated. Beauty is the ultimate defence
>>> against complexity.
>>> — David Gelernter
>> _______________________________________________
>> jemalloc-discuss mailing list
>> jemalloc-discuss at canonware.com
>> http://www.canonware.com/mailman/listinfo/jemalloc-discuss
More information about the jemalloc-discuss
mailing list