diff options
author | Mike Pall <mike> | 2013-09-09 04:24:51 +0200 |
---|---|---|
committer | Mike Pall <mike> | 2013-09-09 04:32:31 +0200 |
commit | 2befb8b1de3c6dec4d326a01419615a8bab4eeef (patch) | |
tree | 83f184ec0070f74978e2ece06c5664af708cd8a3 | |
parent | 1fd2048c8d296e7bde3e27b8ec1fc5b2ea834d3c (diff) | |
download | luajit-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.lua | 95 |
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") | |||
42 | assert(jit.version_num == 20100, "LuaJIT core/library version mismatch") | 44 | assert(jit.version_num == 20100, "LuaJIT core/library version mismatch") |
43 | local profile = require("jit.profile") | 45 | local profile = require("jit.profile") |
44 | local vmdef = require("jit.vmdef") | 46 | local vmdef = require("jit.vmdef") |
45 | local pairs, tonumber, floor, min = pairs, tonumber, math.floor, math.min | 47 | local math = math |
48 | local pairs, ipairs, tonumber, floor = pairs, ipairs, tonumber, math.floor | ||
46 | local sort, format = table.sort, string.format | 49 | local sort, format = table.sort, string.format |
47 | local stdout = io.stdout | 50 | local stdout = io.stdout |
48 | local zone -- Load jit.zone module on demand. | 51 | local zone -- Load jit.zone module on demand. |
@@ -54,7 +57,7 @@ local out | |||
54 | 57 | ||
55 | local prof_ud | 58 | local prof_ud |
56 | local prof_states, prof_split, prof_min, prof_raw, prof_fmt, prof_depth | 59 | local prof_states, prof_split, prof_min, prof_raw, prof_fmt, prof_depth |
57 | local prof_count1, prof_count2, prof_samples | 60 | local prof_ann, prof_count1, prof_count2, prof_samples |
58 | 61 | ||
59 | local map_vmmode = { | 62 | local 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 |
143 | end | 145 | end |
144 | 146 | ||
147 | -- Annotate source code | ||
148 | local 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 | ||
214 | end | ||
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 |