1313
1414use std:: cell:: RefCell ;
1515use std:: cmp:: Ordering ;
16+ use std:: io:: Write ;
1617use std:: iter:: FromIterator ;
1718use 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 ) ]
203205pub struct Iteration {
204206 variables : Vec < Box < dyn VariableTrait > > ,
207+ round : u32 ,
208+ debug_stats : Option < Box < dyn Write > > ,
205209}
206210
207211impl 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.
244262trait 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