diff options
author | Giovanni Campagna <gcampagn@cs.stanford.edu> | 2015-07-17 11:55:49 +0100 |
---|---|---|
committer | Simon Marlow <marlowsd@gmail.com> | 2015-07-22 17:50:02 +0100 |
commit | 0d1a8d09f452977aadef7897aa12a8d41c7a4af0 (patch) | |
tree | 3e8404c7f37c77b67ca913521e6890d6491f4721 /testsuite/tests | |
parent | b949c96b4960168a3b399fe14485b24a2167b982 (diff) | |
download | haskell-0d1a8d09f452977aadef7897aa12a8d41c7a4af0.tar.gz |
Two step allocator for 64-bit systems
Summary:
The current OS memory allocator conflates the concepts of allocating
address space and allocating memory, which makes the HEAP_ALLOCED()
implementation excessively complicated (as the only thing it cares
about is address space layout) and slow. Instead, what we want
is to allocate a single insanely large contiguous block of address
space (to make HEAP_ALLOCED() checks fast), and then commit subportions
of that in 1MB blocks as we did before.
This is currently behind a flag, USE_LARGE_ADDRESS_SPACE, that is only enabled for
certain OSes.
Test Plan: validate
Reviewers: simonmar, ezyang, austin
Subscribers: thomie, carter
Differential Revision: https://phabricator.haskell.org/D524
GHC Trac Issues: #9706
Diffstat (limited to 'testsuite/tests')
-rw-r--r-- | testsuite/tests/rts/Makefile | 4 | ||||
-rw-r--r-- | testsuite/tests/rts/all.T | 7 | ||||
-rw-r--r-- | testsuite/tests/rts/outofmem.stderr-ws-64 | 2 | ||||
-rw-r--r-- | testsuite/tests/rts/outofmem.stdout | 2 | ||||
-rw-r--r-- | testsuite/tests/rts/testmblockalloc.c | 75 |
5 files changed, 86 insertions, 4 deletions
diff --git a/testsuite/tests/rts/Makefile b/testsuite/tests/rts/Makefile index 5e5782a3cb..52de19c876 100644 --- a/testsuite/tests/rts/Makefile +++ b/testsuite/tests/rts/Makefile @@ -7,14 +7,14 @@ outofmem-prep:: outofmem:: @$(MAKE) outofmem-prep - @ulimit -v 10000000 2>/dev/null; ./outofmem || echo "exit($$?)" + @ulimit -m 10000000 2>/dev/null; ./outofmem || echo "exit($$?)" outofmem2-prep:: '$(TEST_HC)' $(TEST_HC_OPTS) -v0 -rtsopts --make -fforce-recomp outofmem2.hs -o outofmem2 outofmem2:: @$(MAKE) outofmem2-prep - @ulimit -v 1000000 2>/dev/null; ./outofmem2 +RTS -M5m -RTS || echo "exit($$?)" + @ulimit -m 1000000 2>/dev/null; ./outofmem2 +RTS -M5m -RTS || echo "exit($$?)" T2615-prep: $(RM) libfoo_T2615.so diff --git a/testsuite/tests/rts/all.T b/testsuite/tests/rts/all.T index 5be36349d0..0e891e8f1b 100644 --- a/testsuite/tests/rts/all.T +++ b/testsuite/tests/rts/all.T @@ -2,6 +2,13 @@ test('testblockalloc', [c_src, only_ways(['normal','threaded1']), extra_run_opts('+RTS -I0')], compile_and_run, ['']) +test('testmblockalloc', + [c_src, only_ways(['normal','threaded1']), extra_run_opts('+RTS -I0')], + compile_and_run, ['']) +# -I0 is important: the idle GC will run the memory leak detector, +# which will crash because the mblocks we allocate are not in a state +# the leak detector is expecting. + # See bug #101, test requires +RTS -c (or equivalently +RTS -M<something>) # only GHCi triggers the bug, but we run the test all ways for completeness. diff --git a/testsuite/tests/rts/outofmem.stderr-ws-64 b/testsuite/tests/rts/outofmem.stderr-ws-64 index 42a4696fcf..dca02c7ed8 100644 --- a/testsuite/tests/rts/outofmem.stderr-ws-64 +++ b/testsuite/tests/rts/outofmem.stderr-ws-64 @@ -1 +1 @@ -outofmem: out of memory (requested 2148532224 bytes) +outofmem: out of memory diff --git a/testsuite/tests/rts/outofmem.stdout b/testsuite/tests/rts/outofmem.stdout index 63a3a6988c..1acdde769d 100644 --- a/testsuite/tests/rts/outofmem.stdout +++ b/testsuite/tests/rts/outofmem.stdout @@ -1 +1 @@ -exit(1) +exit(251) diff --git a/testsuite/tests/rts/testmblockalloc.c b/testsuite/tests/rts/testmblockalloc.c new file mode 100644 index 0000000000..df03658387 --- /dev/null +++ b/testsuite/tests/rts/testmblockalloc.c @@ -0,0 +1,75 @@ +#include "Rts.h" + +#include <stdio.h> + +// 16 * 64 == max 1GB +const int MAXALLOC = 16; +const int ARRSIZE = 64; + +const int LOOPS = 1000; +const int SEED = 0xf00f00; + +extern lnat mblocks_allocated; + +int main (int argc, char *argv[]) +{ + int i, j, b; + + void *a[ARRSIZE]; + nat sizes[ARRSIZE]; + + srand(SEED); + + { + RtsConfig conf = defaultRtsConfig; + conf.rts_opts_enabled = RtsOptsAll; + hs_init_ghc(&argc, &argv, conf); + } + + // repeatedly sweep though the array, allocating new random-sized + // objects and deallocating the old ones. + for (i=0; i < LOOPS; i++) + { + for (j=0; j < ARRSIZE; j++) + { + if (i > 0) + { + freeMBlocks(a[j], sizes[j]); + } + b = (rand() % MAXALLOC) + 1; + a[j] = getMBlocks(b); + sizes[j] = b; + } + } + + releaseFreeMemory(); + + for (j=0; j < ARRSIZE; j++) + { + freeMBlocks(a[j], sizes[j]); + } + + releaseFreeMemory(); + + // this time, sweep forwards allocating new blocks, and then + // backwards deallocating them. + for (i=0; i < LOOPS; i++) + { + for (j=0; j < ARRSIZE; j++) + { + b = (rand() % MAXALLOC) + 1; + a[j] = getMBlocks(b); + sizes[j] = b; + } + for (j=ARRSIZE-1; j >= 0; j--) + { + freeMBlocks(a[j], sizes[j]); + } + } + + releaseFreeMemory(); + + hs_exit(); // will do a memory leak test + + exit(0); +} |