d2a2afcd6c5c19257f8ed2f746c3f94474f4ab78
braney
  Tue Sep 1 13:37:34 2026 -0700
hgTracks: let hg.conf set how big a step malloc takes, refs #38225

hgTracks loads tracks in parallel threads, and each thread grows its own
memory pool in the 128 kB steps glibc uses by default.  A heavy render asks
the kernel to enlarge a pool about 133,000 times, work that does nothing for
the reader.

The new hg.conf setting mallocTopPad is a number of bytes.  When it is set,
cfgSetMallocTopPad() passes it to mallopt(M_TOP_PAD) before anything else in
main() has a chance to allocate, so the heap grows in that size step instead.
Absent or zero, glibc is left alone and nothing changes.

Measured with the #38094 harness over eight sessions and two positions, at
32 MB: renders take 0.926 of the time they did, against a noise floor of
1.006.  With the setting absent the same build measures 1.004, inside that
noise floor.  Through apache on a sandbox it measures 0.906.  The cost is
about 65 MB more resident memory on a heavy session and 8 to 20 MB on an
ordinary view, where it also saves no measurable time; the saving and the
cost are the same effect and appear together.  The rendered image is byte
identical either way.

Off by default, so a server opts in.

diff --git src/hg/hgTracks/mainMain.c src/hg/hgTracks/mainMain.c
index 3a56e42cd40..fce837d8279 100644
--- src/hg/hgTracks/mainMain.c
+++ src/hg/hgTracks/mainMain.c
@@ -23,30 +23,34 @@
 #include "versionInfo.h"
 #include "net.h"
 #include "search.h"
 #include "imageV2.h"
 #include "extTools.h"
 #include "botDelay.h"
 #include "hgConfig.h"
 #include <sys/time.h>
 #include <sys/resource.h>
 
 boolean issueBotWarning;
 long enteredMainTime = 0;
 
 int main(int argc, char *argv[])
 {
+// First, before anything has a chance to allocate: read hg.conf and set how
+// big a step the C library takes when it grows the heap.  refs #38225
+cfgSetMallocTopPad();
+
 enteredMainTime = clock1000();
 measureTime(NULL);
 
 // This is generic CGI setup code: Should be moved one day into a generic function 
 // combined with the code cart.c:genericCgiSetup() ?
 cfgSetMaxMem(); // read hg.conf and set the maxMem if there
 cfgSetLogCgiVars(); // set logging of the CGI vars
 
 issueBotWarning = earlyBotCheck(enteredMainTime, "hgTracks", delayFraction, 0, 0, "html");
 browserName = hBrowserName();
 organization = "UCSC";
 
 /* Push very early error handling - this is just
  * for the benefit of the cgiVarExists, which
  * somehow can't be moved effectively into doMiddle. */