use std::time::{SystemTime, UNIX_EPOCH};
#[inline]
pub fn now_ms() -> u64 {
SystemTime::now()
.duration_since(UNIX_EPOCH)
.map(|d| d.as_millis() as u64)
.unwrap_or(0)
}
#[cfg(target_os = "android")]
mod sink {
use std::ffi::CString;
const ANDROID_LOG_INFO: i32 = 4;
extern "C" {
fn __android_log_write(prio: i32, tag: *const u8, msg: *const u8) -> i32;
}
pub fn write(tag: &str, msg: &str) {
if let (Ok(t), Ok(m)) = (CString::new(tag), CString::new(msg)) {
unsafe {
__android_log_write(
ANDROID_LOG_INFO,
t.as_ptr() as *const u8,
m.as_ptr() as *const u8,
);
}
}
}
pub fn enabled() -> bool {
cfg!(debug_assertions) || option_env!("IRIS_PERF_LOG").is_some()
}
}
#[cfg(not(target_os = "android"))]
mod sink {
use std::sync::OnceLock;
pub fn enabled() -> bool {
static ENABLED: OnceLock<bool> = OnceLock::new();
*ENABLED.get_or_init(|| {
std::env::var("IRIS_PERF_LOG")
.map(|value| {
let value = value.trim().to_ascii_lowercase();
!value.is_empty() && value != "0" && value != "false" && value != "off"
})
.unwrap_or(false)
})
}
pub fn write(tag: &str, msg: &str) {
eprintln!("{tag}: {msg}");
}
}
#[macro_export]
macro_rules! perflog {
($($arg:tt)*) => {
$crate::perflog::__write(format_args!($($arg)*))
};
}
#[doc(hidden)]
pub fn __write(args: std::fmt::Arguments<'_>) {
if !sink::enabled() {
return;
}
let msg = format!("{} {}", now_ms(), args);
sink::write("IrisPerf", &msg);
}