summary refs log tree commit diff stats
path: root/compiler/vmprofiler.nim
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/vmprofiler.nim')
-rw-r--r--compiler/vmprofiler.nim45
1 files changed, 45 insertions, 0 deletions
diff --git a/compiler/vmprofiler.nim b/compiler/vmprofiler.nim
new file mode 100644
index 000000000..3f0db84bd
--- /dev/null
+++ b/compiler/vmprofiler.nim
@@ -0,0 +1,45 @@
+
+import options, vmdef, lineinfos, msgs
+
+import std/[times, strutils, tables]
+
+proc enter*(prof: var Profiler, c: PCtx, tos: PStackFrame) {.inline.} =
+  if optProfileVM in c.config.globalOptions:
+    prof.tEnter = cpuTime()
+    prof.tos = tos
+
+proc leaveImpl(prof: var Profiler, c: PCtx) {.noinline.} =
+  let tLeave = cpuTime()
+  var tos = prof.tos
+  var data = c.config.vmProfileData.data
+  while tos != nil:
+    if tos.prc != nil:
+      let li = tos.prc.info
+      if li notin data:
+        data[li] = ProfileInfo()
+      data[li].time += tLeave - prof.tEnter
+      if tos == prof.tos:
+        inc data[li].count
+    tos = tos.next
+
+proc leave*(prof: var Profiler, c: PCtx) {.inline.} =
+  if optProfileVM in c.config.globalOptions:
+    leaveImpl(prof, c)
+
+proc dump*(conf: ConfigRef, pd: ProfileData): string =
+  var data = pd.data
+  result = "\nprof:     µs    #instr  location"
+  for i in 0..<32:
+    var tMax: float
+    var infoMax: ProfileInfo = default(ProfileInfo)
+    var flMax: TLineInfo = default(TLineInfo)
+    for fl, info in data:
+      if info.time > infoMax.time:
+        infoMax = info
+        flMax = fl
+    if infoMax.count == 0:
+      break
+    result.add  "  " & align($int(infoMax.time * 1e6), 10) &
+                       align($int(infoMax.count), 10) & "  " &
+                       conf.toFileLineCol(flMax) & "\n"
+    data.del flMax