a5d42e58d7f8ce1e985cf7422145619122ca5d25
braney
  Sat Sep 19 18:16:16 2026 -0700
mallocTopPadTester: check the heap step setting still reaches the library

cfgSetMallocTopPad() asks glibc to grow the heap in steps of mallocTopPad bytes
instead of its 128 kB default, which saves a heavy hgTracks render more than a
hundred thousand system calls that draw nothing.

The failure to catch is backsliding: the mallopt call is dropped in a later
edit, or the setting is renamed, or it stops being read before the first
allocation.  Every page still draws correctly and the only symptom is that
renders are slower than they used to be, which nobody attributes to this.

So the test measures the step, not the clock.  A timing test here would be red
on a busy hgwdev, green on an idle one, and deleted within a month.  sbrk(0)
says where the heap ends and the distance it jumps when malloc extends it is
what M_TOP_PAD sets, so the answer is the same on a loaded machine as an idle
one.  It is read in buckets, since glibc may round and may change what it
rounds to; what must not change is the order of magnitude between a configured
step and the default.  Allocations stay under the mmap threshold, or the break
never moves and the test measures nothing while appearing to pass.

Two runs, with the setting and without, because the answer is the difference
between them: a single run would pass on a library whose own default happened
to be large.

Watched to fail and then pass: leaving the knob read but never applied gives
the default step under both confs, which is the one line the diff shows.
Recorded as sandbox-ab in utils/testRegistry.

refs #38225, refs #38391

diff --git src/hg/lib/tests/makefile src/hg/lib/tests/makefile
index cad98d9069c..4e9057e935e 100644
--- src/hg/lib/tests/makefile
+++ src/hg/lib/tests/makefile
@@ -1,103 +1,114 @@
 kentSrc = ../../..
 include ../../../inc/common.mk
 
 L += ${MYSQLLIBS} -lm
 MYLIBDIR = ../../../lib/${MACHTYPE}
 MYLIBS =  ${MYLIBDIR}/jkhgap.a ${MYLIBDIR}/jkweb.a
 BIN_DIR = bin/${MACHTYPE}
 
 all: 	${BIN_DIR}/genePredTester \
 	${BIN_DIR}/trashDirTester \
+	${BIN_DIR}/mallocTopPadTester \
 	${BIN_DIR}/pslReaderTester \
 	${BIN_DIR}/quickLiftTester \
 	${BIN_DIR}/sessionDataTester \
 	${BIN_DIR}/trashDirTester \
 #	${BIN_DIR}/annoGratorTester \
 	${BIN_DIR}/binTest \
 	${BIN_DIR}/customTrackTester \
 	${BIN_DIR}/hgvsTester \
 	${BIN_DIR}/sqlCheck 
 
 ${BIN_DIR}/%: %.c ${MYLIBS}
 	@${MKDIR} ${BIN_DIR}
 	${CC} ${CC_PROG_OPTS} -o $@ $*.c ${MYLIBS} $L
 
 #test: binTest spDbTest hdbTest genePredTest pslReaderTest annoGratorTest customTrackTest hgvsTest
-test: binTest quickLiftTest sessionDataTest trashDirTest spDbTest hdbTest genePredTest pslReaderTest customTrackTest hgvsTest
+test: binTest quickLiftTest sessionDataTest trashDirTest mallocTopPadTest spDbTest hdbTest genePredTest pslReaderTest customTrackTest hgvsTest
 	rm -r output
 	echo tested all
 
 mkdirs:
 	@${MKDIR} output ${BIN_DIR}
 
 loaders:
 	ln -sf ${CGI_BIN}/loader .
 
 spDbTest: ${BIN_DIR}/spDbTest mkdirs
 	${BIN_DIR}/spDbTest sp121210 Q9FFH7 > output/spDbTest
 	${BIN_DIR}/spDbTest sp121210 P29312 >> output/spDbTest
 	diff expected/spDbTest output/spDbTest
 
 hdbTest: ${BIN_DIR}/hdbTest mkdirs
 	${BIN_DIR}/hdbTest > output/hdbTest
 	diff expected/hdbTest output/hdbTest
 
 genePredTest: ${BIN_DIR}/genePredTester mkdirs
 	${MAKE} -f genePredTests.mk test
 
 pslReaderTest: ${BIN_DIR}/pslReaderTester mkdirs
 	${MAKE} -f pslReaderTests.mk test
 
 #annoGratorTest: ${BIN_DIR}/annoGratorTester mkdirs
 #	${MAKE} -f annoGratorTests.mk test
 
 customTrackTest: ${BIN_DIR}/customTrackTester loaders mkdirs
 	${MAKE} -f customTrackTests.mk test BIN_DIR=${BIN_DIR} OUT_DIR=output
 
 hgvsTest: ${BIN_DIR}/hgvsTester mkdirs
 	${MAKE} -f hgvsTests.mk test
 
 binTest: mkdirs ${BIN_DIR}/binTest
 	@./binTest.sh
 
 quickLiftTest: ${BIN_DIR}/quickLiftTester mkdirs
 	${BIN_DIR}/quickLiftTester > output/quickLiftTest
 	diff expected/quickLiftTest output/quickLiftTest
 
 sessionDataTest: ${BIN_DIR}/sessionDataTester mkdirs
 	${BIN_DIR}/sessionDataTester output/sessionData > output/sessionDataTest
 	diff expected/sessionDataTest output/sessionDataTest
 
 # Three runs, because hgConfig caches the config it read, so one process can only answer for
 # one spelling of sessionDataDir.  The fixture is made here rather than in C: a directory, a
 # symlink to it, and three confs naming the same place three ways.  Each conf includes the
 # developer's own so the database settings come along, and is mode 600 because hgConfig
 # refuses a group-readable file whose name begins with a dot -- these do not, but the habit is
 # worth keeping.
 trashDirTest: ${BIN_DIR}/trashDirTester mkdirs
 	rm -rf output/sd
 	${MKDIR} output/sd/real/hgt
 	ln -s real output/sd/link
 	echo "include ${HOME}/.hg.conf" > output/sd/link.conf
 	echo "sessionDataDir=`pwd`/output/sd/link" >> output/sd/link.conf
 	echo "include ${HOME}/.hg.conf" > output/sd/real.conf
 	echo "sessionDataDir=`pwd`/output/sd/real" >> output/sd/real.conf
 	echo "include ${HOME}/.hg.conf" > output/sd/rel.conf
 	echo "sessionDataDir=output/sd/link" >> output/sd/rel.conf
 	HGDB_CONF=output/sd/link.conf ${BIN_DIR}/trashDirTester \
 	    "the symlink, absolute" `pwd`/output/sd/link `pwd`/output/sd/real \
 	    > output/trashDirTest
 	HGDB_CONF=output/sd/real.conf ${BIN_DIR}/trashDirTester \
 	    "the resolved directory, absolute" `pwd`/output/sd/link `pwd`/output/sd/real \
 	    >> output/trashDirTest
 	HGDB_CONF=output/sd/rel.conf ${BIN_DIR}/trashDirTester \
 	    "the symlink, relative" `pwd`/output/sd/link `pwd`/output/sd/real \
 	    >> output/trashDirTest
 	diff expected/trashDirTest output/trashDirTest
 
+# Twice: once with the setting and once without, because the answer is the DIFFERENCE between
+# them.  A single run could pass on a library whose own default happened to be large.
+mallocTopPadTest: ${BIN_DIR}/mallocTopPadTester mkdirs
+	echo "include ${HOME}/.hg.conf" > output/topPadOff.conf
+	echo "include ${HOME}/.hg.conf" > output/topPadOn.conf
+	echo "mallocTopPad=33554432" >> output/topPadOn.conf
+	HGDB_CONF=output/topPadOff.conf ${BIN_DIR}/mallocTopPadTester > output/mallocTopPadTest
+	HGDB_CONF=output/topPadOn.conf ${BIN_DIR}/mallocTopPadTester >> output/mallocTopPadTest
+	diff expected/mallocTopPadTest output/mallocTopPadTest
+
 sqlCheck: ${BIN_DIR}/sqlCheck mkdirs
 	${MAKE} -f sqlCheck.mk test BIN_DIR=${BIN_DIR} OUT_DIR=output
 
 
 clean:
 	rm -rf *.o bin output *.tmp loader udcCache