use std::time::{Duration, Instant};
#[derive(Debug, Clone, Default)]
pub struct ParsingStats {
pub total_duration: Duration,
pub triple_count: usize,
pub token_count: usize,
pub bytes_processed: usize,
pub start_time: Option<Instant>,
pub end_time: Option<Instant>,
}
impl ParsingStats {
pub fn new() -> Self {
Self::default()
}
pub fn start(&mut self) {
self.start_time = Some(Instant::now());
}
pub fn stop(&mut self) {
self.end_time = Some(Instant::now());
if let (Some(start), Some(end)) = (self.start_time, self.end_time) {
self.total_duration = end.duration_since(start);
}
}
pub fn triples_per_second(&self) -> f64 {
if self.total_duration.as_secs_f64() > 0.0 {
self.triple_count as f64 / self.total_duration.as_secs_f64()
} else {
0.0
}
}
pub fn bytes_per_second(&self) -> f64 {
if self.total_duration.as_secs_f64() > 0.0 {
self.bytes_processed as f64 / self.total_duration.as_secs_f64()
} else {
0.0
}
}
pub fn mb_per_second(&self) -> f64 {
self.bytes_per_second() / (1024.0 * 1024.0)
}
pub fn report(&self) -> String {
format!(
"Parsing Statistics:\n\
- Duration: {:.3}s\n\
- Triples: {}\n\
- Tokens: {}\n\
- Bytes: {} ({:.2} MB)\n\
- Throughput: {:.0} triples/s\n\
- Speed: {:.2} MB/s",
self.total_duration.as_secs_f64(),
self.triple_count,
self.token_count,
self.bytes_processed,
self.bytes_processed as f64 / (1024.0 * 1024.0),
self.triples_per_second(),
self.mb_per_second()
)
}
}
pub struct TtlProfiler {
pub stats: ParsingStats,
enabled: bool,
}
impl TtlProfiler {
pub fn new() -> Self {
Self {
stats: ParsingStats::new(),
enabled: true,
}
}
pub fn disabled() -> Self {
Self {
stats: ParsingStats::new(),
enabled: false,
}
}
pub fn enable(&mut self) {
self.enabled = true;
}
pub fn disable(&mut self) {
self.enabled = false;
}
pub fn is_enabled(&self) -> bool {
self.enabled
}
pub fn start(&mut self) {
if self.enabled {
self.stats.start();
}
}
pub fn stop(&mut self) {
if self.enabled {
self.stats.stop();
}
}
pub fn record_triple(&mut self) {
if self.enabled {
self.stats.triple_count += 1;
}
}
pub fn record_triples(&mut self, count: usize) {
if self.enabled {
self.stats.triple_count += count;
}
}
pub fn record_token(&mut self) {
if self.enabled {
self.stats.token_count += 1;
}
}
pub fn record_bytes(&mut self, bytes: usize) {
if self.enabled {
self.stats.bytes_processed += bytes;
}
}
pub fn statistics(&self) -> &ParsingStats {
&self.stats
}
pub fn report(&self) -> String {
self.stats.report()
}
pub fn reset(&mut self) {
self.stats = ParsingStats::new();
}
}
impl Default for TtlProfiler {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::thread;
use std::time::Duration;
#[test]
fn test_parsing_stats() {
let mut stats = ParsingStats::new();
stats.triple_count = 1000;
stats.bytes_processed = 50000;
stats.start();
thread::sleep(Duration::from_millis(100));
stats.stop();
assert!(stats.total_duration.as_millis() >= 100);
assert!(stats.triples_per_second() > 0.0);
assert!(stats.bytes_per_second() > 0.0);
let report = stats.report();
assert!(report.contains("1000"));
assert!(report.contains("triples/s"));
}
#[test]
fn test_profiler() {
let mut profiler = TtlProfiler::new();
assert!(profiler.is_enabled());
profiler.start();
profiler.record_triples(100);
profiler.record_bytes(5000);
profiler.stop();
assert_eq!(profiler.statistics().triple_count, 100);
assert_eq!(profiler.statistics().bytes_processed, 5000);
}
#[test]
fn test_disabled_profiler() {
let mut profiler = TtlProfiler::disabled();
assert!(!profiler.is_enabled());
profiler.start();
profiler.record_triples(100);
profiler.stop();
assert_eq!(profiler.statistics().triple_count, 0);
assert_eq!(profiler.statistics().total_duration.as_secs(), 0);
}
#[test]
fn test_enable_disable() {
let mut profiler = TtlProfiler::new();
profiler.disable();
assert!(!profiler.is_enabled());
profiler.enable();
assert!(profiler.is_enabled());
}
#[test]
fn test_reset() {
let mut profiler = TtlProfiler::new();
profiler.record_triples(50);
profiler.record_bytes(1000);
assert_eq!(profiler.statistics().triple_count, 50);
profiler.reset();
assert_eq!(profiler.statistics().triple_count, 0);
assert_eq!(profiler.statistics().bytes_processed, 0);
}
}