/locktick

Automated lock accounting & profiling

Primary LanguageRustCreative Commons Zero v1.0 UniversalCC0-1.0

locktick

crates.io docs.rs actively developed

locktick provides the means to measure things like the average guard duration and wait time for different kinds of locks, just by substituting the applicable locks' imports.

Example use

use std::{thread, time::Duration};

use locktick::lock_snapshots;

fn print_active_guards() {
    thread::spawn(|| {
        loop {
            let mut locks = lock_snapshots();
            locks.sort_unstable_by(|l1, l2| l1.location.cmp(&l2.location));

            // Check if any of the known guards are currently active.
            if locks.iter().flat_map(|lock| lock.known_guards.values()).all(|g| g.num_active_uses() == 0) {
                // It's possible that the program is halted for reasons different than a deadlock; print
                // something in order to ensure that the lock accounting thread is operational at all times.
                println!("there are no active guards");
            } else {
                println!("\nthere are active guards:");

                // Traverse all the known locks.
                for lock in locks {
                    // Collec the data on all the known guards of the given lock.
                    let mut active_guards = lock.known_guards.values().filter(|g| g.num_active_uses() != 0).collect::<Vec<_>>();
                    // Skip a lock if none of its known guards are currently active.
                    if active_guards.is_empty() {
                        continue;
                    }
                    active_guards.sort_unstable_by(|g1, g2| g1.location.cmp(&g2.location));

                    println!("{}:", lock.location);
                    // Traverse the known guards of the given lock.
                    for guard in &active_guards {
                        let location = &guard.location;
                        let kind = guard.kind;
                        let num_uses = guard.num_uses;
                        let avg_duration = guard.avg_duration();
                        let avg_wait_time = guard.avg_wait_time();
                        // Log the desired details.
                        println!(
                            "- {location} ({:?}): used {num_uses} time(s) so far; avg duration: {:?}; avg wait: {:?}",
                            kind, avg_duration, avg_wait_time
                        );
                    }
                }
            }
            // Check for active guards every 1 second.
            thread::sleep(Duration::from_secs(1));
        }
    });
}

status

  • the basic functionalities are complete
  • API breakage can still happen
  • some of the TODOs include additional tests, examples, and improvements to documentation