aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Pall <mike>2013-09-09 04:24:51 +0200
committerMike Pall <mike>2013-09-09 04:32:31 +0200
commit2befb8b1de3c6dec4d326a01419615a8bab4eeef (patch)
tree83f184ec0070f74978e2ece06c5664af708cd8a3
parent1fd2048c8d296e7bde3e27b8ec1fc5b2ea834d3c (diff)
downloadluajit-2befb8b1de3c6dec4d326a01419615a8bab4eeef.tar.gz
luajit-2befb8b1de3c6dec4d326a01419615a8bab4eeef.tar.bz2
luajit-2befb8b1de3c6dec4d326a01419615a8bab4eeef.zip
Low-overhead profiler, part 5: add annotation mode for -jp.
-rw-r--r--src/jit/p.lua95
1 files changed, 88 insertions, 7 deletions
diff --git a/src/jit/p.lua b/src/jit/p.lua
index 90b50bca..f3bec9f0 100644
--- a/src/jit/p.lua
+++ b/src/jit/p.lua
@@ -31,6 +31,8 @@
31-- v Show VM states. Can be combined with stack dumps, e.g. vf or fv. 31-- v Show VM states. Can be combined with stack dumps, e.g. vf or fv.
32-- z Show zones. Can be combined with stack dumps, e.g. zf or fz. 32-- z Show zones. Can be combined with stack dumps, e.g. zf or fz.
33-- r Show raw sample counts. Default: show percentages. 33-- r Show raw sample counts. Default: show percentages.
34-- a Annotate excerpts from source code files.
35-- A Annotate complete source code files.
34-- G Produce output suitable for graphical tools (e.g. flame graphs). 36-- G Produce output suitable for graphical tools (e.g. flame graphs).
35-- m<number> Minimum sample percentage to be shown. Default: 3. 37-- m<number> Minimum sample percentage to be shown. Default: 3.
36-- i<number> Sampling interval in milliseconds. Default: 10. 38-- i<number> Sampling interval in milliseconds. Default: 10.
@@ -42,7 +44,8 @@ local jit = require("jit")
42assert(jit.version_num == 20100, "LuaJIT core/library version mismatch") 44assert(jit.version_num == 20100, "LuaJIT core/library version mismatch")
43local profile = require("jit.profile") 45local profile = require("jit.profile")
44local vmdef = require("jit.vmdef") 46local vmdef = require("jit.vmdef")
45local pairs, tonumber, floor, min = pairs, tonumber, math.floor, math.min 47local math = math
48local pairs, ipairs, tonumber, floor = pairs, ipairs, tonumber, math.floor
46local sort, format = table.sort, string.format 49local sort, format = table.sort, string.format
47local stdout = io.stdout 50local stdout = io.stdout
48local zone -- Load jit.zone module on demand. 51local zone -- Load jit.zone module on demand.
@@ -54,7 +57,7 @@ local out
54 57
55local prof_ud 58local prof_ud
56local prof_states, prof_split, prof_min, prof_raw, prof_fmt, prof_depth 59local prof_states, prof_split, prof_min, prof_raw, prof_fmt, prof_depth
57local prof_count1, prof_count2, prof_samples 60local prof_ann, prof_count1, prof_count2, prof_samples
58 61
59local map_vmmode = { 62local map_vmmode = {
60 N = "Compiled", 63 N = "Compiled",
@@ -120,15 +123,14 @@ local function prof_top(count1, count2, samples, indent)
120 t[n] = k 123 t[n] = k
121 end 124 end
122 sort(t, function(a, b) return count1[a] > count1[b] end) 125 sort(t, function(a, b) return count1[a] > count1[b] end)
123 local raw = prof_raw
124 for i=1,n do 126 for i=1,n do
125 local k = t[i] 127 local k = t[i]
126 local v = count1[k] 128 local v = count1[k]
127 local pct = floor(v*100/samples + 0.5) 129 local pct = floor(v*100/samples + 0.5)
128 if pct < prof_min then break end 130 if pct < prof_min then break end
129 if not raw then 131 if not prof_raw then
130 out:write(format("%s%2d%% %s\n", indent, pct, k)) 132 out:write(format("%s%2d%% %s\n", indent, pct, k))
131 elseif raw == "r" then 133 elseif prof_raw == "r" then
132 out:write(format("%s%5d %s\n", indent, v, k)) 134 out:write(format("%s%5d %s\n", indent, v, k))
133 else 135 else
134 out:write(format("%s %d\n", k, v)) 136 out:write(format("%s %d\n", k, v))
@@ -142,6 +144,75 @@ local function prof_top(count1, count2, samples, indent)
142 end 144 end
143end 145end
144 146
147-- Annotate source code
148local function prof_annotate(count1, samples)
149 local files = {}
150 local ms = 0
151 for k, v in pairs(count1) do
152 local pct = floor(v*100/samples + 0.5)
153 ms = math.max(ms, v)
154 if pct >= prof_min then
155 local file, line = k:match("^(.*):(%d+)$")
156 local fl = files[file]
157 if not fl then fl = {}; files[file] = fl; files[#files+1] = file end
158 line = tonumber(line)
159 fl[line] = prof_raw and v or pct
160 end
161 end
162 sort(files)
163 local fmtv, fmtn = " %3d%% | %s\n", " | %s\n"
164 if prof_raw then
165 local n = math.max(5, math.ceil(math.log10(ms)))
166 fmtv = "%"..n.."d | %s\n"
167 fmtn = (" "):rep(n).." | %s\n"
168 end
169 local ann = prof_ann
170 for _, file in ipairs(files) do
171 local f0 = file:byte()
172 if f0 == 40 or f0 == 91 then
173 out:write(format("\n====== %s ======\n[Cannot annotate non-file]\n", file))
174 break
175 end
176 local fp, err = io.open(file)
177 if not fp then
178 out:write(format("====== ERROR: %s: %s\n", file, err))
179 break
180 end
181 out:write(format("\n====== %s ======\n", file))
182 local fl = files[file]
183 local n, show = 1, false
184 if ann ~= 0 then
185 for i=1,ann do
186 if fl[i] then show = true; out:write("@@ 1 @@\n"); break end
187 end
188 end
189 for line in fp:lines() do
190 if line:byte() == 27 then
191 out:write("[Cannot annotate bytecode file]\n")
192 break
193 end
194 local v = fl[n]
195 if ann ~= 0 then
196 if show then
197 if v then show = n elseif show+ann < n then show = false end
198 elseif fl[n+ann] then
199 show = n+ann
200 out:write(format("@@ %d @@\n", n))
201 end
202 if not show then goto next end
203 end
204 if v then
205 out:write(format(fmtv, v, line))
206 else
207 out:write(format(fmtn, line))
208 end
209 ::next::
210 n = n + 1
211 end
212 fp:close()
213 end
214end
215
145------------------------------------------------------------------------------ 216------------------------------------------------------------------------------
146 217
147-- Finish profiling and dump result. 218-- Finish profiling and dump result.
@@ -153,7 +224,11 @@ local function prof_finish()
153 if prof_raw ~= true then out:write("[no samples collected]\n") end 224 if prof_raw ~= true then out:write("[no samples collected]\n") end
154 return 225 return
155 end 226 end
156 prof_top(prof_count1, prof_count2, samples, "") 227 if prof_ann then
228 prof_annotate(prof_count1, samples)
229 else
230 prof_top(prof_count1, prof_count2, samples, "")
231 end
157 prof_count1 = nil 232 prof_count1 = nil
158 prof_count2 = nil 233 prof_count2 = nil
159 prof_ud = nil 234 prof_ud = nil
@@ -182,7 +257,13 @@ local function prof_start(mode)
182 else 257 else
183 prof_split = (scope == "" or mode:find("[zv].*[lfF]")) and 1 or 0 258 prof_split = (scope == "" or mode:find("[zv].*[lfF]")) and 1 or 0
184 end 259 end
185 if m.G and scope ~= "" then 260 prof_ann = m.A and 0 or (m.a and 3)
261 if prof_ann then
262 scope = "l"
263 prof_fmt = "pl"
264 prof_split = 0
265 prof_depth = 1
266 elseif m.G and scope ~= "" then
186 prof_fmt = flags..scope.."Z;" 267 prof_fmt = flags..scope.."Z;"
187 prof_depth = -100 268 prof_depth = -100
188 prof_raw = true 269 prof_raw = true