modified the integrated profiler to hopefully produce more reliable results

This commit is contained in:
Andreas Rumpf
2015-12-18 01:47:39 +01:00
parent 1386592aab
commit f75d11193a
2 changed files with 35 additions and 28 deletions

View File

@@ -1,7 +1,7 @@
#
#
# Nim's Runtime Library
# (c) Copyright 2012 Andreas Rumpf
# (c) Copyright 2015 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
@@ -117,24 +117,38 @@ when defined(memProfiler):
var
gTicker {.threadvar.}: int
proc hook(st: StackTrace, size: int) {.nimcall.} =
proc requestedHook(): bool {.nimcall.} =
if gTicker == 0:
gTicker = -1
when defined(ignoreAllocationSize):
hookAux(st, 1)
else:
hookAux(st, size)
gTicker = SamplingInterval
result = true
dec gTicker
proc hook(st: StackTrace, size: int) {.nimcall.} =
when defined(ignoreAllocationSize):
hookAux(st, 1)
else:
hookAux(st, size)
else:
var
t0 {.threadvar.}: Ticks
gTicker: int # we use an additional counter to
# avoid calling 'getTicks' too frequently
proc requestedHook(): bool {.nimcall.} =
if interval == 0: result = true
elif gTicker == 0:
gTicker = 500
if getTicks() - t0 > interval:
result = true
else:
dec gTicker
proc hook(st: StackTrace) {.nimcall.} =
#echo "profiling! ", interval
if interval == 0:
hookAux(st, 1)
elif int64(t0) == 0 or getTicks() - t0 > interval:
else:
hookAux(st, 1)
t0 = getTicks()
@@ -145,9 +159,10 @@ proc cmpEntries(a, b: ptr ProfileEntry): int =
result = b.getTotal - a.getTotal
proc `//`(a, b: int): string =
result = format("$1/$2 = $3%", a, b, formatFloat(a / b * 100.0, ffDefault, 2))
result = format("$1/$2 = $3%", a, b, formatFloat(a / b * 100.0, ffDecimal, 2))
proc writeProfile() {.noconv.} =
system.profilingRequestedHook = nil
when declared(system.StackTrace):
system.profilerHook = nil
const filename = "profile_results.txt"
@@ -193,12 +208,12 @@ var
proc disableProfiling*() =
when declared(system.StackTrace):
atomicDec disabled
system.profilerHook = nil
system.profilingRequestedHook = nil
proc enableProfiling*() =
when declared(system.StackTrace):
if atomicInc(disabled) >= 0:
system.profilerHook = hook
system.profilingRequestedHook = requestedHook
when declared(system.StackTrace):
system.profilerHook = hook

View File

@@ -50,10 +50,15 @@ proc captureStackTrace(f: PFrame, st: var StackTrace) =
inc(i)
b = b.prev
var
profilingRequestedHook*: proc (): bool {.nimcall, benign.}
## set this variable to provide a procedure that implements a profiler in
## user space. See the `nimprof` module for a reference implementation.
when defined(memProfiler):
type
MemProfilerHook* = proc (st: StackTrace, requestedSize: int) {.nimcall, benign.}
{.deprecated: [TMemProfilerHook: MemProfilerHook].}
var
profilerHook*: MemProfilerHook
## set this variable to provide a procedure that implements a profiler in
@@ -65,17 +70,13 @@ when defined(memProfiler):
hook(st, requestedSize)
proc nimProfile(requestedSize: int) =
if not isNil(profilerHook):
if not isNil(profilingRequestedHook) and profilingRequestedHook():
callProfilerHook(profilerHook, requestedSize)
else:
const
SamplingInterval = 50_000
# set this to change the default sampling interval
var
profilerHook*: ProfilerHook
## 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: ProfilerHook) {.noinline.} =
# 'noinline' so that 'nimProfile' does not perform the stack allocation
@@ -86,16 +87,7 @@ else:
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
if not isNil(profilingRequestedHook) and profilingRequestedHook():
callProfilerHook(profilerHook)
{.pop.}