1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-03-09 15:50:02 +00:00

tests/leaks.sh: allow run without vmalloc/vmstate

This allows running 'bin/shtests leaks' on a ksh without the
vmstate builtin and/or that is not compiled with AST vmalloc.
It falls back to 'ps -o rss= -p $$' to get the memory state.

This is in preparation for the beta and release versions, which
will not use vmalloc due to its defects[*]. Unfortunately,
abandoning vmalloc means abandoning the vmstate builtin which makes
it extremely efficient to test for memory leaks.

Because 'ps' only has a KiB granularity and also shows larger
artefacts/variations than vmalloc on most systems, we need many
more iterations (16384) and also tolerate a higher number of bytes
per iterations (8). So the run takes much longer. To tolerate only
2 bytes per iteration, we would need four times as many iterations,
which would make it take too long to run. Since a single word (e.g.
one pointer) on a 64-bit system is 8 bytes, it still seems very
unlikely for a real memory leak to be that small.

This is coded to make it easy to detect and add iteration and
tolerance parameters for a new method to get the memory state,
if some efficient or precise system-specific way is discovered.

I've also managed to trigger a false leak with shcomp in a UTF-8
locale on CentOS on a ksh with vmalloc/vmstate. So this increases
the tolerance for vmalloc from 2 to 4 bytes/iteration.

[*] Discussion: https://github.com/ksh93/ksh/issues/95
This commit is contained in:
Martijn Dekker 2020-09-18 19:19:18 +02:00
parent 69679be8d7
commit fbdf240acb

View file

@ -30,17 +30,33 @@ Command=${0##*/}
integer Errors=0
[[ -d $tmp && -w $tmp && $tmp == "$PWD" ]] || { err\_exit "$LINENO" '$tmp not set; run this from shtests. Aborting.'; exit 1; }
builtin vmstate 2>/dev/null || { err\_exit "$LINENO" 'vmstate built-in command not compiled in; skipping tests'; exit 0; }
# Get the current amount of memory usage
function getmem
{
vmstate --format='%(busy_size)u'
}
n=$(getmem)
if ! let "($n) == ($n) && n > 0" # not a non-zero number?
then err\_exit "$LINENO" "vmstate built-in command not functioning; tests cannot be run"
exit 1
# Determine method for running tests.
# The 'vmstate' builtin can be used if ksh was compiled with vmalloc.
if builtin vmstate 2>/dev/null &&
n=$(vmstate --format='%(busy_size)u') &&
let "($n) == ($n) && n > 0" # non-zero number?
then N=512 # number of iterations for each test
unit=bytes
tolerance=$((4*N)) # tolerate 4 bytes per iteration to account for vmalloc artefacts
function getmem
{
vmstate --format='%(busy_size)u'
}
# Otherwise, make do with the nonstandard 'rss' (real resident size) keyword
# of the 'ps' command (the standard 'vsz', virtual size, is not usable).
elif n=$(ps -o rss= -p "$$" 2>/dev/null) &&
let "($n) == ($n) && n > 0"
then N=16384
unit=KiB
tolerance=$((8*N/1024)) # tolerate 8 bytes per iteration to account for malloc/ps artefacts
function getmem
{
ps -o rss= -p "$$"
}
else err\_exit "$LINENO" 'WARNING: cannot find method to measure memory usage; skipping tests'
exit 0
fi
# test for variable reset leak #
@ -57,18 +73,13 @@ function test_reset
# Initialise variables used below to avoid false leaks
before=0 after=0 i=0 u=0
# Number of iterations for each test
N=512
# Check results. Add a tolerance of 2 bytes per iteration. Some tests appear to have tiny leaks, but they
# must be vmalloc artefacts; they may increase with the number of iterations, then suddenly go away when the
# number of iterations is large enough (e.g. 10000) and don't return when increasing iterations further.
#
# Check results.
# The function has 'err_exit' in the name so that shtests counts each call as at test.
function err_exit_if_leak
{
if ((after > before + 2 * N))
then err\_exit "$1" "$2 (leaked $((after - before)) bytes after $N iterations)"
if ((after > before + tolerance))
then err\_exit "$1" "$2 (leaked approx $((after - before)) $unit after $N iterations)"
fi
}
alias err_exit_if_leak='err_exit_if_leak "$LINENO"'
@ -91,6 +102,9 @@ done
data="(v=;sid=;di=;hi=;ti='1328244300';lv='o';id='172.3.161.178';var=(k='conn_num._total';u=;fr=;l='Number of Connections';n='22';t='number';))"
read -C stat <<< "$data"
for ((i=0; i < 8; i++)) # steady state first
do print -r -- "$data" | while read -u$n -C stat; do :; done {n}<&0-
done
before=$(getmem)
for ((i=0; i < N; i++))
do print -r -- "$data"
@ -109,7 +123,6 @@ for ((i=0; i < N; i++))
do read -C stat <<< "$data"
done
after=$(getmem)
# this test can show minor variations in memory usage when run with shcomp: https://github.com/ksh93/ksh/issues/70
err_exit_if_leak "memory leak with read -C when using <<<"
# ======