Skip to content

Commit 00742d2

Browse files
author
Ico Doornekamp
committed
Added 'getAllocStats()' to get low level alloc/dealloc counters. Enable with -d:allocStats
1 parent 38c5712 commit 00742d2

12 files changed

+165
-90
lines changed

lib/system/alloc.nim

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1002,19 +1002,19 @@ template instantiateForRegion(allocator: untyped) {.dirty.} =
10021002
10031003
proc deallocOsPages = deallocOsPages(allocator)
10041004
1005-
proc alloc(size: Natural): pointer =
1005+
proc allocImpl(size: Natural): pointer =
10061006
result = alloc(allocator, size)
10071007
1008-
proc alloc0(size: Natural): pointer =
1008+
proc alloc0Impl(size: Natural): pointer =
10091009
result = alloc0(allocator, size)
10101010
1011-
proc dealloc(p: pointer) =
1011+
proc deallocImpl(p: pointer) =
10121012
dealloc(allocator, p)
10131013
1014-
proc realloc(p: pointer, newSize: Natural): pointer =
1014+
proc reallocImpl(p: pointer, newSize: Natural): pointer =
10151015
result = realloc(allocator, p, newSize)
10161016
1017-
proc realloc0(p: pointer, oldSize, newSize: Natural): pointer =
1017+
proc realloc0Impl(p: pointer, oldSize, newSize: Natural): pointer =
10181018
result = realloc(allocator, p, newSize)
10191019
if newSize > oldSize:
10201020
zeroMem(cast[pointer](cast[int](result) + oldSize), newSize - oldSize)
@@ -1044,35 +1044,35 @@ template instantiateForRegion(allocator: untyped) {.dirty.} =
10441044
var heapLock: SysLock
10451045
initSysLock(heapLock)
10461046
1047-
proc allocShared(size: Natural): pointer =
1047+
proc allocSharedImpl(size: Natural): pointer =
10481048
when hasThreadSupport:
10491049
acquireSys(heapLock)
10501050
result = alloc(sharedHeap, size)
10511051
releaseSys(heapLock)
10521052
else:
10531053
result = alloc(size)
10541054
1055-
proc allocShared0(size: Natural): pointer =
1055+
proc allocShared0Impl(size: Natural): pointer =
10561056
result = allocShared(size)
10571057
zeroMem(result, size)
10581058
1059-
proc deallocShared(p: pointer) =
1059+
proc deallocSharedImpl(p: pointer) =
10601060
when hasThreadSupport:
10611061
acquireSys(heapLock)
10621062
dealloc(sharedHeap, p)
10631063
releaseSys(heapLock)
10641064
else:
10651065
dealloc(p)
10661066
1067-
proc reallocShared(p: pointer, newSize: Natural): pointer =
1067+
proc reallocSharedImpl(p: pointer, newSize: Natural): pointer =
10681068
when hasThreadSupport:
10691069
acquireSys(heapLock)
10701070
result = realloc(sharedHeap, p, newSize)
10711071
releaseSys(heapLock)
10721072
else:
10731073
result = realloc(p, newSize)
10741074
1075-
proc reallocShared0(p: pointer, oldSize, newSize: Natural): pointer =
1075+
proc reallocShared0Impl(p: pointer, oldSize, newSize: Natural): pointer =
10761076
when hasThreadSupport:
10771077
acquireSys(heapLock)
10781078
result = realloc0(sharedHeap, p, oldSize, newSize)

lib/system/gc_regions.nim

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -377,21 +377,21 @@ proc asgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
377377
proc asgnRefNoCycle(dest: PPointer, src: pointer) {.compilerproc, inline,
378378
deprecated: "old compiler compat".} = asgnRef(dest, src)
379379
380-
proc alloc(size: Natural): pointer =
380+
proc allocImpl(size: Natural): pointer =
381381
result = c_malloc(cast[csize_t](size))
382382
if result == nil: raiseOutOfMem()
383-
proc alloc0(size: Natural): pointer =
383+
proc alloc0Impl(size: Natural): pointer =
384384
result = alloc(size)
385385
zeroMem(result, size)
386-
proc realloc(p: pointer, newsize: Natural): pointer =
386+
proc reallocImpl(p: pointer, newsize: Natural): pointer =
387387
result = c_realloc(p, cast[csize_t](newsize))
388388
if result == nil: raiseOutOfMem()
389-
proc realloc0(p: pointer, oldsize, newsize: Natural): pointer =
389+
proc realloc0Impl(p: pointer, oldsize, newsize: Natural): pointer =
390390
result = c_realloc(p, cast[csize_t](newsize))
391391
if result == nil: raiseOutOfMem()
392392
if newsize > oldsize:
393393
zeroMem(cast[pointer](cast[int](result) + oldsize), newsize - oldsize)
394-
proc dealloc(p: pointer) = c_free(p)
394+
proc deallocImpl(p: pointer) = c_free(p)
395395
396396
proc alloc0(r: var MemRegion; size: Natural): pointer =
397397
# ignore the region. That is correct for the channels module
@@ -405,21 +405,21 @@ proc alloc(r: var MemRegion; size: Natural): pointer =
405405
406406
proc dealloc(r: var MemRegion; p: pointer) = dealloc(p)
407407
408-
proc allocShared(size: Natural): pointer =
408+
proc allocSharedImpl(size: Natural): pointer =
409409
result = c_malloc(cast[csize_t](size))
410410
if result == nil: raiseOutOfMem()
411-
proc allocShared0(size: Natural): pointer =
411+
proc allocShared0Impl(size: Natural): pointer =
412412
result = alloc(size)
413413
zeroMem(result, size)
414-
proc reallocShared(p: pointer, newsize: Natural): pointer =
414+
proc reallocSharedImpl(p: pointer, newsize: Natural): pointer =
415415
result = c_realloc(p, cast[csize_t](newsize))
416416
if result == nil: raiseOutOfMem()
417-
proc reallocShared0(p: pointer, oldsize, newsize: Natural): pointer =
417+
proc reallocShared0Impl(p: pointer, oldsize, newsize: Natural): pointer =
418418
result = c_realloc(p, cast[csize_t](newsize))
419419
if result == nil: raiseOutOfMem()
420420
if newsize > oldsize:
421421
zeroMem(cast[pointer](cast[int](result) + oldsize), newsize - oldsize)
422-
proc deallocShared(p: pointer) = c_free(p)
422+
proc deallocSharedImpl(p: pointer) = c_free(p)
423423
424424
when hasThreadSupport:
425425
proc getFreeSharedMem(): int = 0

lib/system/memalloc.nim

Lines changed: 77 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,48 @@ when notJSnotNims:
3333
## otherwise. Like any procedure dealing with raw memory this is
3434
## **unsafe**.
3535

36-
when hasAlloc:
37-
proc alloc*(size: Natural): pointer {.noconv, rtl, tags: [], benign, raises: [].}
36+
when hasAlloc and not defined(js):
37+
38+
proc allocImpl*(size: Natural): pointer {.noconv, rtl, tags: [], benign, raises: [].}
39+
proc alloc0Impl*(size: Natural): pointer {.noconv, rtl, tags: [], benign, raises: [].}
40+
proc deallocImpl*(p: pointer) {.noconv, rtl, tags: [], benign, raises: [].}
41+
proc reallocImpl*(p: pointer, newSize: Natural): pointer {.noconv, rtl, tags: [], benign, raises: [].}
42+
proc realloc0Impl*(p: pointer, oldSize, newSize: Natural): pointer {.noconv, rtl, tags: [], benign, raises: [].}
43+
44+
proc allocSharedImpl*(size: Natural): pointer {.noconv, compilerproc, rtl, benign, raises: [], tags: [].}
45+
proc allocShared0Impl*(size: Natural): pointer {.noconv, rtl, benign, raises: [], tags: [].}
46+
proc deallocSharedImpl*(p: pointer) {.noconv, rtl, benign, raises: [], tags: [].}
47+
proc reallocSharedImpl*(p: pointer, newSize: Natural): pointer {.noconv, rtl, tags: [], benign, raises: [].}
48+
proc reallocShared0Impl*(p: pointer, oldSize, newSize: Natural): pointer {.noconv, rtl, tags: [], benign, raises: [].}
49+
50+
# Allocator statistics for memory leak tests
51+
52+
{.push stackTrace: off.}
53+
54+
type AllocStats* = object
55+
allocCount: int
56+
deallocCount: int
57+
58+
proc `-`*(a, b: AllocStats): AllocStats =
59+
result.allocCount = a.allocCount - b.allocCount
60+
result.deallocCount = a.deallocCount - b.deallocCount
61+
62+
template dumpAllocstats*(code: untyped) =
63+
let stats1 = getAllocStats()
64+
code
65+
let stats2 = getAllocStats()
66+
echo $(stats2 - stats1)
67+
68+
when defined(allocStats):
69+
var stats: AllocStats
70+
template incStat(what: untyped) = inc stats.what
71+
proc getAllocStats*(): AllocStats = stats
72+
73+
else:
74+
template incStat(what: untyped) = discard
75+
proc getAllocStats*(): AllocStats = discard
76+
77+
template alloc*(size: Natural): pointer =
3878
## Allocates a new memory block with at least ``size`` bytes.
3979
##
4080
## The block has to be freed with `realloc(block, 0) <#realloc,pointer,Natural>`_
@@ -47,6 +87,9 @@ when hasAlloc:
4787
##
4888
## See also:
4989
## * `alloc0 <#alloc0,Natural>`_
90+
incStat(allocCount)
91+
allocImpl(size)
92+
5093
proc createU*(T: typedesc, size = 1.Positive): ptr T {.inline, benign, raises: [].} =
5194
## Allocates a new memory block with at least ``T.sizeof * size`` bytes.
5295
##
@@ -62,7 +105,7 @@ when hasAlloc:
62105
## * `create <#create,typedesc>`_
63106
cast[ptr T](alloc(T.sizeof * size))
64107
65-
proc alloc0*(size: Natural): pointer {.noconv, rtl, tags: [], benign, raises: [].}
108+
template alloc0*(size: Natural): pointer =
66109
## Allocates a new memory block with at least ``size`` bytes.
67110
##
68111
## The block has to be freed with `realloc(block, 0) <#realloc,pointer,Natural>`_
@@ -72,6 +115,9 @@ when hasAlloc:
72115
##
73116
## The allocated memory belongs to its allocating thread!
74117
## Use `allocShared0 <#allocShared0,Natural>`_ to allocate from a shared heap.
118+
incStat(allocCount)
119+
alloc0Impl(size)
120+
75121
proc create*(T: typedesc, size = 1.Positive): ptr T {.inline, benign, raises: [].} =
76122
## Allocates a new memory block with at least ``T.sizeof * size`` bytes.
77123
##
@@ -84,8 +130,7 @@ when hasAlloc:
84130
## Use `createShared <#createShared,typedesc>`_ to allocate from a shared heap.
85131
cast[ptr T](alloc0(sizeof(T) * size))
86132
87-
proc realloc*(p: pointer, newSize: Natural): pointer {.noconv, rtl, tags: [],
88-
benign, raises: [].}
133+
template realloc*(p: pointer, newSize: Natural): pointer =
89134
## Grows or shrinks a given memory block.
90135
##
91136
## If `p` is **nil** then a new memory block is returned.
@@ -97,8 +142,9 @@ when hasAlloc:
97142
## The allocated memory belongs to its allocating thread!
98143
## Use `reallocShared <#reallocShared,pointer,Natural>`_ to reallocate
99144
## from a shared heap.
100-
proc realloc0*(p: pointer, oldSize, newSize: Natural): pointer {.noconv, rtl, tags: [],
101-
benign, raises: [].}
145+
reallocImpl(p, newSize)
146+
147+
template realloc0*(p: pointer, oldSize, newSize: Natural): pointer =
102148
## Grows or shrinks a given memory block.
103149
##
104150
## If `p` is **nil** then a new memory block is returned.
@@ -113,6 +159,8 @@ when hasAlloc:
113159
## The allocated memory belongs to its allocating thread!
114160
## Use `reallocShared <#reallocShared,pointer,Natural>`_ to reallocate
115161
## from a shared heap.
162+
realloc0Impl(p, oldSize, newSize)
163+
116164
proc resize*[T](p: ptr T, newSize: Natural): ptr T {.inline, benign, raises: [].} =
117165
## Grows or shrinks a given memory block.
118166
##
@@ -126,7 +174,7 @@ when hasAlloc:
126174
## from a shared heap.
127175
cast[ptr T](realloc(p, T.sizeof * newSize))
128176
129-
proc dealloc*(p: pointer) {.noconv, rtl, tags: [], benign, raises: [].}
177+
template dealloc*(p: pointer) =
130178
## Frees the memory allocated with ``alloc``, ``alloc0`` or
131179
## ``realloc``.
132180
##
@@ -137,8 +185,10 @@ when hasAlloc:
137185
##
138186
## The freed memory must belong to its allocating thread!
139187
## Use `deallocShared <#deallocShared,pointer>`_ to deallocate from a shared heap.
188+
incStat(deallocCount)
189+
deallocImpl(p)
140190
141-
proc allocShared*(size: Natural): pointer {.noconv, compilerproc, rtl, benign, raises: [], tags: [].}
191+
template allocShared*(size: Natural): pointer =
142192
## Allocates a new memory block on the shared heap with at
143193
## least ``size`` bytes.
144194
##
@@ -151,6 +201,9 @@ when hasAlloc:
151201
##
152202
## See also:
153203
## `allocShared0 <#allocShared0,Natural>`_.
204+
incStat(allocCount)
205+
allocSharedImpl(size)
206+
154207
proc createSharedU*(T: typedesc, size = 1.Positive): ptr T {.inline, tags: [],
155208
benign, raises: [].} =
156209
## Allocates a new memory block on the shared heap with at
@@ -167,7 +220,7 @@ when hasAlloc:
167220
## * `createShared <#createShared,typedesc>`_
168221
cast[ptr T](allocShared(T.sizeof * size))
169222
170-
proc allocShared0*(size: Natural): pointer {.noconv, rtl, benign, raises: [], tags: [].}
223+
template allocShared0*(size: Natural): pointer =
171224
## Allocates a new memory block on the shared heap with at
172225
## least ``size`` bytes.
173226
##
@@ -178,6 +231,9 @@ when hasAlloc:
178231
## The block is initialized with all bytes
179232
## containing zero, so it is somewhat safer than
180233
## `allocShared <#allocShared,Natural>`_.
234+
incStat(allocCount)
235+
allocShared0Impl(size)
236+
181237
proc createShared*(T: typedesc, size = 1.Positive): ptr T {.inline.} =
182238
## Allocates a new memory block on the shared heap with at
183239
## least ``T.sizeof * size`` bytes.
@@ -191,8 +247,7 @@ when hasAlloc:
191247
## `createSharedU <#createSharedU,typedesc>`_.
192248
cast[ptr T](allocShared0(T.sizeof * size))
193249
194-
proc reallocShared*(p: pointer, newSize: Natural): pointer {.noconv, rtl, tags: [],
195-
benign, raises: [].}
250+
template reallocShared*(p: pointer, newSize: Natural): pointer =
196251
## Grows or shrinks a given memory block on the heap.
197252
##
198253
## If `p` is **nil** then a new memory block is returned.
@@ -201,8 +256,9 @@ when hasAlloc:
201256
## ``deallocShared(p)``.
202257
## In other cases the block has to be freed with
203258
## `deallocShared <#deallocShared,pointer>`_.
204-
proc reallocShared0*(p: pointer, oldSize, newSize: Natural): pointer {.noconv, rtl, tags: [],
205-
benign, raises: [].}
259+
reallocSharedImpl(p, newSize)
260+
261+
template reallocShared0*(p: pointer, oldSize, newSize: Natural): pointer =
206262
## Grows or shrinks a given memory block on the heap.
207263
##
208264
## When growing, the new bytes of the block is initialized with all bytes
@@ -214,6 +270,8 @@ when hasAlloc:
214270
## ``deallocShared(p)``.
215271
## In other cases the block has to be freed with
216272
## `deallocShared <#deallocShared,pointer>`_.
273+
reallocShared0Impl(p, oldSize, newSize)
274+
217275
proc resizeShared*[T](p: ptr T, newSize: Natural): ptr T {.inline, raises: [].} =
218276
## Grows or shrinks a given memory block on the heap.
219277
##
@@ -225,14 +283,17 @@ when hasAlloc:
225283
## `freeShared <#freeShared,ptr.T>`_.
226284
cast[ptr T](reallocShared(p, T.sizeof * newSize))
227285
228-
proc deallocShared*(p: pointer) {.noconv, compilerproc, rtl, benign, raises: [], tags: [].}
286+
proc deallocShared*(p: pointer) {.noconv, compilerproc, rtl, benign, raises: [], tags: [].} =
229287
## Frees the memory allocated with ``allocShared``, ``allocShared0`` or
230288
## ``reallocShared``.
231289
##
232290
## **This procedure is dangerous!**
233291
## If one forgets to free the memory a leak occurs; if one tries to
234292
## access freed memory (or just freeing it twice!) a core dump may happen
235293
## or other memory may be corrupted.
294+
incStat(deallocCount)
295+
deallocSharedImpl(p)
296+
236297
proc freeShared*[T](p: ptr T) {.inline, benign, raises: [].} =
237298
## Frees the memory allocated with ``createShared``, ``createSharedU`` or
238299
## ``resizeShared``.
@@ -243,6 +304,7 @@ when hasAlloc:
243304
## or other memory may be corrupted.
244305
deallocShared(p)
245306
307+
{.pop.}
246308
247309
# GC interface:
248310

0 commit comments

Comments
 (0)