add: internal timers

This commit is contained in:
2025-12-05 21:40:23 +01:00
parent 2c36198ba8
commit 3f64295fb5

View File

@@ -113,15 +113,22 @@ pub mod dl {
} }
pub mod loader { pub mod loader {
use std::time::{Duration, Instant};
use crate::dl::Handle; use crate::dl::Handle;
pub type ChallengeFn<T> = unsafe extern "Rust" fn(&[u8]) -> T; pub type ChallengeFn<T> = unsafe extern "Rust" fn(&[u8]) -> T;
pub type TimedChallengeFn<T> = unsafe extern "Rust" fn(&[u8], &Instant) -> T;
pub enum FnVariant { pub enum FnVariant {
Isize(ChallengeFn<isize>), Isize(ChallengeFn<isize>),
Usize(ChallengeFn<usize>), Usize(ChallengeFn<usize>),
IsizeDuple(ChallengeFn<(isize, isize)>), IsizeDuple(ChallengeFn<(isize, isize)>),
UsizeDuple(ChallengeFn<(usize, usize)>), UsizeDuple(ChallengeFn<(usize, usize)>),
TIsize(TimedChallengeFn<isize>),
TUsize(TimedChallengeFn<usize>),
TIsizeDuple(TimedChallengeFn<(isize, isize)>),
TUsizeDuple(TimedChallengeFn<(usize, usize)>),
} }
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
@@ -146,7 +153,7 @@ pub mod loader {
/// # Safety /// # Safety
/// ///
/// Calls external arbitrary FNs. /// Calls external arbitrary FNs.
pub unsafe fn call(&self, buf: &[u8]) -> FnRetVariant { pub unsafe fn call(&self, buf: &[u8], instant: &Instant) -> FnRetVariant {
use FnRetVariant as R; use FnRetVariant as R;
use FnVariant as V; use FnVariant as V;
@@ -155,6 +162,26 @@ pub mod loader {
V::Usize(f) => unsafe { R::Usize((f)(buf)) }, V::Usize(f) => unsafe { R::Usize((f)(buf)) },
V::IsizeDuple(f) => unsafe { R::IsizeDuple((f)(buf)) }, V::IsizeDuple(f) => unsafe { R::IsizeDuple((f)(buf)) },
V::UsizeDuple(f) => unsafe { R::UsizeDuple((f)(buf)) }, V::UsizeDuple(f) => unsafe { R::UsizeDuple((f)(buf)) },
V::TIsize(f) => unsafe { R::Isize((f)(buf, instant)) },
V::TUsize(f) => unsafe { R::Usize((f)(buf, instant)) },
V::TIsizeDuple(f) => unsafe { R::IsizeDuple((f)(buf, instant)) },
V::TUsizeDuple(f) => unsafe { R::UsizeDuple((f)(buf, instant)) },
}
}
/// # Safety
///
/// Calls external arbitrary FNs.
pub unsafe fn call_notimer(&self, buf: &[u8]) -> Option<FnRetVariant> {
use FnRetVariant as R;
use FnVariant as V;
match self {
V::Isize(f) => Some(unsafe { R::Isize((f)(buf)) }),
V::Usize(f) => Some(unsafe { R::Usize((f)(buf)) }),
V::IsizeDuple(f) => Some(unsafe { R::IsizeDuple((f)(buf)) }),
V::UsizeDuple(f) => Some(unsafe { R::UsizeDuple((f)(buf)) }),
_ => None,
} }
} }
} }
@@ -171,6 +198,7 @@ pub mod loader {
use ChallengeFn as C; use ChallengeFn as C;
use FnVariant as V; use FnVariant as V;
use TimedChallengeFn as TC;
// SAFETY: This is actually safe as it just creates the fn ptr, no weird fn with weird // SAFETY: This is actually safe as it just creates the fn ptr, no weird fn with weird
// drop. // drop.
@@ -185,8 +213,29 @@ pub mod loader {
.map(V::UsizeDuple) .map(V::UsizeDuple)
); );
untry!(unsafe { handle.symfn::<TC<isize>>(c"challenge_t_isize") }.map(V::TIsize));
untry!(unsafe { handle.symfn::<TC<usize>>(c"challenge_t_usize") }.map(V::TUsize));
untry!(
unsafe { handle.symfn::<TC<(isize, isize)>>(c"challenge_t_isize_duple") }
.map(V::TIsizeDuple)
);
untry!(
unsafe { handle.symfn::<TC<(usize, usize)>>(c"challenge_t_usize_duple") }
.map(V::TUsizeDuple)
);
None None
} }
pub fn load_timers_from(handle: &Handle) -> Option<&[(&str, Duration)]> {
// SAFETY: This is actually safe as it just creates the fn ptr, no weird fn with weird
// drop.
let at = unsafe { handle.sym::<(&str, Duration)>(c"TIMERS") }?;
let len = unsafe { handle.sym::<usize>(c"TIMERS_LEN") }?;
let len = unsafe { *len.as_ref() };
Some(unsafe { std::slice::from_raw_parts(at.as_ptr(), len) })
}
} }
pub mod performer { pub mod performer {
@@ -240,18 +289,23 @@ fn main() -> io::Result<()> {
let challenge = dl::open(so_path).expect("Couldn't load dyn library"); let challenge = dl::open(so_path).expect("Couldn't load dyn library");
let challenge_main = loader::load_fn_from(&challenge).expect(concat!( let challenge_main = loader::load_fn_from(&challenge).expect(concat!(
"Didn't find any appropiate symbol in the compiled .so file. Make sure there is one and is ", "Didn't find any appropiate symbol in the compiled .so file. Make sure there is one.",
stringify!(unsafe extern "Rust" fn(&[u8]) -> isize)
)); ));
let start = Instant::now(); let start = Instant::now();
let result = unsafe { challenge_main.call(&input) }; let result = unsafe { challenge_main.call(&input, &start) };
println!( println!(
"done in {:#?} and yielded result {:?}", "done in {:#?} and yielded result {:?}",
start.elapsed(), start.elapsed(),
result result
); );
if let Some(timers) = loader::load_timers_from(&challenge) {
println!("with timers:");
for (name, timer) in timers {
println!(" '{name}': {timer:#?}");
}
}
Ok(()) Ok(())
} }
@@ -260,10 +314,10 @@ const STUB_ISIZE: loader::FnVariant = loader::FnVariant::make_noop_stub_isize();
fn measure_noop_overhead() -> (time::Duration, time::Duration) { fn measure_noop_overhead() -> (time::Duration, time::Duration) {
let timer = Instant::now(); let timer = Instant::now();
// SAFETY: completely safe, not arbitrary fn but our stub // SAFETY: completely safe, not arbitrary fn but our stub
unsafe { STUB_ISIZE.call(&[]) }; unsafe { STUB_ISIZE.call(&[], &timer) };
let cold = timer.elapsed(); let cold = timer.elapsed();
let hot = performer::get_avg_runt(u16::MAX.into(), || unsafe { let hot = performer::get_avg_runt(u16::MAX.into(), || unsafe {
STUB_ISIZE.call(&[]); STUB_ISIZE.call_notimer(&[]);
}); });
(cold, hot) (cold, hot)