@@ -195,11 +195,11 @@ function time_print(io::IO, elapsedtime, bytes=0, gctime=0, allocs=0, lock_confl
195
195
nothing
196
196
end
197
197
198
- function timev_print (elapsedtime, diff:: GC_Diff , compile_times; msg:: Union{String,Nothing} = nothing )
198
+ function timev_print (elapsedtime, diff:: GC_Diff , lock_conflicts, compile_times; msg:: Union{String,Nothing} = nothing )
199
199
allocs = gc_alloc_count (diff)
200
200
compile_time = first (compile_times)
201
201
recompile_time = last (compile_times)
202
- time_print (stdout , elapsedtime, diff. allocd, diff. total_time, allocs, compile_time, recompile_time, true ; msg)
202
+ time_print (stdout , elapsedtime, diff. allocd, diff. total_time, allocs, lock_conflicts, compile_time, recompile_time, true ; msg)
203
203
padded_nonzero_print (elapsedtime, " elapsed time (ns)" )
204
204
padded_nonzero_print (diff. total_time, " gc time (ns)" )
205
205
padded_nonzero_print (diff. allocd, " bytes allocated" )
231
231
A macro to execute an expression, printing the time it took to execute, the number of
232
232
allocations, and the total number of bytes its execution caused to be allocated, before
233
233
returning the value of the expression. Any time spent garbage collecting (gc), compiling
234
- new code, or recompiling invalidated code is shown as a percentage.
234
+ new code, or recompiling invalidated code is shown as a percentage. Any lock conflicts
235
+ where a lock had to wait are shown as a count.
235
236
236
237
Optionally provide a description string to print before the time report.
237
238
@@ -252,6 +253,9 @@ See also [`@showtime`](@ref), [`@timev`](@ref), [`@timed`](@ref), [`@elapsed`](@
252
253
253
254
Recompilation time being shown separately from compilation time was introduced in Julia 1.8
254
255
256
+ !!! compat "Julia 1.11"
257
+ The reporting of any lock conflicts was added in Julia 1.11.
258
+
255
259
```julia-repl
256
260
julia> x = rand(10,10);
257
261
@@ -373,18 +377,22 @@ end
373
377
macro timev (msg, ex)
374
378
quote
375
379
Experimental. @force_compile
380
+ Threads. lock_profiling (true )
381
+ local lock_conflicts = Threads. LOCK_CONFLICT_COUNT[]
376
382
local stats = gc_num ()
377
383
local elapsedtime = time_ns ()
378
384
cumulative_compile_timing (true )
379
385
local compile_elapsedtimes = cumulative_compile_time_ns ()
380
386
local val = @__tryfinally ($ (esc (ex)),
381
387
(elapsedtime = time_ns () - elapsedtime;
382
388
cumulative_compile_timing (false );
383
- compile_elapsedtimes = cumulative_compile_time_ns () .- compile_elapsedtimes)
389
+ compile_elapsedtimes = cumulative_compile_time_ns () .- compile_elapsedtimes;
390
+ lock_conflicts = Threads. LOCK_CONFLICT_COUNT[] - lock_conflicts;
391
+ Threads. lock_profiling (false ))
384
392
)
385
393
local diff = GC_Diff (gc_num (), stats)
386
394
local _msg = $ (esc (msg))
387
- timev_print (elapsedtime, diff, compile_elapsedtimes; msg= _msg)
395
+ timev_print (elapsedtime, diff, lock_conflicts, compile_elapsedtimes; msg= _msg)
388
396
val
389
397
end
390
398
end
@@ -478,6 +486,41 @@ macro allocations(ex)
478
486
end
479
487
end
480
488
489
+ """
490
+ @lock_conflicts
491
+
492
+ A macro to evaluate an expression, discard the resulting value, and instead return the
493
+ total number of lock conflicts during evalution, where a lock attempt resulted in a wait
494
+ because the lock was already held.
495
+
496
+ See also [`@time`](@ref), [`@timev`](@ref) and [`@timed`](@ref).
497
+
498
+ ```julia-repl
499
+ julia> @lock_conflicts begin
500
+ l = ReentrantLock()
501
+ Threads.@threads for i in 1:Threads.nthreads()
502
+ lock(l) do
503
+ sleep(1)
504
+ end
505
+ end
506
+ end
507
+ 5
508
+ ```
509
+
510
+ !!! compat "Julia 1.11"
511
+ This macro was added in Julia 1.11.
512
+ """
513
+ macro lock_conflicts (ex)
514
+ quote
515
+ Experimental. @force_compile
516
+ Threads. lock_profiling (true )
517
+ local lock_conflicts = Threads. LOCK_CONFLICT_COUNT[]
518
+ $ (esc (ex))
519
+ Threads. lock_profiling (false )
520
+ Threads. LOCK_CONFLICT_COUNT[] - lock_conflicts
521
+ end
522
+ end
523
+
481
524
"""
482
525
@timed
483
526
@@ -513,15 +556,23 @@ julia> stats.gcstats.total_time
513
556
514
557
!!! compat "Julia 1.5"
515
558
The return type of this macro was changed from `Tuple` to `NamedTuple` in Julia 1.5.
559
+
560
+ !!! compat "Julia 1.11"
561
+ The field `lock_conflicts` was added to the returned NamedTuple in Julia 1.11.
516
562
"""
517
563
macro timed (ex)
518
564
quote
519
565
Experimental. @force_compile
566
+ Threads. lock_profiling (true )
567
+ local lock_conflicts = Threads. LOCK_CONFLICT_COUNT[]
520
568
local stats = gc_num ()
521
569
local elapsedtime = time_ns ()
522
- local val = $ (esc (ex))
523
- elapsedtime = time_ns () - elapsedtime
570
+ local val = @__tryfinally ($ (esc (ex)),
571
+ (elapsedtime = time_ns () - elapsedtime;
572
+ lock_conflicts = Threads. LOCK_CONFLICT_COUNT[] - lock_conflicts;
573
+ Threads. lock_profiling (false ))
574
+ )
524
575
local diff = GC_Diff (gc_num (), stats)
525
- (value= val, time= elapsedtime/ 1e9 , bytes= diff. allocd, gctime= diff. total_time/ 1e9 , gcstats= diff)
576
+ (value= val, time= elapsedtime/ 1e9 , bytes= diff. allocd, gctime= diff. total_time/ 1e9 , gcstats= diff, lock_conflicts = lock_conflicts )
526
577
end
527
578
end
0 commit comments