summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2015-12-18 01:47:39 +0100
committerAndreas Rumpf <rumpf_a@web.de>2015-12-18 01:47:39 +0100
commitf75d11193adbb19d8df2171fd7146744200a9898 (patch)
tree8e955f0366a3fafa17b7c4e85a71e66cba876a40
parent1386592aab784f194c54ee2dad6ea115df27ce6f (diff)
downloadNim-f75d11193adbb19d8df2171fd7146744200a9898.tar.gz
modified the integrated profiler to hopefully produce more reliable results
-rw-r--r--lib/pure/nimprof.nim37
-rw-r--r--lib/system/profiler.nim26
2 files changed, 35 insertions, 28 deletions
diff --git a/lib/pure/nimprof.nim b/lib/pure/nimprof.nim
index cfe6bc40d..d1f215bae 100644
--- a/lib/pure/nimprof.nim
+++ b/lib/pure/nimprof.nim
@@ -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
diff --git a/lib/system/profiler.nim b/lib/system/profiler.nim
index 4f600417e..ae8ff4e19 100644
--- a/lib/system/profiler.nim
+++ b/lib/system/profiler.nim
@@ -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.}