use alloc::boxed::Box;
use core::fmt::Display;
pub use cubecl_environment::time::{Duration, Instant};
use cubecl_environment::future::DynFut;
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
pub enum TimingMethod {
System,
Device,
}
impl Display for TimingMethod {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
TimingMethod::System => f.write_str("system"),
TimingMethod::Device => f.write_str("device"),
}
}
}
#[derive(Debug)]
pub struct ProfileTicks {
start: Instant,
end: Instant,
}
impl ProfileTicks {
pub fn from_start_end(start: Instant, end: Instant) -> Self {
Self { start, end }
}
pub fn duration(&self) -> Duration {
self.end.duration_since(self.start)
}
pub fn start_duration_since(&self, epoch: Instant) -> Duration {
self.start.duration_since(epoch)
}
pub fn end_duration_since(&self, epoch: Instant) -> Duration {
self.end.duration_since(epoch)
}
}
pub struct ProfileDuration {
future: DynFut<ProfileTicks>,
method: TimingMethod,
}
impl ProfileDuration {
pub fn timing_method(&self) -> TimingMethod {
self.method
}
pub fn new(future: DynFut<ProfileTicks>, method: TimingMethod) -> ProfileDuration {
Self { future, method }
}
pub fn new_system_time(start: Instant, end: Instant) -> Self {
Self::new(
Box::pin(async move { ProfileTicks::from_start_end(start, end) }),
TimingMethod::System,
)
}
pub fn new_device_time(
future: impl Future<Output = ProfileTicks> + Send + 'static,
) -> ProfileDuration {
Self::new(Box::pin(future), TimingMethod::Device)
}
pub fn into_future(self) -> DynFut<ProfileTicks> {
self.future
}
pub async fn resolve(self) -> ProfileTicks {
self.future.await
}
}