bdwgc icon indicating copy to clipboard operation
bdwgc copied to clipboard

Too many heap sections: Increase MAXHINCR or MAX_HEAP_SECTS

Open UltimatePea opened this issue 1 year ago • 5 comments

Sorry if this is a dumb question. I have a program that repeatedly allocates medium sized blocks (around 2KB~2MB) consecutively for 3 minutes, and roughly all blocks are discarded seconds after allocation. The libgc runtime still prompts the error.

Too many heap sections: Increase MAXHINCR or MAX_HEAP_SECTS

I manually increased those values in gc_priv.h. However, the issue still persists.

I tried both master and ubuntu distribution libgc-8.0.6 with apt source libgc-dev on ubuntu-WSL2. Here're the relevant changes and information about the built shared object.

Changes:

~/y/bdwgc (master|✚1) $ grep -rIn "define MAX_HEAP_SECTS" . ../libgc-8.0.6/
./include/private/gc_priv.h:1277:#     define MAX_HEAP_SECTS 8192000000
./include/private/gc_priv.h:1279:#     define MAX_HEAP_SECTS 7680000000
./include/private/gc_priv.h:1283:#     define MAX_HEAP_SECTS 38400000
./include/private/gc_priv.h:1285:#     define MAX_HEAP_SECTS 12800000         /* Roughly 256 MB (128*2048*1024) */
./include/private/gc_priv.h:1288:#   define MAX_HEAP_SECTS 102400000 		/* Roughly 8 GB */
./include/private/gc_priv.h:1290:#   define MAX_HEAP_SECTS 51200000           /* Roughly 4 GB */
../libgc-8.0.6/include/private/gc_priv.h:1204:#     define MAX_HEAP_SECTS 81920000
../libgc-8.0.6/include/private/gc_priv.h:1206:#     define MAX_HEAP_SECTS 76800000
../libgc-8.0.6/include/private/gc_priv.h:1210:#     define MAX_HEAP_SECTS 38400000
../libgc-8.0.6/include/private/gc_priv.h:1212:#     define MAX_HEAP_SECTS 12800000         /* Roughly 256MB (128*2048*1K)  */
../libgc-8.0.6/include/private/gc_priv.h:1215:#   define MAX_HEAP_SECTS 102400000          /* Roughly 8GB                  */
../libgc-8.0.6/include/private/gc_priv.h:1217:#   define MAX_HEAP_SECTS 51200000           /* Roughly 4GB                  */ 
~/y/bdwgc (master|✚1) $ grep -rIn "define MAXHINCR" . ../libgc-8.0.6/
./include/private/gc_priv.h:413:#   define MAXHINCR 409600
./include/private/gc_priv.h:417:#   define MAXHINCR 2048 /* Maximum heap increment, in blocks.  */
../libgc-8.0.6/include/private/gc_priv.h:383:#   define MAXHINCR 2048000 /* Maximum heap increment, in blocks              */
../libgc-8.0.6/include/private/gc_priv.h:386:#   define MAXHINCR 4096000                                                                                          

SO BSS information:

~/y/bdwgc (master|✚1) $ nm --print-size -D --size-sort -B ./.libs/libgc.so | grep B
0000000000103370 0000000000000004 B GC_dont_expand
0000000000030920 0000000000000004 B GC_dont_gc
000000000003091c 0000000000000004 B GC_dont_precollect
0000000000030910 0000000000000004 B GC_finalize_on_demand
0000000000030914 0000000000000004 B GC_find_leak
000000000010378c 0000000000000004 B GC_gcj_debug_kind
0000000000103790 0000000000000004 B GC_gcj_kind
0000000000103340 0000000000000004 B GC_no_dls
0000000000103374 0000000000000004 B GC_parallel
0000000000103788 0000000000000004 B GC_use_entire_heap
0000000000030908 0000000000000008 B GC_finalizer_notifier
0000000000103378 0000000000000008 B GC_gc_no
0000000000103358 0000000000000008 B GC_greatest_plausible_heap_addr
0000000000103350 0000000000000008 B GC_max_retries
0000000000103380 0000000000000008 B GC_non_gc_bytes
0000000000103360 0000000000000008 B GC_on_heap_resize
0000000000030928 0000000000000008 B GC_stackbottom
0000000000030940 00000000000d2a00 B GC_arrays
                                                                                                                                                                                                                                                   
~/y/bdwgc (master|✚1) $ nm --print-size -D --size-sort -B ../libgc-8.0.6/.libs/libgc.so | grep B
000000004e303fc8 0000000000000004 B GC_dont_expand
000000000003120c 0000000000000004 B GC_dont_gc
0000000000031208 0000000000000004 B GC_dont_precollect
00000000000311f0 0000000000000004 B GC_finalize_on_demand
00000000000311f4 0000000000000004 B GC_find_leak
000000004e304400 0000000000000004 B GC_gcj_debug_kind
000000004e304404 0000000000000004 B GC_gcj_kind
000000004e303da8 0000000000000004 B GC_no_dls
000000004e303fdc 0000000000000004 B GC_parallel
000000004e3043e8 0000000000000004 B GC_use_entire_heap
00000000000311e8 0000000000000008 B GC_finalizer_notifier
000000004e303fe0 0000000000000008 B GC_gc_no
000000004e303f78 0000000000000008 B GC_greatest_plausible_heap_addr
000000004e303f68 0000000000000008 B GC_max_retries
000000004e303fe8 0000000000000008 B GC_non_gc_bytes
000000004e303f88 0000000000000008 B GC_on_heap_resize
0000000000031210 0000000000000008 B GC_stackbottom
0000000000031220 000000004e2d28f0 B GC_arrays

I have also tried incrementing MAX_HEAP_SECTS but not MAXHINCR, and nothing works.

I also tried to set the enviroment variable, which fails.

~/y/bdwgc (master|✚1) $ env | grep GC
GC_MAXIMUM_HEAP_SIZE=68719476736

I greatly appreciate any suggestions on working around this issue.

UltimatePea avatar Jan 08 '24 04:01 UltimatePea

I just realized this solution https://github.com/NixOS/hydra/issues/549 that I did not try. I am trying it.

UltimatePea avatar Jan 08 '24 05:01 UltimatePea

Okay, I see you've found a workaround. But let's keep the issue open - the proper way, I think, is to remove MAX_HEAP_SECTS constant usage in bdwgc.

ivmai avatar Jan 08 '24 21:01 ivmai

Related issue (closed): #143

ivmai avatar Jan 08 '24 21:01 ivmai

I just realized this solution https://github.com/NixOS/hydra/issues/549 that I did not try. I am trying it.

This workaround actually does not work once the memory required exceeds a certain threshold (e.g. 100GB). The proper workaround is to rewrite the program to reduce the number of allocations.

UltimatePea avatar Jan 08 '24 21:01 UltimatePea

The workaround also requires grouping allocations together to prevent fragmentation. For example, if the following allocation sequences are repeated:

[ 8 bytes, 1 Kb, 8 bytes, 1 Kb, 1 Kb, 8 bytes, 1 Kb, 1 Kb ...]

where only the 8 bytes allocation are retained and all 1Kb allocations are set for gc, then the collector will error out very easily.

This problem is actually very severe, in my case, the program crashes with only a 8 GB heap. Will continue to investigate a workaround.

UltimatePea avatar Jan 09 '24 04:01 UltimatePea