Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathprofile.lua
More file actions
Latest commit
175 lines (162 loc) · 4.04 KB
/
Copy pathprofile.lua
File metadata and controls
175 lines (162 loc) · 4.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
localclock=os.clock
localprofile= {}
-- function labels
local_labeled= {}
-- function definitions
local_defined= {}
-- time of last call
local_tcalled= {}
-- total execution time
local_telapsed= {}
-- number of calls
local_ncalls= {}
-- list of internal profiler functions
local_internal= {}
functionprofile.hooker(event, line, info)
info=infoordebug.getinfo(2, 'fnS')
localf=info.func
-- ignore the profiler itself
if_internal[f] orinfo.what~="Lua" then
return
end
-- get the function name if available
ifinfo.namethen
_labeled[f] =info.name
end
-- find the line definition
ifnot_defined[f] then
_defined[f] =info.short_src..":"..info.linedefined
_ncalls[f] =0
_telapsed[f] =0
end
if_tcalled[f] then
localdt=clock() -_tcalled[f]
_telapsed[f] =_telapsed[f] +dt
_tcalled[f] =nil
end
ifevent=="tail call" then
localprev=debug.getinfo(3, 'fnS')
profile.hooker("return", line, prev)
profile.hooker("call", line, info)
elseifevent=='call' then
_tcalled[f] =clock()
else
_ncalls[f] =_ncalls[f] +1
end
end
--- Sets a clock function to be used by the profiler.
-- @param f Clock function that returns a number
functionprofile.setclock(f)
assert(type(f) =="function", "clock must be a function")
clock=f
end
--- Starts collecting data.
functionprofile.start()
ifrawget(_G, 'jit') then
jit.off()
jit.flush()
end
debug.sethook(profile.hooker, "cr")
end
--- Stops collecting data.
functionprofile.stop()
debug.sethook()
forfinpairs(_tcalled) do
localdt=clock() -_tcalled[f]
_telapsed[f] =_telapsed[f] +dt
_tcalled[f] =nil
end
-- merge closures
locallookup= {}
forf, dinpairs(_defined) do
localid= (_labeled[f] or'?')..d
localf2=lookup[id]
iff2then
_ncalls[f2] =_ncalls[f2] + (_ncalls[f] or0)
_telapsed[f2] =_telapsed[f2] + (_telapsed[f] or0)
_defined[f], _labeled[f] =nil, nil
_ncalls[f], _telapsed[f] =nil, nil
else
lookup[id] =f
end
end
collectgarbage('collect')
end
--- Resets all collected data.
functionprofile.reset()
forfinpairs(_ncalls) do
_ncalls[f] =0
end
forfinpairs(_telapsed) do
_telapsed[f] =0
end
forfinpairs(_tcalled) do
_tcalled[f] =nil
end
collectgarbage('collect')
end
functionprofile.comp(a, b)
localdt=_telapsed[b] -_telapsed[a]
ifdt==0then
return_ncalls[b] <_ncalls[a]
end
returndt<0
end
--- Iterates all functions that have been called since the profile was started.
-- @param n Number of results (optional)
functionprofile.query(limit)
localt= {}
forf, ninpairs(_ncalls) do
ifn>0then
t[#t+1] =f
end
end
table.sort(t, profile.comp)
iflimitthen
while#t>limitdo
table.remove(t)
end
end
fori, finipairs(t) do
localdt=0
if_tcalled[f] then
dt=clock() -_tcalled[f]
end
t[i] = { i, _labeled[f] or'?', _ncalls[f], _telapsed[f] +dt, _defined[f] }
end
returnt
end
localcols= { 3, 29, 11, 24, 32 }
functionprofile.report(n)
localout= {}
localreport=profile.query(n)
fori, rowinipairs(report) do
forj=1, 5do
locals=row[j]
locall2=cols[j]
s=tostring(s)
locall1=s:len()
ifl1<l2then
s=s..(''):rep(l2-l1)
elseifl1>l2then
s=s:sub(l1-l2+1, l1)
end
row[j] =s
end
out[i] =table.concat(row, ' | ')
end
localrow=" +-----+-------------------------------+-------------+--------------------------+----------------------------------+ \n"
localcol=" | # | Function | Calls | Time | Code | \n"
localsz=row..col..row
if#out>0then
sz=sz..' | '..table.concat(out, ' | \n | ')..' | \n'
end
return'\n'..sz..row
end
-- store all internal profiler functions
fork, vinpairs(profile) do
iftype(v) =="function" then
_internal[v] =true
end
end
returnprofile