trac-inf.lua /size: 9 Kb    last modification: 2020-07-01 14:35
1
if
not
modules
then
modules
=
{
}
end
modules
[
'
trac-inf
'
]
=
{
2
version
=
1
.
001
,
3
comment
=
"
companion to trac-inf.mkiv
"
,
4
author
=
"
Hans Hagen, PRAGMA-ADE, Hasselt NL
"
,
5
copyright
=
"
PRAGMA ADE / ConTeXt Development Team
"
,
6
license
=
"
see context related readme files
"
7
}
8 9
-- As we want to protect the global tables, we no longer store the timing
10
-- in the tables themselves but in a hidden timers table so that we don't
11
-- get warnings about assignments. This is more efficient than using rawset
12
-- and rawget.
13 14
local
type
,
tonumber
,
select
=
type
,
tonumber
,
select
15
local
format
,
lower
,
find
=
string
.
format
,
string
.
lower
,
string
.
find
16
local
concat
=
table
.
concat
17
local
clock
=
os
.
gettimeofday
or
os
.
clock
-- should go in environment
18 19
local
setmetatableindex
=
table
.
setmetatableindex
20
local
serialize
=
table
.
serialize
21
local
formatters
=
string
.
formatters
22 23
statistics
=
statistics
or
{
}
24
local
statistics
=
statistics
25 26
statistics
.
enable
=
true
27
statistics
.
threshold
=
0
.
01
28 29
local
statusinfo
,
n
,
registered
,
timers
=
{
}
,
0
,
{
}
,
{
}
30 31
setmetatableindex
(
timers
,
function
(
t
,
k
)
32
local
v
=
{
timing
=
0
,
loadtime
=
0
,
offset
=
0
}
33
t
[
k
]
=
v
34
return
v
35
end
)
36 37
local
function
hastiming
(
instance
)
38
return
instance
and
timers
[
instance
]
39
end
40 41
local
function
resettiming
(
instance
)
42
timers
[
instance
or
"
notimer
"
]
=
{
timing
=
0
,
loadtime
=
0
,
offset
=
0
}
43
end
44 45
local
ticks
=
clock
46
local
seconds
=
function
(
n
)
return
n
or
0
end
47 48
if
os
.
type
~
=
"
windows
"
then
49 50
-- doesn't work well yet on unix (system time vs process time so a mtxrun
51
-- timing with nested call gives the wrong result)
52 53
elseif
lua
.
getpreciseticks
then
54 55
ticks
=
lua
.
getpreciseticks
56
seconds
=
lua
.
getpreciseseconds
57 58
elseif
FFISUPPORTED
then
59 60
-- Do we really care when not in luametatex? For now we do, so:
61 62
local
okay
,
kernel
=
pcall
(
ffi
.
load
,
"
kernel32
"
)
63 64
if
kernel
then
65 66
local
tonumber
=
ffi
.
number
or
tonumber
67 68
ffi
.
cdef
[[
69 int QueryPerformanceFrequency(int64_t *lpFrequency); 70 int QueryPerformanceCounter(int64_t *lpPerformanceCount); 71
]]
72 73
local
target
=
ffi
.
new
(
"
__int64[1]
"
)
74 75
ticks
=
function
(
)
76
if
kernel
.
QueryPerformanceCounter
(
target
)
=
=
1
then
77
return
tonumber
(
target
[
0
]
)
78
else
79
return
0
80
end
81
end
82 83
local
target
=
ffi
.
new
(
"
__int64[1]
"
)
84 85
seconds
=
function
(
ticks
)
86
if
kernel
.
QueryPerformanceFrequency
(
target
)
=
=
1
then
87
return
ticks
/
tonumber
(
target
[
0
]
)
88
else
89
return
0
90
end
91
end
92 93
end
94 95
else
96 97
-- excessive timing costs some 1-2 percent runtime
98 99
end
100 101 102
local
function
starttiming
(
instance
,
reset
)
103
local
timer
=
timers
[
instance
or
"
notimer
"
]
104
local
it
=
timer
.
timing
105
if
reset
then
106
it
=
0
107
timer
.
loadtime
=
0
108
end
109
if
it
=
=
0
then
110
timer
.
starttime
=
ticks
(
)
111
if
not
timer
.
loadtime
then
112
timer
.
loadtime
=
0
113
end
114
end
115
timer
.
timing
=
it
+
1
116
end
117 118
local
function
stoptiming
(
instance
)
119
local
timer
=
timers
[
instance
or
"
notimer
"
]
120
local
it
=
timer
.
timing
121
if
it
>
1
then
122
timer
.
timing
=
it
-
1
123
else
124
local
starttime
=
timer
.
starttime
125
if
starttime
and
starttime
>
0
then
126
local
stoptime
=
ticks
(
)
127
local
loadtime
=
stoptime
-
starttime
128
timer
.
stoptime
=
stoptime
129
timer
.
loadtime
=
timer
.
loadtime
+
loadtime
130
timer
.
timing
=
0
131
timer
.
starttime
=
0
132
return
loadtime
133
end
134
end
135
return
0
136
end
137 138
local
function
benchmarktimer
(
instance
)
139
local
timer
=
timers
[
instance
or
"
notimer
"
]
140
local
it
=
timer
.
timing
141
if
it
>
1
then
142
timer
.
timing
=
it
-
1
143
else
144
local
starttime
=
timer
.
starttime
145
if
starttime
and
starttime
>
0
then
146
timer
.
offset
=
ticks
(
)
-
starttime
147
else
148
timer
.
offset
=
0
149
end
150
end
151
end
152 153
local
function
elapsed
(
instance
)
154
if
type
(
instance
)
=
=
"
number
"
then
155
return
instance
156
else
157
local
timer
=
timers
[
instance
or
"
notimer
"
]
158
return
timer
and
seconds
(
timer
.
loadtime
-
2
*
(
timer
.
offset
or
0
)
)
or
0
159
end
160
end
161 162
local
function
currenttime
(
instance
)
163
if
type
(
instance
)
=
=
"
number
"
then
164
return
instance
165
else
166
local
timer
=
timers
[
instance
or
"
notimer
"
]
167
local
it
=
timer
.
timing
168
if
it
>
1
then
169
-- whatever
170
else
171
local
starttime
=
timer
.
starttime
172
if
starttime
and
starttime
>
0
then
173
return
seconds
(
timer
.
loadtime
+
ticks
(
)
-
starttime
-
2
*
(
timer
.
offset
or
0
)
)
174
end
175
end
176
return
0
177
end
178
end
179 180
local
function
elapsedtime
(
instance
)
181
return
format
(
"
%0.3f
"
,
elapsed
(
instance
)
)
182
end
183 184
local
function
elapsedindeed
(
instance
)
185
return
elapsed
(
instance
)
>
statistics
.
threshold
186
end
187 188
local
function
elapsedseconds
(
instance
,
rest
)
-- returns nil if 0 seconds
189
if
elapsedindeed
(
instance
)
then
190
return
format
(
"
%0.3f seconds %s
"
,
elapsed
(
instance
)
,
rest
or
"
"
)
191
end
192
end
193 194
statistics
.
hastiming
=
hastiming
195
statistics
.
resettiming
=
resettiming
196
statistics
.
starttiming
=
starttiming
197
statistics
.
stoptiming
=
stoptiming
198
statistics
.
currenttime
=
currenttime
199
statistics
.
elapsed
=
elapsed
200
statistics
.
elapsedtime
=
elapsedtime
201
statistics
.
elapsedindeed
=
elapsedindeed
202
statistics
.
elapsedseconds
=
elapsedseconds
203
statistics
.
benchmarktimer
=
benchmarktimer
204 205
-- general function .. we might split this module
206 207
function
statistics
.
register
(
tag
,
fnc
)
208
if
statistics
.
enable
and
type
(
fnc
)
=
=
"
function
"
then
209
local
rt
=
registered
[
tag
]
or
(
#
statusinfo
+
1
)
210
statusinfo
[
rt
]
=
{
tag
,
fnc
}
211
registered
[
tag
]
=
rt
212
if
#
tag
>
n
then
n
=
#
tag
end
213
end
214
end
215 216
local
report
=
logs
.
reporter
(
"
mkiv lua stats
"
)
217 218
function
statistics
.
show
(
)
219
if
statistics
.
enable
then
220
-- this code will move
221
local
register
=
statistics
.
register
222
register
(
"
used platform
"
,
function
(
)
223
return
format
(
"
%s, type: %s, binary subtree: %s
"
,
224
os
.
platform
or
"
unknown
"
,
os
.
type
or
"
unknown
"
,
environment
.
texos
or
"
unknown
"
)
225
end
)
226
-- register("luatex banner", function()
227
-- return lower(status.banner)
228
-- end)
229
if
LUATEXENGINE
=
=
"
luametatex
"
then
230
register
(
"
used engine
"
,
function
(
)
231
return
format
(
"
%s version: %s, functionality level: %s, format id: %s, compiler: %s
"
,
232
LUATEXENGINE
,
LUATEXVERSION
,
LUATEXFUNCTIONALITY
,
LUATEXFORMATID
,
status
.
used_compiler
)
233
end
)
234
else
235
register
(
"
used engine
"
,
function
(
)
236
return
format
(
"
%s version: %s, functionality level: %s, banner: %s
"
,
237
LUATEXENGINE
,
LUATEXVERSION
,
LUATEXFUNCTIONALITY
,
lower
(
status
.
banner
)
)
238
end
)
239
end
240
register
(
"
used hash slots
"
,
function
(
)
241
return
format
(
"
%s of %s + %s
"
,
status
.
cs_count
,
status
.
hash_size
,
status
.
hash_extra
)
242
end
)
243
register
(
"
callbacks
"
,
statistics
.
callbacks
)
244
if
JITSUPPORTED
then
245
local
jitstatus
=
jit
.
status
246
if
jitstatus
then
247
local
jitstatus
=
{
jitstatus
(
)
}
248
if
jitstatus
[
1
]
then
249
register
(
"
luajit options
"
,
concat
(
jitstatus
,
"
"
,
2
)
)
250
end
251
end
252
end
253
-- so far
254
-- collectgarbage("collect")
255
register
(
"
lua properties
"
,
function
(
)
256
local
hashchar
=
tonumber
(
status
.
luatex_hashchars
)
257
local
mask
=
lua
.
mask
or
"
ascii
"
258
return
format
(
"
engine: %s %s, used memory: %s, hash chars: min(%i,40), symbol mask: %s (%s)
"
,
259
jit
and
"
luajit
"
or
"
lua
"
,
260
LUAVERSION
,
261
statistics
.
memused
(
)
,
262
hashchar
and
2
^
hashchar
or
"
unknown
"
,
263
mask
,
264
mask
=
=
"
utf
"
and
"
τεχ
"
or
"
tex
"
)
265
end
)
266
register
(
"
runtime
"
,
statistics
.
runtime
)
267
logs
.
newline
(
)
-- initial newline
268
for
i
=
1
,
#
statusinfo
do
269
local
s
=
statusinfo
[
i
]
270
local
r
=
s
[
2
]
(
)
271
if
r
then
272
report
(
"
%s: %s
"
,
s
[
1
]
,
r
)
273
end
274
end
275
-- logs.newline() -- final newline
276
statistics
.
enable
=
false
277
end
278
end
279 280
function
statistics
.
memused
(
)
-- no math.round yet -)
281
local
round
=
math
.
round
or
math
.
floor
282
return
format
(
"
%s MB, ctx: %s MB, max: %s MB
"
,
283
round
(
collectgarbage
(
"
count
"
)
/
1000
)
,
284
round
(
status
.
luastate_bytes
/
1000000
)
,
285
status
.
luastate_bytes_max
and
round
(
status
.
luastate_bytes_max
/
1000000
)
or
"
unknown
"
286
)
287
end
288 289
starttiming
(
statistics
)
290 291
function
statistics
.
formatruntime
(
runtime
)
-- indirect so it can be overloaded and
292
return
format
(
"
%s seconds
"
,
runtime
)
-- indeed that happens in cure-uti.lua
293
end
294 295
function
statistics
.
runtime
(
)
296
stoptiming
(
statistics
)
297
-- stoptiming(statistics) -- somehow we can start the timer twice, but where
298
local
runtime
=
lua
.
getruntime
and
lua
.
getruntime
(
)
or
elapsedtime
(
statistics
)
299
return
statistics
.
formatruntime
(
runtime
)
300
end
301 302
local
report
=
logs
.
reporter
(
"
system
"
)
303 304
function
statistics
.
timed
(
action
,
all
)
305
starttiming
(
"
run
"
)
306
action
(
)
307
stoptiming
(
"
run
"
)
308
local
runtime
=
tonumber
(
elapsedtime
(
"
run
"
)
)
309
if
all
then
310
local
alltime
=
tonumber
(
lua
.
getruntime
and
lua
.
getruntime
(
)
or
elapsedtime
(
statistics
)
)
311
if
alltime
and
alltime
>
0
then
312
report
(
"
total runtime: %0.3f seconds of %0.3f seconds
"
,
runtime
,
alltime
)
313
return
314
end
315
end
316
report
(
"
total runtime: %0.3f seconds
"
,
runtime
)
317
end
318 319
-- goodie
320 321
function
statistics
.
tracefunction
(
base
,
tag
,
...
)
322
for
i
=
1
,
select
(
"
#
"
,
...
)
do
323
local
name
=
select
(
i
,
...
)
324
local
stat
=
{
}
325
local
func
=
base
[
name
]
326
setmetatableindex
(
stat
,
function
(
t
,
k
)
t
[
k
]
=
0
return
0
end
)
327
base
[
name
]
=
function
(
n
,
k
,
v
)
stat
[
k
]
=
stat
[
k
]
+
1
return
func
(
n
,
k
,
v
)
end
328
statistics
.
register
(
formatters
[
"
%s.%s
"
]
(
tag
,
name
)
,
function
(
)
return
serialize
(
stat
,
"
calls
"
)
end
)
329
end
330
end
331