forked from openzfs/zfs
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
measure zettacache::Locked acquisition and hold times (openzfs#478)
Add 2 new macros to the `measure` infrastructure: `lock_measured!(&tokio::sync::Mutex)` and `lock_non_send_measured!(&tokio::sync::Mutex)`. These macros measure the lock acquision time, count, and number of in-flight waiters; as well as the lock hold time and number of in-flight holders (which is at most one). Use this infrastructure to measure the `zettacache::Locked` lock for all acquirers. Remove the now-unused `lock_non_send()` function in favor of `lock_non_send_measured!()`.
- Loading branch information
Showing
7 changed files
with
214 additions
and
75 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
use std::ops::Deref; | ||
use std::ops::DerefMut; | ||
use std::time::Instant; | ||
|
||
use super::Measurement; | ||
|
||
pub struct MeasuredMutexGuard<'a, T> { | ||
inner: tokio::sync::MutexGuard<'a, T>, | ||
begin: Instant, | ||
hold: &'static Measurement, | ||
} | ||
|
||
impl<'a, T> Drop for MeasuredMutexGuard<'a, T> { | ||
fn drop(&mut self) { | ||
self.hold.end_timed(self.begin); | ||
} | ||
} | ||
|
||
impl<'a, T> Deref for MeasuredMutexGuard<'a, T> { | ||
type Target = T; | ||
fn deref(&self) -> &Self::Target { | ||
&self.inner | ||
} | ||
} | ||
|
||
impl<'a, T> DerefMut for MeasuredMutexGuard<'a, T> { | ||
fn deref_mut(&mut self) -> &mut Self::Target { | ||
&mut self.inner | ||
} | ||
} | ||
|
||
pub async fn lock<'a, T>( | ||
mutex: &'a tokio::sync::Mutex<T>, | ||
acquire: &'static Measurement, | ||
hold: &'static Measurement, | ||
) -> MeasuredMutexGuard<'a, T> { | ||
MeasuredMutexGuard { | ||
inner: acquire.fut_timed(mutex.lock()).await, | ||
hold, | ||
begin: hold.begin_timed(), | ||
} | ||
} | ||
|
||
/// This locks the mutex like `Mutex::lock()`, but measures the time spent waiting for the lock, | ||
/// and the time spent holding the lock. | ||
#[macro_export] | ||
macro_rules! lock_measured { | ||
($lock:expr, $tag:literal) => {{ | ||
static ACQUIRE: $crate::measure::Measurement = $crate::measure::Measurement::new(concat!( | ||
"acquire lock ", | ||
$tag, | ||
" (", | ||
file!(), | ||
":", | ||
line!(), | ||
":", | ||
column!(), | ||
")" | ||
)); | ||
ACQUIRE.register(); | ||
static HOLD: $crate::measure::Measurement = $crate::measure::Measurement::new(concat!( | ||
"hold lock ", | ||
$tag, | ||
" (", | ||
file!(), | ||
":", | ||
line!(), | ||
":", | ||
column!(), | ||
")" | ||
)); | ||
HOLD.register(); | ||
|
||
$crate::measure::lock::lock($lock, &ACQUIRE, &HOLD) | ||
}}; | ||
($lock:expr) => { | ||
$crate::lock_measured!($lock, "") | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
use std::marker::PhantomData; | ||
use std::ops::Deref; | ||
use std::ops::DerefMut; | ||
|
||
use super::lock::MeasuredMutexGuard; | ||
use super::Measurement; | ||
|
||
pub struct NonSendMeasuredMutexGuard<'a, T> { | ||
inner: MeasuredMutexGuard<'a, T>, | ||
_marker: PhantomData<*const ()>, | ||
} | ||
|
||
impl<'a, T> Deref for NonSendMeasuredMutexGuard<'a, T> { | ||
type Target = T; | ||
fn deref(&self) -> &Self::Target { | ||
&self.inner | ||
} | ||
} | ||
|
||
impl<'a, T> DerefMut for NonSendMeasuredMutexGuard<'a, T> { | ||
fn deref_mut(&mut self) -> &mut Self::Target { | ||
&mut self.inner | ||
} | ||
} | ||
|
||
pub async fn lock_non_send<'a, T>( | ||
mutex: &'a tokio::sync::Mutex<T>, | ||
acquire: &'static Measurement, | ||
hold: &'static Measurement, | ||
) -> NonSendMeasuredMutexGuard<'a, T> { | ||
NonSendMeasuredMutexGuard { | ||
inner: super::lock::lock(mutex, acquire, hold).await, | ||
_marker: PhantomData, | ||
} | ||
} | ||
|
||
/// This locks the mutex like `Mutex::lock()`, but measures it (like `lock_measured!`), and | ||
/// returns a new kind of guard which can not be sent between threads. This is useful if you | ||
/// want to ensure that .await is not used while the mutex is locked by some callers, but .await | ||
/// can be used from other callers (that use `lock_measured!` or `tokio::sync::Mutex::lock()` | ||
/// directly). | ||
#[macro_export] | ||
macro_rules! lock_non_send_measured { | ||
($lock:expr, $tag:literal) => {{ | ||
static ACQUIRE: $crate::measure::Measurement = $crate::measure::Measurement::new(concat!( | ||
"acquire lock non send", | ||
$tag, | ||
" (", | ||
file!(), | ||
":", | ||
line!(), | ||
":", | ||
column!(), | ||
")" | ||
)); | ||
ACQUIRE.register(); | ||
static HOLD: $crate::measure::Measurement = $crate::measure::Measurement::new(concat!( | ||
"hold lock non send", | ||
$tag, | ||
" (", | ||
file!(), | ||
":", | ||
line!(), | ||
":", | ||
column!(), | ||
")" | ||
)); | ||
HOLD.register(); | ||
|
||
$crate::measure::lock_non_send::lock_non_send($lock, &ACQUIRE, &HOLD) | ||
}}; | ||
($lock:expr) => { | ||
$crate::lock_non_send_measured!($lock, "") | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.