public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] libio/vasprintf.c: Always use realloc.
@ 2015-11-27 15:03 Carlos O'Donell
  2015-12-01 16:36 ` Carlos O'Donell
  0 siblings, 1 reply; 4+ messages in thread
From: Carlos O'Donell @ 2015-11-27 15:03 UTC (permalink / raw)
  To: GNU C Library, Siddhesh Poyarekar

The asprintf/vasprintf implementations calls into _IO_vasprintf
to carry out operations on a string-based FILE* object. When
the work is complete and the buffer filled with the result the
implementation null-terminates and returns the string which is
passed back to the caller of asprintf.

During underflow the string-based buffer might have grown, and
conversely the buffer might be exactly the right size, but short
by 1-byte for the NULL terminator. Therefore the implementation
chooses to realloc the buffer to return back any excess memory
or get 1-byte more for the NULL terminator.

In 2000 the implementation was changed by Ulrich Drpper to
make a local deicsion to use realloc vs. malloc/memcpy/free
based on a heuristic and in order to reduce memory fragmentation.
The idea is that if the buffer is only just bigger than what the
user needs the realloc will split the chunk and increase
fragmentation. While this is true, this decision should not be
made at the _IO_vasprintf level. The allocator should be making
this decision based on known fragmentation estimates and a tunable
fragmentation parameter which could be used to control when realloc
splits a chunk and when it decides to malloc/memcpy/free.

Therefore we remove the local heuristic. This should increase
performance slightly at the cost of fragmentation. Future malloc
work to handle fragmentation should be pursued. If someone measures
fragmentation and tracks it back down to _IO_vasprintf, we add a
comment to guide the reader to what we consider is best practice:
enhance realloc to handle fragmentation decisions.

OK to checkin?

No regressions on x86_64.

Cheers,
Carlos.

2015-11-27  Carlos O'Donell  <carlos@redhat.com>

	* libio/vasprintf.c (_IO_vasprintf): Always use realloc.

diff --git a/libio/vasprintf.c b/libio/vasprintf.c
index 61cdfdd..5b39ee7 100644
--- a/libio/vasprintf.c
+++ b/libio/vasprintf.c
@@ -41,7 +41,6 @@ _IO_vasprintf (char **result_ptr, const char *format, _IO_va_list args)
   _IO_strfile sf;
   int ret;
   _IO_size_t needed;
-  _IO_size_t allocated;
   /* No need to clear the memory here (unlike for open_memstream) since
      we know we will never seek on the stream.  */
   string = (char *) malloc (init_string_size);
@@ -62,24 +61,18 @@ _IO_vasprintf (char **result_ptr, const char *format, _IO_va_list args)
       free (sf._sbf._f._IO_buf_base);
       return ret;
     }
-  /* Only use realloc if the size we need is of the same (binary)
-     order of magnitude then the memory we allocated.  */
   needed = sf._sbf._f._IO_write_ptr - sf._sbf._f._IO_write_base + 1;
-  allocated = sf._sbf._f._IO_write_end - sf._sbf._f._IO_write_base;
-  if ((allocated >> 1) <= needed)
-    *result_ptr = (char *) realloc (sf._sbf._f._IO_buf_base, needed);
-  else
-    {
-      *result_ptr = (char *) malloc (needed);
-      if (*result_ptr != NULL)
-	{
-	  memcpy (*result_ptr, sf._sbf._f._IO_buf_base, needed - 1);
-	  free (sf._sbf._f._IO_buf_base);
-	}
-      else
-	/* We have no choice, use the buffer we already have.  */
-	*result_ptr = (char *) realloc (sf._sbf._f._IO_buf_base, needed);
-    }
+  /* We are either shrinking the buffer, doing nothing, or growing
+     the buffer by 1 byte for the NULL.  In all of these cases it's
+     fastest to call realloc.  At the cost of more memory we could
+     choose not to realloc and return a larger buffer, but tuning
+     that requires some thought.  At one point this code was expanded
+     to consider realloc vs. malloc/memcpy/free as a method for
+     reducing fragmentation caused by realloc, but was later removed
+     because such decisions are tuning parameters that should be part
+     of the realloc decisions made by malloc e.g. fragmentation vs.
+     making a copy.  */
+  *result_ptr = (char *) realloc (sf._sbf._f._IO_buf_base, needed);
   if (*result_ptr == NULL)
     *result_ptr = sf._sbf._f._IO_buf_base;
   (*result_ptr)[needed - 1] = '\0';

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] libio/vasprintf.c: Always use realloc.
  2015-11-27 15:03 [PATCH] libio/vasprintf.c: Always use realloc Carlos O'Donell
@ 2015-12-01 16:36 ` Carlos O'Donell
  2016-03-04 18:42   ` Roland McGrath
  0 siblings, 1 reply; 4+ messages in thread
From: Carlos O'Donell @ 2015-12-01 16:36 UTC (permalink / raw)
  To: GNU C Library, Siddhesh Poyarekar

On 11/27/2015 10:03 AM, Carlos O'Donell wrote:
> The asprintf/vasprintf implementations calls into _IO_vasprintf
> to carry out operations on a string-based FILE* object. When
> the work is complete and the buffer filled with the result the
> implementation null-terminates and returns the string which is
> passed back to the caller of asprintf.
> 
> During underflow the string-based buffer might have grown, and
> conversely the buffer might be exactly the right size, but short
> by 1-byte for the NULL terminator. Therefore the implementation
> chooses to realloc the buffer to return back any excess memory
> or get 1-byte more for the NULL terminator.
> 
> In 2000 the implementation was changed by Ulrich Drpper to
> make a local deicsion to use realloc vs. malloc/memcpy/free
> based on a heuristic and in order to reduce memory fragmentation.
> The idea is that if the buffer is only just bigger than what the
> user needs the realloc will split the chunk and increase
> fragmentation. While this is true, this decision should not be
> made at the _IO_vasprintf level. The allocator should be making
> this decision based on known fragmentation estimates and a tunable
> fragmentation parameter which could be used to control when realloc
> splits a chunk and when it decides to malloc/memcpy/free.
> 
> Therefore we remove the local heuristic. This should increase
> performance slightly at the cost of fragmentation. Future malloc
> work to handle fragmentation should be pursued. If someone measures
> fragmentation and tracks it back down to _IO_vasprintf, we add a
> comment to guide the reader to what we consider is best practice:
> enhance realloc to handle fragmentation decisions.
> 
> OK to checkin?
> 
> No regressions on x86_64.

I'm going to drop this until I can get a benchtest to show this
is better than before.

c.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] libio/vasprintf.c: Always use realloc.
  2015-12-01 16:36 ` Carlos O'Donell
@ 2016-03-04 18:42   ` Roland McGrath
  2016-03-04 21:51     ` Carlos O'Donell
  0 siblings, 1 reply; 4+ messages in thread
From: Roland McGrath @ 2016-03-04 18:42 UTC (permalink / raw)
  To: Carlos O'Donell; +Cc: GNU C Library, Siddhesh Poyarekar

> I'm going to drop this until I can get a benchtest to show this
> is better than before.

IMHO if benchmarks simply show it's not clearly worse, then you should go
ahead because it simplifies the code.  If the motivation for a change is
not performance alone, then it doesn't need to demonstrate a performance
improvement per se.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] libio/vasprintf.c: Always use realloc.
  2016-03-04 18:42   ` Roland McGrath
@ 2016-03-04 21:51     ` Carlos O'Donell
  0 siblings, 0 replies; 4+ messages in thread
From: Carlos O'Donell @ 2016-03-04 21:51 UTC (permalink / raw)
  To: Roland McGrath; +Cc: GNU C Library, Siddhesh Poyarekar

On 03/04/2016 01:42 PM, Roland McGrath wrote:
>> I'm going to drop this until I can get a benchtest to show this
>> is better than before.
> 
> IMHO if benchmarks simply show it's not clearly worse, then you should go
> ahead because it simplifies the code.  If the motivation for a change is
> not performance alone, then it doesn't need to demonstrate a performance
> improvement per se.

It's hard to tell. I'd like to prove it to myself that it's generating
better code.

c.
 

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2016-03-04 21:51 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-11-27 15:03 [PATCH] libio/vasprintf.c: Always use realloc Carlos O'Donell
2015-12-01 16:36 ` Carlos O'Donell
2016-03-04 18:42   ` Roland McGrath
2016-03-04 21:51     ` Carlos O'Donell

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).