-
Notifications
You must be signed in to change notification settings - Fork 4
/
profile.lua
102 lines (89 loc) · 3.04 KB
/
profile.lua
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
--| Profiler module.
--b "Pedro Miller Rabinovitch" <[email protected]>
--$Id: prof.lua,v 1.4 2003/10/17 00:17:21 miller Exp $
--TODO add function call profiling. Some of the skeleton is already in
--- place, but call profiling behaves different, so a couple of new
--- functionalities must be added.
--TODO add methods for proper result retrieval
--TODO use optional clock() function for millisecond precision, if it's
--- available
local E, I = {}, {}
--& Profiler module.
-- Profiler = E
--. Keeps track of the hit counts of each item
E.counts = {
line = {}
}
--. These should be inside the _line_ table above.
E.last_line = nil
E.last_time = os.epoch("utc")
E.started, E.ended = nil, nil
local dontdie = 0
--% Activates the profiling system.
--@ [kind] (string) Optional hook kind. For now, only 'line' works,
--- so just avoid it. >: )
function E:activate( kind )
kind = kind or 'line'
local function hook_counter( hk_name, param,... )
local t = self.counts[hk_name][param]
if t == nil then
t = { count=0, time = 0, name = debug.getinfo(2).short_src }
self.counts[hk_name][param] = t
end
self.counts[hk_name][param].count =
self.counts[hk_name][param].count + 1
dontdie = dontdie + 1
if dontdie > 1000000 then
dontdie = 0
print("yielding")
self.ended = os.epoch("utc")
E:write_results("line", "profile.txt")
coroutine.yield()
end
if self.last_line then
local delta = os.epoch("utc") - self.last_time
if delta > 0 then
self.counts[hk_name][self.last_line].time =
self.counts[hk_name][self.last_line].time + delta
self.last_time = os.epoch("utc")
end
end
self.last_line = param
end
self.started = os.epoch("utc")
debug.sethook( hook_counter, kind )
end
--% Deactivates the profiling system.
--@ [kind] (string) Optional hook kind. For now, only 'line' works,
--- so just avoid it.
function E:deactivate( kind )
kind = kind or 'line'
self.ended = os.epoch("utc")
debug.sethook( nil, kind )
end
--% Prints the results.
--@ [kind] (string) Optional hook... Aah, you got it by now.
--TODO add print output formatting and sorting
function E:print_results( kind )
kind = kind or 'line'
print( kind, 'count', 'approx. time (s)' )
print( '----', '-----', '----------------' )
for i,v in pairs( self.counts[kind] ) do
print( i, v.count, v.time )
end
print( self.ended - self.started,
' second(s) total (approximately).' )
end
function E:write_results( kind, filename )
kind = kind or 'line'
local f = io.open( filename, 'w' )
f:write( 'file', kind, ' count', ' approx. time (s)', '\n' )
f:write( '-------------', '----', ' -----', ' ----------------', '\n' )
for i,v in pairs( self.counts[kind] ) do
f:write( v.name, ' ', i, ' ', v.count, ' ', v.time, '\n' )
end
f:write( self.ended - self.started,
' second(s) total (approximately).', '\n' )
f:close()
end
return E