Skip to content

Add profiling hooks #336

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
May 26, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions benches/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ publish = false

[features]
_single_precision = []
profiling = []

# deps

Expand Down
10 changes: 9 additions & 1 deletion benches/src/cut_edges.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use honeycomb::{
prelude::{CMap2, CMapBuilder, CoordsFloat, DartIdType, EdgeIdType},
};

use crate::{cli::CutEdgesArgs, utils::hash_file};
use crate::{cli::CutEdgesArgs, prof_start, prof_stop, utils::hash_file};

// const MAX_RETRY: u8 = 10;

Expand Down Expand Up @@ -64,8 +64,10 @@ pub fn bench_cut_edges<T: CoordsFloat>(args: CutEdgesArgs) -> CMap2<T> {

let mut step = 0;
print!(" {step:>4} "); // Step
prof_start!("HCBENCH_CUTS");

// compute first batch
prof_start!("HCBENCH_CUTS_COMPUTE");
instant = Instant::now();
let mut edges: Vec<EdgeIdType> = map.iter_edges().collect();
print!("| {:>12} ", edges.len()); // n_edge_total
Expand All @@ -83,11 +85,13 @@ pub fn bench_cut_edges<T: CoordsFloat>(args: CutEdgesArgs) -> CMap2<T> {
print!("| {n_e:>17} "); // n_edge_to_process
let mut nd = map.add_free_darts(6 * n_e); // 2 for edge split + 2*2 for new edges in neighbor tets
let mut darts: Vec<DartIdType> = (nd..nd + 6 * n_e as DartIdType).collect();
prof_stop!("HCBENCH_CUTS_COMPUTE");
print!("| {:>18.6e} ", instant.elapsed().as_secs_f64()); // t_compute_batch

// while there are edges to cut
while !edges.is_empty() {
// process batch
prof_start!("HCBENCH_CUTS_PROCESS");
instant = Instant::now();
let n_retry = match args.backend {
crate::cli::Backend::RayonIter => dispatch_rayon(&map, &mut edges, &darts),
Expand All @@ -98,6 +102,7 @@ pub fn bench_cut_edges<T: CoordsFloat>(args: CutEdgesArgs) -> CMap2<T> {
dispatch_std_threads(&map, &mut edges, &darts, n_threads)
}
};
prof_stop!("HCBENCH_CUTS_PROCESS");
print!("| {:>18.6e} ", instant.elapsed().as_secs_f64()); // t_process_batch
println!("| {n_retry:>15}",); // n_transac_retry

Expand All @@ -110,6 +115,7 @@ pub fn bench_cut_edges<T: CoordsFloat>(args: CutEdgesArgs) -> CMap2<T> {
// compute the new batch
step += 1;
print!(" {step:>4} "); // Step
prof_start!("HCBENCH_CUTS_COMPUTE");
instant = Instant::now();
edges.extend(map.iter_edges());
print!("| {:>12} ", edges.len()); // n_edge_total
Expand All @@ -128,6 +134,7 @@ pub fn bench_cut_edges<T: CoordsFloat>(args: CutEdgesArgs) -> CMap2<T> {
nd = map.add_free_darts(6 * n_e);
darts.par_drain(..); // is there a better way?
darts.extend(nd..nd + 6 * n_e as DartIdType);
prof_stop!("HCBENCH_CUTS_COMPUTE");
if n_e != 0 {
print!("| {:>18.6e} ", instant.elapsed().as_secs_f64()); // t_compute_batch
} else {
Expand All @@ -136,6 +143,7 @@ pub fn bench_cut_edges<T: CoordsFloat>(args: CutEdgesArgs) -> CMap2<T> {
println!("| {:>15}", 0); // n_transac_retry
}
}
prof_stop!("HCBENCH_CUTS");

map
}
Expand Down
6 changes: 6 additions & 0 deletions benches/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use honeycomb_benches::{
cut_edges::bench_cut_edges,
grid_gen::bench_generate_2d_grid,
grisubal::bench_grisubal,
prof_init, prof_start, prof_stop,
remesh::bench_remesh,
shift::bench_shift,
};
Expand All @@ -23,13 +24,18 @@ fn main() {
}

fn run_benchmarks<T: CoordsFloat>(cli: Cli) {
prof_init!();

prof_start!("HCBENCH");
let map: CMap2<T> = match cli.benches {
Benches::Generate2dGrid(args) => bench_generate_2d_grid(args),
Benches::CutEdges(args) => bench_cut_edges(args),
Benches::Grisubal(args) => bench_grisubal(args),
Benches::Remesh(args) => bench_remesh(args),
Benches::Shift(args) => bench_shift(args),
};
prof_stop!("HCBENCH");

// all bench currently generate a map,
// we may have to move this to match arms if this changes
if let Some(f) = cli.save_as {
Expand Down
12 changes: 11 additions & 1 deletion benches/src/remesh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use honeycomb::{
stm::{StmClosureResult, Transaction, abort, atomically, atomically_with_err, retry},
};

use crate::{cli::RemeshArgs, utils::hash_file};
use crate::{cli::RemeshArgs, prof_start, prof_stop, utils::hash_file};

pub fn bench_remesh<T: CoordsFloat>(args: RemeshArgs) -> CMap2<T> {
let input_map = args.input.to_str().unwrap();
Expand Down Expand Up @@ -44,6 +44,7 @@ pub fn bench_remesh<T: CoordsFloat>(args: RemeshArgs) -> CMap2<T> {

// -- triangulation
instant = Instant::now();
prof_start!("HCBENCH_REMESH_TRIANGULATION");
let n_tot = map
.iter_faces()
.map(|id| (map.orbit(OrbitPolicy::Face, id as DartIdType).count() - 3) * 2)
Expand Down Expand Up @@ -96,6 +97,7 @@ pub fn bench_remesh<T: CoordsFloat>(args: RemeshArgs) -> CMap2<T> {
}
});
let triangulation_time = instant.elapsed();
prof_stop!("HCBENCH_REMESH_TRIANGULATION");

// check that the mesh is triangular, consistently oriented and fully classified
debug_assert!(
Expand Down Expand Up @@ -145,12 +147,14 @@ pub fn bench_remesh<T: CoordsFloat>(args: RemeshArgs) -> CMap2<T> {
// b. cut / collapse
// c. swap
// check for ending condition after each relax
prof_start!("HCBENCH_REMESH_MAINLOOP");
let mut n = 0;
let mut r;
loop {
print!("{:>5}", n);

// -- relax
prof_start!("HCBENCH_REMESH_RELAX");
instant = Instant::now();
r = 0;
loop {
Expand Down Expand Up @@ -182,6 +186,7 @@ pub fn bench_remesh<T: CoordsFloat>(args: RemeshArgs) -> CMap2<T> {
break;
}
}
prof_stop!("HCBENCH_REMESH_RELAX");
print!(" | {:>14.6e}", instant.elapsed().as_secs_f64());

debug_assert!(
Expand Down Expand Up @@ -228,6 +233,7 @@ pub fn bench_remesh<T: CoordsFloat>(args: RemeshArgs) -> CMap2<T> {
print!(" | {:>17.6e}", instant.elapsed().as_secs_f64());

// -- cut / collapse
prof_start!("HCBENCH_REMESH_CC");
instant = Instant::now();
for e in edges_to_process {
if map.is_unused(e as DartIdType) {
Expand Down Expand Up @@ -308,9 +314,11 @@ pub fn bench_remesh<T: CoordsFloat>(args: RemeshArgs) -> CMap2<T> {
}
}
}
prof_stop!("HCBENCH_REMESH_CC");
print!(" | {:>16.6e}", instant.elapsed().as_secs_f64());

// -- swap
prof_start!("HCBENCH_REMESH_SWAP");
instant = Instant::now();
for (e, diff) in map
.iter_edges()
Expand Down Expand Up @@ -367,6 +375,7 @@ pub fn bench_remesh<T: CoordsFloat>(args: RemeshArgs) -> CMap2<T> {
);
}
}
prof_stop!("HCBENCH_REMESH_SWAP");
println!(" | {:>8.6e}", instant.elapsed().as_secs_f64());

debug_assert!(map.iter_faces().all(|f| {
Expand All @@ -379,6 +388,7 @@ pub fn bench_remesh<T: CoordsFloat>(args: RemeshArgs) -> CMap2<T> {
break;
}
}
prof_stop!("HCBENCH_REMESH_MAINLOOP");

debug_assert!(map.iter_faces().all(|f| {
map.orbit(OrbitPolicy::FaceLinear, f).count() == 3
Expand Down
3 changes: 3 additions & 0 deletions benches/src/shift.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ use honeycomb::prelude::{

use crate::cli::ShiftArgs;
use crate::utils::hash_file;
use crate::{prof_start, prof_stop};

pub fn bench_shift<T: CoordsFloat>(args: ShiftArgs) -> CMap2<T> {
let mut instant = std::time::Instant::now();
Expand All @@ -45,6 +46,7 @@ pub fn bench_shift<T: CoordsFloat>(args: ShiftArgs) -> CMap2<T> {
};
let build_time = instant.elapsed();

prof_start!("HCBENCH_SHIFT");
if args.no_conflict {
todo!("TODO: require a partitioning algorithm")
} else {
Expand Down Expand Up @@ -117,6 +119,7 @@ pub fn bench_shift<T: CoordsFloat>(args: ShiftArgs) -> CMap2<T> {
}
}
}
prof_stop!("HCBENCH_SHIFT");

map
}
69 changes: 69 additions & 0 deletions benches/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,72 @@ pub fn hash_file(path: &str) -> Result<u64, std::io::Error> {

Ok(hasher.finish())
}

#[cfg(feature = "profiling")]
pub static mut PERF_FIFO: Option<File> = None;

/// Attempt to open a fifo at the path `/tmp/hc_perf_control`.
///
/// This macro doesn't generate any code if the `profiling` feature is disabled.
#[macro_export]
macro_rules! prof_init {
() => {
#[cfg(feature = "profiling")]
{
unsafe {
$crate::utils::PERF_FIFO = Some(
std::fs::OpenOptions::new()
.write(true)
.open("/tmp/hc_perf_control")
.expect("Failed to open FIFO"),
);
}
}
};
}

/// Write to the `/tmp/hc_perf_control` to enable perf sampling if `${$var}` is defined.
///
/// This macro doesn't generate any code if the `profiling` feature is disabled.
#[macro_export]
macro_rules! prof_start {
($var: literal) => {
#[cfg(feature = "profiling")]
{
// use an env variable to select profiled section
if std::env::var_os($var).is_some() {
use std::io::Write;
unsafe {
if let Some(ref mut f) = $crate::utils::PERF_FIFO {
f.write_all(b"enable\n")
.expect("E: failed to write to FIFO");
f.flush().expect("E: failed to flush FIFO");
}
}
}
}
};
}

/// Write to the `/tmp/hc_perf_control` to disable perf sampling if `${$var}` is defined.
///
/// This macro doesn't generate any code if the `profiling` feature is disabled.
#[macro_export]
macro_rules! prof_stop {
($var: literal) => {
#[cfg(feature = "profiling")]
{
// use an env variable to select profiled section
if std::env::var_os($var).is_some() {
use std::io::Write;
unsafe {
if let Some(ref mut f) = $crate::utils::PERF_FIFO {
f.write_all(b"disable\n")
.expect("E: failed to write to FIFO");
f.flush().expect("E: failed to flush FIFO");
}
}
}
}
};
}
Loading