Skip to content

Commit 1e01c8e

Browse files
add Profile.@count_lock_conflicts
1 parent 5b6a94d commit 1e01c8e

File tree

3 files changed

+28
-1
lines changed

3 files changed

+28
-1
lines changed

base/atomics.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ end
8080

8181
Atomic() = Atomic{Int}()
8282

83+
LOCK_CONFLICT_COUNT = Threads.Atomic{Int}(0);
84+
8385
"""
8486
Threads.atomic_cas!(x::Atomic{T}, cmp::T, newval::T) where T
8587

base/lock.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,9 @@ end
134134
return false
135135
end
136136

137+
LOCK_PROFILING::Bool = false
138+
inc_lock_conflict_count() = Threads.atomic_add!(Threads.LOCK_CONFLICT_COUNT, 1)
139+
137140
"""
138141
lock(lock)
139142
@@ -145,6 +148,7 @@ Each `lock` must be matched by an [`unlock`](@ref).
145148
"""
146149
@inline function lock(rl::ReentrantLock)
147150
trylock(rl) || (@noinline function slowlock(rl::ReentrantLock)
151+
LOCK_PROFILING && inc_lock_conflict_count()
148152
c = rl.cond_wait
149153
lock(c.lock)
150154
try

stdlib/Profile/src/Profile.jl

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Profiling support.
1010
- `Profile.print()` to print the report.
1111
- `Profile.clear()` to clear the buffer.
1212
- Send a $(Sys.isbsd() ? "SIGINFO (ctrl-t)" : "SIGUSR1") signal to the process to automatically trigger a profile and print.
13+
- `@count_lock_conflicts foo()` to count how many times a task had to wait to acquire a lock.
1314
1415
## Memory profiling
1516
- `Profile.Allocs.@profile [sample_rate=0.1] foo()` to sample allocations within a specific call. A sample rate of 1.0 will record everything; 0.0 will record nothing.
@@ -44,7 +45,7 @@ const nmeta = 4 # number of metadata fields per block (threadid, taskid, cpu_cyc
4445
# deprecated functions: use `getdict` instead
4546
lookup(ip::UInt) = lookup(convert(Ptr{Cvoid}, ip))
4647

47-
export @profile
48+
export @profile, @count_lock_conflicts
4849

4950
"""
5051
@profile
@@ -63,6 +64,26 @@ macro profile(ex)
6364
end
6465
end
6566

67+
68+
"""
69+
@count_lock_conflicts
70+
71+
`count_lock_conflicts <expression>` runs your expression while monitoring how many times a task had to wait
72+
to acquire a lock.
73+
"""
74+
macro count_lock_conflicts(ex)
75+
return quote
76+
Base.LOCK_PROFILING = true
77+
Threads.LOCK_CONFLICT_COUNT[] = 0
78+
try
79+
$(esc(ex))
80+
finally
81+
Base.LOCK_PROFILING = false
82+
end
83+
println("$(Threads.LOCK_CONFLICT_COUNT[]) lock conflicts")
84+
end
85+
end
86+
6687
# An internal function called to show the report after an information request (SIGINFO or SIGUSR1).
6788
function _peek_report()
6889
iob = IOBuffer()

0 commit comments

Comments
 (0)