-
Notifications
You must be signed in to change notification settings - Fork 18.4k
Description
Here is repro program:
http://play.golang.org/p/giKY6IcWjU
If you run it as-is, it runs for 1.357s and profile looks as:
21.94% test test [.] runtime.memclr
12.24% test test [.] runtime.MSpanList_IsEmpty
11.02% test test [.] runtime.xchg
7.94% test test [.] MHeap_AllocLocked
5.19% test test [.] runtime.MSpan_Sweep
If you uncomment "y = make([]byte, 1<<30)" line, it runs for 26.696s and profile looks as:
37.52% test test [.] runtime.sweepone
27.15% test test [.] runtime.xadd
24.96% test test [.] markroot
1.96% test test [.] runtime.memclr
0.75% test test [.] runtime.xchg
The problem is that the program creates 131221 spans when the live set is 1GB and the heap grows to 2GB. Later the live set drops to 1MB and GCs become very frequent, but each GC has to iterate over all of 131221 spans in sweepone and markroot. The total time spent in span handling becomes 90%.
This was reported on golang-nuts:
https://groups.google.com/forum/#!topic/golang-nuts/-Dq4WkivD2E
We need to either (1) re-partition allspans so that we don't iterate over the dead part, or (2) remove and deallocate dead spans from allspans after some time of inactivity.