Closed lilkeet closed 2 weeks ago
Here's valgrind's output on above example when nim is passed -d:useMalloc
and the mm scheme is orc.
HEAP SUMMARY:
in use at exit: 16,161,616 bytes in 1,010,101 blocks
total heap usage: 5,055,657 allocs, 4,045,556 frees, 187,586,304 bytes allocated
Searching for pointers to 1,010,101 not-freed blocks
Checked 108,560 bytes
16 bytes in 1 blocks are still reachable in loss record 1 of 2
at 0x4846828: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
by 0x10AFC8: allocImpl__system_u1742 (in /path/to/mainmodule)
by 0x10AFEE: allocSharedImpl (in /path/to/mainmodule)
by 0x10DD04: alignedAlloc__system_u1882 (in /path/to/mainmodule)
by 0x10E014: newSeqPayloadUninit (in /path/to/mainmodule)
by 0x10E28C: prepareSeqAddUninit (in /path/to/mainmodule)
by 0x1125A9: setLen__mainmodule_u129 (in /path/to/mainmodule)
by 0x11369A: eqdup___mainmodule_u115 (in /path/to/mainmodule)
by 0x114E11: innerTestTotalMemmyPairsInline__mainmodule_u451 (in /path/to/mainmodule)
by 0x11534F: main__mainmodule_u20 (in /path/to/mainmodule)
by 0x115592: NimMainModule (in /path/to/mainmodule)
by 0x1154CA: NimMainInner (in /path/to/mainmodule)
16,161,600 bytes in 1,010,100 blocks are definitely lost in loss record 2 of 2
at 0x4846828: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
by 0x10AFC8: allocImpl__system_u1742 (in /path/to/mainmodule)
by 0x10AFEE: allocSharedImpl (in /path/to/mainmodule)
by 0x10DD04: alignedAlloc__system_u1882 (in /path/to/mainmodule)
by 0x10E014: newSeqPayloadUninit (in /path/to/mainmodule)
by 0x10E28C: prepareSeqAddUninit (in /path/to/mainmodule)
by 0x1125A9: setLen__mainmodule_u129 (in /path/to/mainmodule)
by 0x11369A: eqdup___mainmodule_u115 (in /path/to/mainmodule)
by 0x114E11: innerTestTotalMemmyPairsInline__mainmodule_u451 (in /path/to/mainmodule)
by 0x11534F: main__mainmodule_u20 (in /path/to/mainmodule)
by 0x115592: NimMainModule (in /path/to/mainmodule)
by 0x1154CA: NimMainInner (in /path/to/mainmodule)
LEAK SUMMARY:
definitely lost: 16,161,600 bytes in 1,010,100 blocks
indirectly lost: 0 bytes in 0 blocks
possibly lost: 0 bytes in 0 blocks
still reachable: 16 bytes in 1 blocks
of which reachable via heuristic:
newarray : 16 bytes in 1 blocks
suppressed: 0 bytes in 0 blocks
ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
!nim c --gc:orc
iterator myPairsInline*[T](twoDarray: seq[seq[T]]): (int, seq[T]) {.inline.} =
for indexValuePair in twoDarray.pairs:
yield indexValuePair
iterator myPairsClosure*[T](twoDarray: seq[seq[T]]): (int, seq[T]) {.closure.} =
for indexValuePair in twoDarray.pairs:
yield indexValuePair
template testTotalMem(iter: untyped): int =
proc innerTestTotalMem(): int {.gensym.} =
result = 0
# do the same operation 100 times, which should have similar mem footprint
# as doing it once.
for iterNum in 0..100:
result = max(result, getTotalMem()) # record current mem footprint
# initialize nested sequence
var my2dArray: seq[seq[int32]] = @[]
# fill with some data...
for i in 0'i32..10_000:
var z = @[i, i+1]
my2dArray.add z
# use that data somehow...
var otherContainer: seq[int32] = @[]
var count = 0'i32
for oneDindex, innerArray in my2dArray.iter:
for value in innerArray:
inc count
if oneDindex > 50 and value < 200:
otherContainer.add count
innerTestTotalMem()
proc main =
let closureMem = testTotalMem(myPairsClosure) #1052672
let inlineMem = testTotalMem(myPairsInline) #20328448
when defined(echoFootprint):
echo "Closure memory footprint: " & $closureMem
echo "Inline memory footprint: " & $inlineMem
# check that mem footprint is relatively similar b/t each method
doAssert (closureMem - inlineMem).abs < (closureMem div 10)
main()
!nim c --gc:orc -d:useMalloc
iterator myPairsInline*[T](twoDarray: seq[seq[T]]): (int, seq[T]) {.inline.} =
for indexValuePair in twoDarray.pairs:
yield indexValuePair
iterator myPairsClosure*[T](twoDarray: seq[seq[T]]): (int, seq[T]) {.closure.} =
for indexValuePair in twoDarray.pairs:
yield indexValuePair
template testTotalMem(iter: untyped): int =
proc innerTestTotalMem(): int {.gensym.} =
result = 0
# do the same operation 100 times, which should have similar mem footprint
# as doing it once.
for iterNum in 0..100:
result = max(result, getTotalMem()) # record current mem footprint
# initialize nested sequence
var my2dArray: seq[seq[int32]] = @[]
# fill with some data...
for i in 0'i32..10_000:
var z = @[i, i+1]
my2dArray.add z
# use that data somehow...
var otherContainer: seq[int32] = @[]
var count = 0'i32
for oneDindex, innerArray in my2dArray.iter:
for value in innerArray:
inc count
if oneDindex > 50 and value < 200:
otherContainer.add count
innerTestTotalMem()
proc main =
let closureMem = testTotalMem(myPairsClosure) #1052672
let inlineMem = testTotalMem(myPairsInline) #20328448
when defined(echoFootprint):
echo "Closure memory footprint: " & $closureMem
echo "Inline memory footprint: " & $inlineMem
# check that mem footprint is relatively similar b/t each method
doAssert (closureMem - inlineMem).abs < (closureMem div 10)
main()
436.18 Kb (446,648 bytes)
Duration 24 mins
453.08 Kb (463,952 bytes)
Duration 23 mins
484.95 Kb (496,584 bytes)
Duration 24 mins
433.79 Kb (444,200 bytes)
Duration 24 mins
437.60 Kb (448,104 bytes)
Duration 22 mins
437.60 Kb (448,104 bytes)
Duration
437.60 Kb (448,104 bytes)
Duration
437.60 Kb (448,104 bytes)
Duration
11.4.0
14.0.0
20.4
2024-11-10T18:41:11Z
3
nim c --gc:orc -d:useMalloc -d:nimArcDebug -d:nimArcIds -d:nimAllocPagesViaMalloc -d:useSysAssert -d:useGcAssert -d:nimLeakDetector --debugger:native --debuginfo:on -d:nimDebug -d:nimDebugDlOpen -d:ssl -d:nimDisableCertificateValidation --forceBuild:on --colors:off --verbosity:0 --hints:off --lineTrace:off --nimcache:/home/runner/work/Nim/Nim --out:/home/runner/work/Nim/Nim/temp /home/runner/work/Nim/Nim/temp.nim && valgrind /home/runner/work/Nim/Nim/temp
:robot: Bug found in 42 mins
bisecting 8
commits at 0
commits per second
Description
On the arc, orc, and atomicArc mm's: Inline iterators that do not return a lent type leak memory when iterating upon nested sequences. Closures that do not return lent types and inlines that do return lent types do not leak.
Nim Version
Nim Compiler Version 2.2.0 [Linux: amd64]
Current Output
Expected Output
No response
Known Workarounds
No response
Additional Information
The regions gc/mm scheme is the only other gc that fails this example.