1
1
module LinuxPerf
2
2
3
+ using Printf
4
+
5
+ export make_bench, enable!, disable!, reset!, reasonable_defaults, counters
6
+
7
+ import Base: show, length, close
8
+
3
9
const SYS_perf_event_open = 298
4
10
5
- type perf_event_attr
6
- typ :: UInt32
7
- size :: UInt32
8
- config :: UInt64
9
- sample_period_or_freq :: UInt64
10
- sample_type :: UInt64
11
- read_format :: UInt64
12
- flags :: UInt64
13
- wakeup_events_or_watermark :: UInt32
14
- bp_type :: UInt32
15
- bp_addr_or_config1 :: UInt64
16
- bp_len_or_config2 :: UInt64
17
- branch_sample_type :: UInt64
18
-
19
- sample_regs_user :: UInt64
20
- sample_stack_user :: UInt32
21
- clockid :: Int32
22
- sample_regs_intr :: UInt64
23
- aux_watermark :: UInt32
24
- __reserved_2 :: UInt32
25
-
26
- perf_event_attr () = new ()
11
+ mutable struct perf_event_attr
12
+ typ:: UInt32
13
+ size:: UInt32
14
+ config:: UInt64
15
+ sample_period_or_freq:: UInt64
16
+ sample_type:: UInt64
17
+ read_format:: UInt64
18
+ flags:: UInt64
19
+ wakeup_events_or_watermark:: UInt32
20
+ bp_type:: UInt32
21
+ bp_addr_or_config1:: UInt64
22
+ bp_len_or_config2:: UInt64
23
+ branch_sample_type:: UInt64
24
+
25
+ sample_regs_user:: UInt64
26
+ sample_stack_user:: UInt32
27
+ clockid:: Int32
28
+ sample_regs_intr:: UInt64
29
+ aux_watermark:: UInt32
30
+ __reserved_2:: UInt32
31
+
27
32
end
28
33
34
+ perf_event_attr () = perf_event_attr (ntuple (x-> 0 , fieldcount (perf_event_attr))... )
35
+
29
36
const EVENT_TYPES =
30
37
[
31
38
(:hw , 0 , # PERF_TYPE_HARDWARE
@@ -70,9 +77,9 @@ const PERF_FORMAT_TOTAL_TIME_ENABLED = 1 << 0
70
77
const PERF_FORMAT_TOTAL_TIME_RUNNING = 1 << 1
71
78
const PERF_FORMAT_GROUP = 1 << 3
72
79
73
- immutable EventType
74
- category :: UInt32
75
- event :: UInt64
80
+ struct EventType
81
+ category:: UInt32
82
+ event:: UInt64
76
83
end
77
84
78
85
function all_events ()
@@ -141,17 +148,19 @@ function EventType(cat::Symbol, cache::Symbol, op::Symbol, evt::Symbol)
141
148
cache_id | (op_id << 8 ) | (evt_id << 16 ))
142
149
end
143
150
144
- type EventGroup
145
- leader_fd :: Cint
146
- fds :: Vector{Cint}
147
- event_types :: Vector{EventType}
148
- leader_io :: IOStream
149
- function EventGroup (types :: Vector{EventType} ;
151
+ mutable struct EventGroup
152
+ leader_fd:: Cint
153
+ fds:: Vector{Cint}
154
+ event_types:: Vector{EventType}
155
+ leader_io:: IOStream
156
+
157
+ function EventGroup (types:: Vector{EventType} ;
150
158
warn_unsupported = true ,
151
159
userspace_only = false
152
160
)
153
- my_types = Array (EventType, 0 )
154
- group = new (- 1 , Array (Cint, 0 ), Array (EventType, 0 ))
161
+ my_types = EventType[]
162
+ group = new (- 1 , Cint[], EventType[])
163
+
155
164
for (i,evt_type) in enumerate (types)
156
165
attr = perf_event_attr ()
157
166
attr. typ = evt_type. category
@@ -175,14 +184,13 @@ type EventGroup
175
184
errno = Libc. errno ()
176
185
if errno in (Libc. EINVAL,Libc. ENOENT)
177
186
if warn_unsupported
178
- warn (" $evt_type not supported, skipping" )
187
+ @ warn (" $evt_type not supported, skipping" )
179
188
end
180
189
continue
181
190
else
182
191
if errno == Libc. EACCES && ! userspace_only
183
- warn (" try to adjust /proc/sys/kernel/perf_event_paranoid to a value <= 1 or use user-space only events" )
192
+ @ warn (" try to adjust /proc/sys/kernel/perf_event_paranoid to a value <= 1 or use user-space only events" )
184
193
end
185
- @show errno
186
194
error (" perf_event_open error : $(Libc. strerror (errno)) " )
187
195
end
188
196
end
@@ -218,48 +226,57 @@ function ioctl(group::EventGroup, x)
218
226
error (" ioctl error : $(Libc. strerror ()) " )
219
227
end
220
228
end
229
+
221
230
enable! (g:: EventGroup ) = ioctl (g, PERF_EVENT_IOC_ENABLE)
222
231
disable! (g:: EventGroup ) = ioctl (g, PERF_EVENT_IOC_DISABLE)
223
232
reset! (g:: EventGroup ) = ioctl (g, PERF_EVENT_IOC_RESET)
233
+
224
234
function Base. close (g:: EventGroup )
225
235
for fd in g. fds
226
236
ccall (:close , Cint, (Cint,), fd)
227
237
end
228
238
end
229
239
230
- type PerfBench
231
- groups :: Vector{EventGroup}
240
+ mutable struct PerfBench
241
+ groups:: Vector{EventGroup}
232
242
end
233
- immutable Counter
234
- event :: EventType
235
- value :: UInt64
236
- enabled :: UInt64
237
- running :: UInt64
243
+
244
+ struct Counter
245
+ event:: EventType
246
+ value:: UInt64
247
+ enabled:: UInt64
248
+ running:: UInt64
238
249
end
239
- immutable Counters
240
- counters :: Vector{Counter}
250
+
251
+ struct Counters
252
+ counters:: Vector{Counter}
241
253
end
254
+
242
255
function Base. show (io:: IO , c:: Counters )
256
+ println (io)
243
257
for c in c. counters
244
- print (io, c. event, " : " )
258
+ print (io, c. event, " : " )
245
259
if c. enabled == 0
246
260
print (io, " never enabled" )
247
261
elseif c. running == 0
248
262
print (io, " did not run" )
249
263
else
250
264
@printf (io, " \n\t %20d (%.1f %%)" , Int64 (c. value), 100 * (c. running/ c. enabled))
251
265
end
252
- println ()
266
+ println (io )
253
267
end
254
268
end
269
+
255
270
enable! (b:: PerfBench ) = foreach (enable!, b. groups)
256
271
disable! (b:: PerfBench ) = foreach (disable!, b. groups)
257
272
reset! (b:: PerfBench ) = foreach (reset!, b. groups)
273
+
258
274
function counters (b:: PerfBench )
259
- c = Array ( Counter, 0 )
275
+ c = Counter[]
260
276
for g in b. groups
261
- values = read (g. leader_io, UInt64, length (g)+ 1 + 2 )
262
- @assert (length (g) == values[1 ])
277
+ values = Vector {UInt64} (undef, length (g)+ 1 + 2 )
278
+ read! (g. leader_io, values)
279
+ # ?Ref@assert(length(g) == values[1])
263
280
enabled, running = values[2 ], values[3 ]
264
281
for i = 1 : length (g)
265
282
push! (c, Counter (g. event_types[i], values[3 + i],
@@ -268,17 +285,6 @@ function counters(b::PerfBench)
268
285
end
269
286
Counters (c)
270
287
end
271
- function make_bench (x)
272
- groups = Array (EventGroup, 0 )
273
- for y in x
274
- if isa (y, EventType)
275
- push! (groups, EventGroup ([y]))
276
- else
277
- push! (groups, EventGroup (y))
278
- end
279
- end
280
- PerfBench (groups)
281
- end
282
288
283
289
const reasonable_defaults =
284
290
[EventType (:hw , :cycles ),
@@ -297,4 +303,18 @@ const reasonable_defaults =
297
303
[EventType(:cache, :L1_data, :write, :access),
298
304
EventType(:cache, :L1_data, :write, :miss)]=# ]
299
305
306
+ function make_bench (x)
307
+ groups = EventGroup[]
308
+ for y in x
309
+ if isa (y, EventType)
310
+ push! (groups, EventGroup ([y]))
311
+ else
312
+ push! (groups, EventGroup (y))
313
+ end
314
+ end
315
+ PerfBench (groups)
316
+ end
317
+
318
+ make_bench () = make_bench (reasonable_defaults)
319
+
300
320
end
0 commit comments