1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
use std::mem;
use std::time::Instant;

use crate::global::{begin, begin_time, end, gen_id, get_id, queue_mutex, BenchData};

fn ts_of(instant: Instant) -> f32 {
    (instant.duration_since(begin_time()).as_nanos() as f32) / 1000.0
}

fn enqueue(data: BenchData) {
    let mut lock = queue_mutex();
    lock.push(data);
}

pub fn _log(log: String) {
    let ts = ts_of(Instant::now());
    let tid = get_id();

    enqueue(BenchData::Log { log, ts, tid });
}

fn bench(name: String, ts: f32) {
    let dur = ts_of(Instant::now()) - ts;
    let tid = get_id();

    enqueue(BenchData::Bench { name, ts, dur, tid });
}

pub fn _count(name: String, data: Vec<(String, f32)>) {
    let ts = ts_of(Instant::now());
    let tid = get_id();

    enqueue(BenchData::Count {
        name,
        data,
        ts,
        tid,
    });
}

/// Starts a benchmarking scope on creation and ends it on drop
///
/// TimeScope saves the Instant it was created. When dropped it
/// saves the benchmarking results to the file.
///
/// Using [scope!] macro instead of this struct is recommened.
///
/// [scope!]: macro.scope.html
pub struct TimeScope {
    start: f32,
    name: String,
}

impl TimeScope {
    pub fn new(name: String) -> TimeScope {
        gen_id();
        TimeScope {
            start: ts_of(Instant::now()),
            name,
        }
    }
}

impl Drop for TimeScope {
    fn drop(&mut self) {
        bench(mem::replace(&mut self.name, String::new()), self.start);
    }
}

/// Instantiates global data on creation and deinstantiates it on drop
///
/// This struct instantiates global data upon creation
/// and deinstantiates it upon drop.
///
/// Using [instantiate!] macro instead of this struct is recommened.
///
/// [instantiate!]: macro.instantiate.html
pub struct Instantiator(&'static str, bool);

impl Instantiator {
    /// Constructs the instantiator
    pub fn new(folder: &'static str) -> Instantiator {
        begin();
        Instantiator(folder, true)
    }

    /// Deinstantiates global variables
    ///
    /// This method is used when Instantiator is never dropped
    pub fn end(&mut self) {
        if self.1 {
            self.1 = false;
            end(self.0);
        }
    }
}

impl Drop for Instantiator {
    fn drop(&mut self) {
        end(self.0);
    }
}