MPS issue job003845

TitleLarge arena grain sizes cause massive AMC fragmentation
Statusclosed
Priorityessential
Assigned userGareth Rees
OrganizationRavenbrook
DescriptionOn Windows (w3i6mv), the test case

    gcbench -a 16384 amc

runs fine, but

    gcbench -a 32768 amc

fails in VMMap: in particular, the call to VirtualAlloc fails. Running GetLastError shows that the problem is "The paging file is too small for this operation to complete."
AnalysisWindows Task Manager shows that memory usage spiking when the grain size is 32768, but not when the grain size is 16384. Turning on MPS_TELEMETRY_CONTROL="Arena Seg" and looking at VMMap events (and thence SegAlloc and ArenaAlloc events), it seems that when the grain size is 32768, every object allocated by AMC is getting its own segment. Why is that?

The problem is here in config.h:

    /* AMC treats segments larger than this as "Large" */
    #define AMC_LARGE_SIZE_DEFAULT ((Size)32768)

Problem 1: The comment is incorrect. In fact, AMC treats segments larger than *or equal to* this as large.

Problem 2: The "large segment" determination is based on the segment size (which is rounded up to a multiple of the arena grain size), not the original object size.

Problem 3: Therefore, when the arena grain size is at least this big, every AMC segment is large.

Problem 4: Moreover, when the allocation clock is updated in BufferAttach, it only accounts for the original object size and not for the whole (padded out) segment. This is inconsistent with the normal case where the padding object at the end of the segment counts towards the allocation clock.

Solution: (1) fix the comment; (2) do the large segment determination based on the object request size, not the rounded up size; (3) don't do anything here: we want to preserve the possibility of handling large objects independently of large segments (add a TODO); (4) leave it as it is at the moment and make job003847 to consider the problem of accounting for overheads in the allocation clock.

Why didn't we find this?

(1) The automated test cases don't allocate big enough virtual memory arenas to be able to try such a large grain size. (The grain size in rnd_grain is constrained by the need to have a full complement of zones in each chunk.) We need test cases that have a wider range of arena sizes.

(2) The inspection of branch/2014-06-10/amc-extend-by was based on diffs [1] which don't show the crucial feature (that in the "large" case a small buffer is returned and the remainder of the segment padded). So the connection was not made.

(3) In some sense I did find it: I discovered that the amcss test case was failing with a large grain size but I didn't investigate further, I just reduced the grain size until the test cases passed (see change 186697 [2]).
How foundmanual_test
Evidence[1] <https://info.ravenbrook.com/infosys/cgi/perfbrowse.cgi?@describe+186584>
[2] <https://info.ravenbrook.com/infosys/cgi/perfbrowse.cgi?@describe+186697>
Created byGareth Rees
Created on2014-06-20 14:27:18
Last modified byGareth Rees
Last modified on2014-06-30 16:09:53
History2014-06-20 GDR Created.

Fixes

Change Effect Date User Description
186755 closed 2014-06-30 16:07:09 Gareth Rees Ensure that the amcss test case uses a wide range of arena grain sizes (by scaling up the whole allocation).
Remove hack from rnd_grain -- this was covering up a bug.
Base the AMC "large" segment determination on the requested object size, not the (rounded up) segment size.
Assert in the case where largeSize < extendBy: this has bad space performance.