diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2020-12-05 23:15:17 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-12-05 23:15:17 +0100 |
commit | af7f7726fe727b68238533f690fb7cd98552e4e4 (patch) | |
tree | e0621ef74aa7cbdb554637185d45149f3d1727b2 | |
parent | 70d4df051648771269251cca8b4a6aa32ae636d0 (diff) | |
download | Nim-af7f7726fe727b68238533f690fb7cd98552e4e4.tar.gz |
ORC: make the adaptive strategy the default in order to fight memory consumption (#16250)
* ORC: make the adaptive strategy the default in order to fight memory consumption * added missing test case
-rw-r--r-- | lib/system/orc.nim | 19 | ||||
-rw-r--r-- | tests/arc/tasyncleak.nim | 2 | ||||
-rw-r--r-- | tests/arc/torcbench.nim | 38 |
3 files changed, 52 insertions, 7 deletions
diff --git a/lib/system/orc.nim b/lib/system/orc.nim index 4bd8952b7..803f3d410 100644 --- a/lib/system/orc.nim +++ b/lib/system/orc.nim @@ -39,7 +39,8 @@ template setColor(c, col) = c.rc = c.rc and not colorMask or col const - optimizedOrc = not defined(nimOldOrc) + optimizedOrc = false # not defined(nimOldOrc) +# XXX Still incorrect, see tests/arc/tdestroy_in_loopcond proc nimIncRefCyclic(p: pointer; cyclic: bool) {.compilerRtl, inl.} = let h = head(p) @@ -72,6 +73,7 @@ type jumpStack: CellSeq # Lins' jump stack in order to speed up traversals toFree: CellSeq freed, touched, edges, rcSum: int + keepThreshold: bool proc trace(s: Cell; desc: PNimTypeV2; j: var GcEnv) {.inline.} = if desc.traceImpl != nil: @@ -309,6 +311,8 @@ proc collectCyclesBacon(j: var GcEnv; lowMark: int) = if j.rcSum == j.edges: # short-cut: we know everything is garbage: colToCollect = colGray + # remember the fact that we got so lucky: + j.keepThreshold = true else: for i in countdown(last, lowMark): scan(roots.d[i][0], roots.d[i][1], j) @@ -327,7 +331,7 @@ proc collectCyclesBacon(j: var GcEnv; lowMark: int) = #roots.len = 0 const - defaultThreshold = when defined(nimAdaptiveOrc): 128 else: 10_000 + defaultThreshold = when defined(nimFixedOrc): 10_000 else: 128 when defined(nimStressOrc): const rootsThreshold = 10 # broken with -d:nimStressOrc: 10 and for havlak iterations 1..8 @@ -335,7 +339,8 @@ else: var rootsThreshold = defaultThreshold proc partialCollect(lowMark: int) = - if roots.len < 10 + lowMark: return + when false: + if roots.len < 10 + lowMark: return when logOrc: cfprintf(cstderr, "[partialCollect] begin\n") var j: GcEnv @@ -373,9 +378,11 @@ proc collectCycles() = # of the cycle collector's effectiveness: # we're effective when we collected 50% or more of the nodes # we touched. If we're effective, we can reset the threshold: - if j.freed * 2 >= j.touched: - when defined(nimAdaptiveOrc): - rootsThreshold = max(rootsThreshold div 2, 16) + if j.keepThreshold and rootsThreshold <= defaultThreshold: + discard + elif j.freed * 2 >= j.touched: + when not defined(nimFixedOrc): + rootsThreshold = max(rootsThreshold div 3 * 2, 16) else: rootsThreshold = defaultThreshold #cfprintf(cstderr, "[collectCycles] freed %ld, touched %ld new threshold %ld\n", j.freed, j.touched, rootsThreshold) diff --git a/tests/arc/tasyncleak.nim b/tests/arc/tasyncleak.nim index 417b67edb..eb0c45213 100644 --- a/tests/arc/tasyncleak.nim +++ b/tests/arc/tasyncleak.nim @@ -1,5 +1,5 @@ discard """ - outputsub: "(allocCount: 4014, deallocCount: 4012)" + outputsub: "(allocCount: 4302, deallocCount: 4300)" cmd: "nim c --gc:orc -d:nimAllocStats $file" """ diff --git a/tests/arc/torcbench.nim b/tests/arc/torcbench.nim new file mode 100644 index 000000000..4c9e65fee --- /dev/null +++ b/tests/arc/torcbench.nim @@ -0,0 +1,38 @@ +discard """ + output: '''true peak memory: true''' + cmd: "nim c --gc:orc -d:release $file" +""" + +import lists, strutils, times + +type + Base = ref object of RootObj + + Node = ref object of Base + parent: DoublyLinkedList[string] + le, ri: Node + self: Node # in order to create a cycle + +proc buildTree(parent: DoublyLinkedList[string]; depth: int): Node = + if depth == 0: + result = nil + elif depth == 1: + result = Node(parent: parent, le: nil, ri: nil, self: nil) + when not defined(gcArc): + result.self = result + else: + result = Node(parent: parent, le: buildTree(parent, depth - 1), ri: buildTree(parent, depth - 2), self: nil) + result.self = result + +proc main() = + for i in countup(1, 100): + var leakList = initDoublyLinkedList[string]() + for j in countup(1, 5000): + leakList.append(newString(200)) + #GC_fullCollect() + for i in 0..400: + discard buildTree(leakList, 8) + +main() +GC_fullCollect() +echo getOccupiedMem() < 10 * 1024 * 1024, " peak memory: ", getMaxMem() < 10 * 1024 * 1024 |