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/inc/hgConfig.h src/hg/inc/hgConfig.h index 5e72dd576d1..03d8e56699f 100644 --- src/hg/inc/hgConfig.h +++ src/hg/inc/hgConfig.h @@ -1,60 +1,65 @@ /* Copyright (C) 2012 The Regents of the University of California * See kent/LICENSE or http://genome.ucsc.edu/license/ for licensing information. */ #ifndef HGCONFIG_H #define HGCONFIG_H char* cfgOption(char* name); /* return the option with the given name, or null if not found */ char* cfgOptionDefault(char* name, char* def); /* return the option with the given name or the given default if it doesn't exist */ boolean cfgOptionBooleanDefault(char* name, boolean def); /* return the boolean value for option with the given name or the given * default if it doesn't exist. Booleans of yes/no/on/off/true/false are * recognized */ char *cfgOptionEnv(char *envName, char* name); /* get a configuration optional value, from either the environment or the cfg * file, with the env take precedence. Return NULL if not found */ char *cfgOptionEnvDefault(char *envName, char* name, char *def); /* get a configuration optional value, from either the environment or the cfg * file, with the env take precedence. Return default if not found */ char *cfgOption2(char *prefix, char *suffix); /* Return the option with the given two-part name, formed from prefix.suffix. * Return NULL if it doesn't exist. */ char* cfgOptionDefault2(char *prefix, char *suffix, char* def); /* Return the option with the given two-part name, formed from prefix.suffix, * or the given default if it doesn't exist. */ char *cfgVal(char *name); /* Return option with given name. Squawk and die if it * doesn't exist. */ struct slName *cfgNames(); /* get list of names in config file. slFreeList when finished */ struct slName *cfgNamesWithPrefix(); /* get list of names in config file with prefix. slFreeList when finished */ struct slName *cfgValsWithPrefix(char* prefix); /* get list of values in config file with prefix. slFreeList when finished */ unsigned long cfgModTime(); /* Return modification time of config file */ void cfgSetMaxMem(); /* Check hg.conf for maxMem. If not set, don't limit memory. Otherwise * limit memory usage to that number. */ +void cfgSetMallocTopPad(); +/* Check hg.conf for mallocTopPad. If set to a positive number of bytes, ask + * the C library to grow the heap in steps that size instead of its 128 kB + * default. */ + void cfgSetLogCgiVars(); /* optionally activate dumping of all CGI variables to stderr log */ void cfgInitCgi(); /* init kent libraries for CGI programs: max RAM, CGI logging, etc*/ #endif