#[cfg(feature = "measurements")]
use std::sync::{
mpsc::{channel, Receiver, Sender},
Mutex,
};
use std::time::Duration;
#[cfg(feature = "measurements")]
use lazy_static::lazy_static;
use serde::Serialize;
#[cfg(feature = "measurements")]
lazy_static! {
pub static ref OP_MEASUREMENTS: (
Mutex<Option<Sender<OpMeasurement>>>,
Mutex<Receiver<OpMeasurement>>
) = {
let (tx, rx) = channel();
(Mutex::new(Some(tx)), Mutex::new(rx))
};
}
#[derive(Debug, Serialize)]
#[serde(rename_all = "kebab-case")]
pub struct OpMeasurement {
pub op: Operation,
pub cpu_time: Duration,
pub wall_time: Duration,
}
#[derive(Debug, Serialize)]
#[serde(rename_all = "kebab-case")]
pub enum Operation {
AddPiece,
GeneratePieceCommitment,
GenerateTreeC,
GenerateTreeRLast,
CommD,
EncodeWindowTimeAll,
WindowCommLeavesTime,
PorepCommitTime,
PostInclusionProofs,
PostFinalizeTicket,
PostReadChallengedRange,
PostPartialTicketHash,
}
#[cfg(feature = "measurements")]
pub fn measure_op<T, F>(op: Operation, f: F) -> T
where
F: FnOnce() -> T,
{
use std::time::Instant;
let cpu_time_start = cpu_time::ProcessTime::now();
let wall_start_time = Instant::now();
#[cfg(feature = "profile")]
gperftools::profiler::PROFILER
.lock()
.unwrap()
.start(format!("./{:?}.profile", op))
.unwrap();
let x = f();
#[cfg(feature = "profile")]
gperftools::profiler::PROFILER
.lock()
.unwrap()
.stop()
.unwrap();
let opt_tx = OP_MEASUREMENTS
.0
.lock()
.expect("acquire lock on tx side of perf channel");
if let Some(tx) = opt_tx.as_ref() {
tx.clone()
.send(OpMeasurement {
op,
cpu_time: cpu_time_start.elapsed(),
wall_time: wall_start_time.elapsed(),
})
.expect("failed to send to perf channel");
}
x
}
#[cfg(not(feature = "measurements"))]
pub fn measure_op<T, F>(_: Operation, f: F) -> T
where
F: FnOnce() -> T,
{
f()
}