This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [RFC] Calling realloc vs. mallo/memcpy/free and _IO_vasprintf.


On 11/26/2015 10:14 PM, Siddhesh Poyarekar wrote:
> On Thu, Nov 26, 2015 at 09:34:29PM -0500, Carlos O'Donell wrote:
>> While answering a question on libc-help about asprintf I happened
>> to look at _IO_vasprintf and noticed some code which tries to
>> decide if it should do a realloc vs. malloc/memcpy/free.
>>
>> In this particular case we should always be shrinking the buffer.
>> For example _IO_vfprintf may have expanded the stream buffer but
>> now no longer needs the extra space. If we are growing the buffer
>> then something is very very wrong since that means _IO_vpfrintf
>> will have failed due to lack of memory, and we handled that case
>> earlier in _IO_vasprintf.
>>
>> So again, if we are only shrinking the buffer, then realloc has
>> to be the most optimal operation in all cases. It would seem to
>> me that an allocation shrink like this would almost never result
>> in an allocation move, but rather malloc would just split the
>> allocation and reuse the remainder for other malloc calls.
>>
>> So why the micro-optimization?
>>
>> Is my assumption of always shrinking the buffer wrong?
>>
>> If my assumption is right, and my logic is right, wouldn't the
>> following patch be a natural cleanup?
> 
> Why would malloc+memcpy+free be faster than a realloc, which does the
> same thing internally, but without adding the extra PLT and avoiding
> memcpy for smaller copies?  I'd say just drop that bit and stick to
> realloc.
 
Just to verify my assertion about the buffer always being shrunk, I added:

  /* The amount the stream has allocated is always >= what we needed.  */
  assert ((sf._sbf._f._IO_write_end - sf._sbf._f._IO_write_base)
          >= needed);

And it triggers in the testsuite:

(gdb) p sf._sbf._f._IO_write_end
$2 = 0x9c5054 ""
(gdb) p sf._sbf._f._IO_write_base
$3 = 0x9c4ff0 "fma_downward (0x3.", '0' <repeats 12 times>, "1ffcp+10132, -0x2.", '0' <repeats 15 times>, "4p+4432, 0x1.80e000000003fffep+14516)"
(gdb) p needed
$4 = 101
(gdb) p sf._sbf._f._IO_write_end - sf._sbf._f._IO_write_base
$5 = 100
(gdb) 

It's a case where the initial working buffer is exactly equal to what's
needed minus the NULL, and because we have to return a null-terminated
string we must grow the buffer by 1 byte.

I still don't see how realloc is going to be slower since it's just
one call, and there *might* be enough space in this chunk or the next
to grow by one byte and that avoids the memcpy.

Cheers,
Carlos.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]