gbranden pushed a commit to branch master
in repository groff.

commit 2d9cd200df13148fe2ae0ed7ff2db4cbdbe20d2d
Author: G. Branden Robinson <[email protected]>
AuthorDate: Wed Jun 10 03:33:37 2026 -0500

    [libgroff]: Tune `string` object allocations.
    
    * src/libs/libgroff/string.cpp: Increase initial buffer size backing
      `string` objects from 8 to 64, and stop allocating double the
      requested length on initial or replacement allocations.  An initial
      buffer size of 64 appears to balance build time against minimization
      of reallocations.
    
      (salloc, sfree_alloc): Allocate only `len` `char` elements, not
      `len * 2`, unless `len` equals zero.
    
      (sfree_alloc): Drop now-taulogous assert(3)ion.
    
    I instrumented `srealloc()` to report when reallocations occurred, and
    timed builds with various values of `initial_string_buffer_size`.
    
    initial size 8
    --------------
    real    0m32.780s
    user    0m35.483s
    sys     0m3.385s
    realloc 535236
    
    initial size 16
    ---------------
    real    0m31.192s
    user    0m33.949s
    sys     0m3.102s
    realloc 426412
    
    initial size 32
    ---------------
    real    0m29.430s
    user    0m32.117s
    sys     0m2.460s
    realloc 271518
    
    initial size 64
    ---------------
    real    0m28.861s
    user    0m31.691s
    sys     0m2.384s
    realloc 184568
    
    initial size 128
    ----------------
    real    0m30.959s
    user    0m34.022s
    sys     0m2.381s
    realloc 75272
    
    initial size 256
    ----------------
    real    0m30.912s
    user    0m34.149s
    sys     0m2.381s
    realloc 28405
    
    We see that while, as expected, reallocations steadily decrease with
    increasing "initial size", there is a local minimum in both wall-clock
    and user-space time for an initial size selection of 64.
---
 ChangeLog                    | 11 +++++++++++
 src/libs/libgroff/string.cpp | 17 +++++++++++++----
 2 files changed, 24 insertions(+), 4 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index a7dcff6d7..cf1054e5a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2026-06-10  G. Branden Robinson <[email protected]>
+
+       * src/libs/libgroff/string.cpp: Increase initial buffer size
+       backing `string` objects from 8 to 64, and stop allocating
+       double the requested length on initial or replacement
+       allocations.  An initial buffer size of 64 appears to balance
+       build time against minimization of reallocations.
+       (salloc, sfree_alloc): Allocate only `len` `char` elements, not
+       `len * 2`, unless `len` equals zero.
+       (sfree_alloc): Drop now-taulogous assert(3)ion.
+
 2026-06-09  G. Branden Robinson <[email protected]>
 
        * src/libs/libgroff/string.cpp: Continue refactoring to
diff --git a/src/libs/libgroff/string.cpp b/src/libs/libgroff/string.cpp
index 7f5e5a32c..862586dad 100644
--- a/src/libs/libgroff/string.cpp
+++ b/src/libs/libgroff/string.cpp
@@ -44,14 +44,20 @@ along with this program.  If not, see 
<http://www.gnu.org/licenses/>. */
 // TODO 1: Replace all this memory management stuff with vector<char>.
 // TODO 2: Replace this entire class.  See Savannah #67735.
 
-static const size_t initial_string_buffer_size = 8;
+// An initial buffer size of 64 appears to balance build time against
+// minimization of reallocations.
+static const size_t initial_string_buffer_size = 64;
 
 static char *salloc(size_t len, size_t *sizep)
 {
   char *p = 0 /* nullptr */;
-  size_t amount = len * 2;
+  size_t amount = len;
   if (0 == amount)
     amount = initial_string_buffer_size;
+  // XXX: Add 1 as a hack to work around a problem created in
+  // src/devices/html/post-html.cpp:page::add_and_encode_char() when it
+  // is omitted.  If/when we resolve that, we can assign simply `len`.
+  amount += 1;
   try {
     p = new char[*sizep = amount];
   }
@@ -90,8 +96,9 @@ static char *sfree_alloc(char *ptr, size_t oldsz, size_t len,
     return 0 /* nullptr */; // XXX: GBR: breaks invariant
   }
   char *p = 0 /* nullptr */;
-  size_t amount = len * 2;
-  assert(amount > 0);
+  size_t amount = len;
+  if (0 == amount)
+    amount = initial_string_buffer_size;
   try {
     p = new char[*sizep = amount];
   }
@@ -116,6 +123,8 @@ static char *srealloc(char *ptr, size_t oldsz, size_t 
oldlen,
     return 0 /* nullptr */; // XXX: GBR: breaks invariant
   }
   else {
+    // If the string changes size once, assume it will change again; try
+    // to prevent excessive reallocations.
     size_t amount = newlen * 2;
     char *p = 0 /* nullptr */;
     try {

_______________________________________________
groff-commit mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/groff-commit

Reply via email to