diff options
author | Araq <rumpf_a@web.de> | 2012-10-10 00:41:34 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2012-10-10 00:41:34 +0200 |
commit | d43febf81e78ac79894ab136717c6100a5492b08 (patch) | |
tree | 451569132c56fb42c39313f81e7a8e895fff6376 /lib/system | |
parent | cf06131decb2d46304874bd243c29267876e0076 (diff) | |
download | Nim-d43febf81e78ac79894ab136717c6100a5492b08.tar.gz |
first version of a memory profiler
Diffstat (limited to 'lib/system')
-rwxr-xr-x | lib/system/gc.nim | 13 | ||||
-rwxr-xr-x | lib/system/profiler.nim | 69 |
2 files changed, 54 insertions, 28 deletions
diff --git a/lib/system/gc.nim b/lib/system/gc.nim index a95319e51..ec656e0ef 100755 --- a/lib/system/gc.nim +++ b/lib/system/gc.nim @@ -28,6 +28,8 @@ const when withRealTime and not defined(getTicks): include "system/timers" +when defined(memProfiler): + proc nimProfile(requestedSize: int) const rcIncrement = 0b1000 # so that lowest 3 bits are not touched @@ -431,12 +433,15 @@ proc rawNewObj(typ: PNimType, size: int, gch: var TGcHeap): pointer = proc newObj(typ: PNimType, size: int): pointer {.compilerRtl.} = result = rawNewObj(typ, size, gch) zeroMem(result, size) + when defined(memProfiler): nimProfile(size) proc newSeq(typ: PNimType, len: int): pointer {.compilerRtl.} = # `newObj` already uses locks, so no need for them here. - result = newObj(typ, addInt(mulInt(len, typ.base.size), GenericSeqSize)) + let size = addInt(mulInt(len, typ.base.size), GenericSeqSize) + result = newObj(typ, size) cast[PGenericSeq](result).len = len cast[PGenericSeq](result).reserved = len + when defined(memProfiler): nimProfile(size) proc newObjRC1(typ: PNimType, size: int): pointer {.compilerRtl.} = # generates a new object and sets its reference counter to 1 @@ -463,11 +468,14 @@ proc newObjRC1(typ: PNimType, size: int): pointer {.compilerRtl.} = result = cellToUsr(res) zeroMem(result, size) sysAssert(allocInv(gch.region), "newObjRC1 end") + when defined(memProfiler): nimProfile(size) proc newSeqRC1(typ: PNimType, len: int): pointer {.compilerRtl.} = - result = newObjRC1(typ, addInt(mulInt(len, typ.base.size), GenericSeqSize)) + let size = addInt(mulInt(len, typ.base.size), GenericSeqSize) + result = newObjRC1(typ, size) cast[PGenericSeq](result).len = len cast[PGenericSeq](result).reserved = len + when defined(memProfiler): nimProfile(size) proc growObj(old: pointer, newsize: int, gch: var TGcHeap): pointer = acquire(gch) @@ -512,6 +520,7 @@ proc growObj(old: pointer, newsize: int, gch: var TGcHeap): pointer = release(gch) result = cellToUsr(res) sysAssert(allocInv(gch.region), "growObj end") + when defined(memProfiler): nimProfile(newsize-oldsize) proc growObj(old: pointer, newsize: int): pointer {.rtl.} = result = growObj(old, newsize, gch) diff --git a/lib/system/profiler.nim b/lib/system/profiler.nim index eafa010ef..8e4c51dd9 100755 --- a/lib/system/profiler.nim +++ b/lib/system/profiler.nim @@ -49,34 +49,51 @@ proc captureStackTrace(f: PFrame, st: var TStackTrace) = inc(i) b = b.prev -const - SamplingInterval = 50_000 - # set this to change the default sampling interval -var - profilerHook*: TProfilerHook - ## set this variable to provide a procedure that implements a profiler in - ## user space. See the `nimprof` module for a reference implementation. - gTicker {.threadvar.}: int +when defined(memProfiler): + type + TMemProfilerHook* = proc (st: TStackTrace, requestedSize: int) {.nimcall.} + var + profilerHook*: TMemProfilerHook + ## set this variable to provide a procedure that implements a profiler in + ## user space. See the `nimprof` module for a reference implementation. -proc callProfilerHook(hook: TProfilerHook) {.noinline.} = - # 'noinline' so that 'nimProfile' does not perform the stack allocation - # in the common case. - var st: TStackTrace - captureStackTrace(framePtr, st) - hook(st) + proc callProfilerHook(hook: TMemProfilerHook, requestedSize: int) = + var st: TStackTrace + captureStackTrace(framePtr, st) + hook(st, requestedSize) -proc nimProfile() = - ## This is invoked by the compiler in every loop and on every proc entry! - if gTicker == 0: - gTicker = -1 + proc nimProfile(requestedSize: int) = if not isNil(profilerHook): - # disable recursive calls: XXX should use try..finally, - # but that's too expensive! - let oldHook = profilerHook - profilerHook = nil - callProfilerHook(oldHook) - profilerHook = oldHook - gTicker = SamplingInterval - dec gTicker + callProfilerHook(profilerHook, requestedSize) +else: + const + SamplingInterval = 50_000 + # set this to change the default sampling interval + var + profilerHook*: TProfilerHook + ## set this variable to provide a procedure that implements a profiler in + ## user space. See the `nimprof` module for a reference implementation. + gTicker {.threadvar.}: int + + proc callProfilerHook(hook: TProfilerHook) {.noinline.} = + # 'noinline' so that 'nimProfile' does not perform the stack allocation + # in the common case. + var st: TStackTrace + captureStackTrace(framePtr, st) + hook(st) + + proc nimProfile() = + ## This is invoked by the compiler in every loop and on every proc entry! + if gTicker == 0: + gTicker = -1 + if not isNil(profilerHook): + # disable recursive calls: XXX should use try..finally, + # but that's too expensive! + let oldHook = profilerHook + profilerHook = nil + callProfilerHook(oldHook) + profilerHook = oldHook + gTicker = SamplingInterval + dec gTicker {.pop.} |