Skip to content

Commit 34055ab

Browse files
authored
Merge pull request #21 from lqd/stats
Add Variable statistics
2 parents be7b63a + 12f0d57 commit 34055ab

File tree

1 file changed

+46
-3
lines changed

1 file changed

+46
-3
lines changed

src/lib.rs

+46-3
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use std::cell::RefCell;
1515
use std::cmp::Ordering;
16+
use std::io::Write;
1617
use std::iter::FromIterator;
1718
use std::rc::Rc;
1819

@@ -200,25 +201,32 @@ impl<Tuple: Ord> std::ops::Deref for Relation<Tuple> {
200201
/// An `Iteration` tracks monotonic variables, and monitors their progress.
201202
/// It can inform the user if they have ceased changing, at which point the
202203
/// computation should be done.
204+
#[derive(Default)]
203205
pub struct Iteration {
204206
variables: Vec<Box<dyn VariableTrait>>,
207+
round: u32,
208+
debug_stats: Option<Box<dyn Write>>,
205209
}
206210

207211
impl Iteration {
208212
/// Create a new iterative context.
209213
pub fn new() -> Self {
210-
Iteration {
211-
variables: Vec::new(),
212-
}
214+
Self::default()
213215
}
214216
/// Reports whether any of the monitored variables have changed since
215217
/// the most recent call.
216218
pub fn changed(&mut self) -> bool {
219+
self.round += 1;
220+
217221
let mut result = false;
218222
for variable in self.variables.iter_mut() {
219223
if variable.changed() {
220224
result = true;
221225
}
226+
227+
if let Some(ref mut stats_writer) = self.debug_stats {
228+
variable.dump_stats(self.round, stats_writer);
229+
}
222230
}
223231
result
224232
}
@@ -238,12 +246,25 @@ impl Iteration {
238246
self.variables.push(Box::new(variable.clone()));
239247
variable
240248
}
249+
250+
/// Set up this Iteration to write debug statistics about each variable,
251+
/// for each round of the computation.
252+
pub fn record_stats_to(&mut self, mut w: Box<dyn Write>) {
253+
// print column names header
254+
writeln!(w, "Variable,Round,Stable count,Recent count")
255+
.expect("Couldn't write debug stats CSV header");
256+
257+
self.debug_stats = Some(w);
258+
}
241259
}
242260

243261
/// A type that can report on whether it has changed.
244262
trait VariableTrait {
245263
/// Reports whether the variable has changed since it was last asked.
246264
fn changed(&mut self) -> bool;
265+
266+
/// Dumps statistics about the variable internals, for debug and profiling purposes.
267+
fn dump_stats(&self, round: u32, w: &mut dyn Write);
247268
}
248269

249270
/// An monotonically increasing set of `Tuple`s.
@@ -554,6 +575,28 @@ impl<Tuple: Ord> VariableTrait for Variable<Tuple> {
554575

555576
!self.recent.borrow().is_empty()
556577
}
578+
579+
fn dump_stats(&self, round: u32, w: &mut dyn Write) {
580+
let mut stable_count = 0;
581+
for tuple in self.stable.borrow().iter() {
582+
stable_count += tuple.len();
583+
}
584+
585+
writeln!(
586+
w,
587+
"{:?},{},{},{}",
588+
self.name,
589+
round,
590+
stable_count,
591+
self.recent.borrow().len()
592+
)
593+
.unwrap_or_else(|e| {
594+
panic!(
595+
"Couldn't write stats for variable {}, round {}: {}",
596+
self.name, round, e
597+
)
598+
});
599+
}
557600
}
558601

559602
// impl<Tuple: Ord> Drop for Variable<Tuple> {

0 commit comments

Comments
 (0)