13
13
14
14
use std:: cell:: RefCell ;
15
15
use std:: cmp:: Ordering ;
16
+ use std:: io:: Write ;
16
17
use std:: iter:: FromIterator ;
17
18
use std:: rc:: Rc ;
18
19
@@ -200,25 +201,32 @@ impl<Tuple: Ord> std::ops::Deref for Relation<Tuple> {
200
201
/// An `Iteration` tracks monotonic variables, and monitors their progress.
201
202
/// It can inform the user if they have ceased changing, at which point the
202
203
/// computation should be done.
204
+ #[ derive( Default ) ]
203
205
pub struct Iteration {
204
206
variables : Vec < Box < dyn VariableTrait > > ,
207
+ round : u32 ,
208
+ debug_stats : Option < Box < dyn Write > > ,
205
209
}
206
210
207
211
impl Iteration {
208
212
/// Create a new iterative context.
209
213
pub fn new ( ) -> Self {
210
- Iteration {
211
- variables : Vec :: new ( ) ,
212
- }
214
+ Self :: default ( )
213
215
}
214
216
/// Reports whether any of the monitored variables have changed since
215
217
/// the most recent call.
216
218
pub fn changed ( & mut self ) -> bool {
219
+ self . round += 1 ;
220
+
217
221
let mut result = false ;
218
222
for variable in self . variables . iter_mut ( ) {
219
223
if variable. changed ( ) {
220
224
result = true ;
221
225
}
226
+
227
+ if let Some ( ref mut stats_writer) = self . debug_stats {
228
+ variable. dump_stats ( self . round , stats_writer) ;
229
+ }
222
230
}
223
231
result
224
232
}
@@ -238,12 +246,25 @@ impl Iteration {
238
246
self . variables . push ( Box :: new ( variable. clone ( ) ) ) ;
239
247
variable
240
248
}
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
+ }
241
259
}
242
260
243
261
/// A type that can report on whether it has changed.
244
262
trait VariableTrait {
245
263
/// Reports whether the variable has changed since it was last asked.
246
264
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 ) ;
247
268
}
248
269
249
270
/// An monotonically increasing set of `Tuple`s.
@@ -554,6 +575,28 @@ impl<Tuple: Ord> VariableTrait for Variable<Tuple> {
554
575
555
576
!self . recent . borrow ( ) . is_empty ( )
556
577
}
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
+ }
557
600
}
558
601
559
602
// impl<Tuple: Ord> Drop for Variable<Tuple> {
0 commit comments