diff --git a/circ_hc/src/hashconsing/example_u8.rs b/circ_hc/src/hashconsing/example_u8.rs index a30fc2fa..75e1ff37 100644 --- a/circ_hc/src/hashconsing/example_u8.rs +++ b/circ_hc/src/hashconsing/example_u8.rs @@ -49,6 +49,10 @@ impl crate::Table for Table { "hashconsing" } + fn for_each(f: impl FnMut(&u8, &[Self::Node])) { + panic!() + } + fn reserve(num_nodes: usize) { FACTORY.reserve(num_nodes); } diff --git a/circ_hc/src/hashconsing/macro_.rs b/circ_hc/src/hashconsing/macro_.rs index def52138..1ad72535 100644 --- a/circ_hc/src/hashconsing/macro_.rs +++ b/circ_hc/src/hashconsing/macro_.rs @@ -52,6 +52,10 @@ macro_rules! generate_hashcons_hashconsing { "hashconsing" } + fn for_each(f: impl FnMut(&$Op, &[Self::Node])) { + panic!() + } + fn reserve(num_nodes: usize) { FACTORY.reserve(num_nodes); } diff --git a/circ_hc/src/hashconsing/template.rs b/circ_hc/src/hashconsing/template.rs index 88127a54..0023eea3 100644 --- a/circ_hc/src/hashconsing/template.rs +++ b/circ_hc/src/hashconsing/template.rs @@ -50,6 +50,10 @@ impl crate::Table for Table { "hashconsing" } + fn for_each(f: impl FnMut(&TemplateOp, &[Self::Node])) { + panic!() + } + fn reserve(num_nodes: usize) { FACTORY.reserve(num_nodes); } diff --git a/circ_hc/src/lib.rs b/circ_hc/src/lib.rs index 0697a273..b6cec58a 100644 --- a/circ_hc/src/lib.rs +++ b/circ_hc/src/lib.rs @@ -39,6 +39,9 @@ pub trait Table { /// The name of the implementation fn name() -> &'static str; + /// Fun a function on every node + fn for_each(f: impl FnMut(&Op, &[Self::Node])); + /// When the table garbage-collects a node with ID `id`, it will call `f(id)`. `f(id)` might /// clear caches, etc., but instead of droping `Node`s, it should return them. /// diff --git a/circ_hc/src/raw/example_u8.rs b/circ_hc/src/raw/example_u8.rs index 6ffd0773..d71c3d0d 100644 --- a/circ_hc/src/raw/example_u8.rs +++ b/circ_hc/src/raw/example_u8.rs @@ -45,6 +45,10 @@ impl crate::Table for Table { "raw" } + fn for_each(mut f: impl FnMut(&u8, &[Self::Node])) { + MANAGER.with(|man| man.table.borrow().keys().for_each(|n| f(&n.op, &n.cs))); + } + fn reserve(num_nodes: usize) { MANAGER.with(|man| man.table.borrow_mut().reserve(num_nodes)) } diff --git a/circ_hc/src/raw/macro_.rs b/circ_hc/src/raw/macro_.rs index eb431603..c11f1898 100644 --- a/circ_hc/src/raw/macro_.rs +++ b/circ_hc/src/raw/macro_.rs @@ -48,6 +48,10 @@ macro_rules! generate_hashcons_raw { "raw" } + fn for_each(mut f: impl FnMut(&$Op, &[Self::Node])) { + MANAGER.with(|man| man.table.borrow().keys().for_each(|n| f(&n.op, &n.cs))); + } + fn reserve(num_nodes: usize) { MANAGER.with(|man| man.table.borrow_mut().reserve(num_nodes)) } diff --git a/circ_hc/src/raw/template.rs b/circ_hc/src/raw/template.rs index 1f24cea0..2287d400 100644 --- a/circ_hc/src/raw/template.rs +++ b/circ_hc/src/raw/template.rs @@ -45,6 +45,10 @@ impl crate::Table for Table { "raw" } + fn for_each(mut f: impl FnMut(&TemplateOp, &[Self::Node])) { + MANAGER.with(|man| man.table.borrow().keys().for_each(|n| f(&n.op, &n.cs))); + } + fn reserve(num_nodes: usize) { MANAGER.with(|man| man.table.borrow_mut().reserve(num_nodes)) } diff --git a/circ_hc/src/rc/example_u8.rs b/circ_hc/src/rc/example_u8.rs index 37576cb6..9ad9c00a 100644 --- a/circ_hc/src/rc/example_u8.rs +++ b/circ_hc/src/rc/example_u8.rs @@ -69,6 +69,10 @@ impl crate::Table for Table { "rc" } + fn for_each(mut f: impl FnMut(&u8, &[Self::Node])) { + MANAGER.with(|man| man.table.borrow().keys().for_each(|n| f(&n.op, &n.cs))); + } + fn reserve(num_nodes: usize) { MANAGER.with(|man| man.table.borrow_mut().reserve(num_nodes)) } diff --git a/circ_hc/src/rc/macro_.rs b/circ_hc/src/rc/macro_.rs index a4b8b9c7..ec846a9b 100644 --- a/circ_hc/src/rc/macro_.rs +++ b/circ_hc/src/rc/macro_.rs @@ -72,6 +72,10 @@ macro_rules! generate_hashcons_rc { "rc" } + fn for_each(mut f: impl FnMut(&$Op, &[Self::Node])) { + MANAGER.with(|man| man.table.borrow().keys().for_each(|n| f(&n.op, &n.cs))); + } + fn reserve(num_nodes: usize) { MANAGER.with(|man| man.table.borrow_mut().reserve(num_nodes)) } diff --git a/circ_hc/src/rc/template.rs b/circ_hc/src/rc/template.rs index b82a1712..924865bd 100644 --- a/circ_hc/src/rc/template.rs +++ b/circ_hc/src/rc/template.rs @@ -69,6 +69,10 @@ impl crate::Table for Table { "rc" } + fn for_each(mut f: impl FnMut(&TemplateOp, &[Self::Node])) { + MANAGER.with(|man| man.table.borrow().keys().for_each(|n| f(&n.op, &n.cs))); + } + fn reserve(num_nodes: usize) { MANAGER.with(|man| man.table.borrow_mut().reserve(num_nodes)) } diff --git a/src/ir/term/extras.rs b/src/ir/term/extras.rs index 5fba4ab2..7f754125 100644 --- a/src/ir/term/extras.rs +++ b/src/ir/term/extras.rs @@ -161,3 +161,35 @@ pub fn array_elements(t: &Term) -> Vec { pub fn array_to_tuple(t: &Term) -> Term { term(Op::Tuple, array_elements(t)) } + +/// Print operator stats +pub fn dump_op_stats() { + use std::mem::size_of; + println!("Op size: {}bytes", size_of::()); + let mut counts: FxHashMap = FxHashMap::default(); + let mut children: FxHashMap = FxHashMap::default(); + let add = |map: &mut FxHashMap, key: &Op, value: usize| { + if let Some(present_value) = map.get_mut(key) { + *present_value += value; + } else { + map.insert(key.clone(), value); + } + }; + hc::Table::for_each(|op, cs| { + add(&mut counts, op, 1); + add(&mut children, op, cs.len()); + }); + let mut vector = Vec::new(); + for k in counts.keys() { + let ct = *counts.get(k).unwrap(); + let cs_ct = *children.get(k).unwrap(); + let ave = cs_ct as f64 / ct as f64; + vector.push((k.clone(), ct, cs_ct, ave)); + } + vector.sort_by_key(|t| t.1); + for (k, ct, cs_ct, ave) in vector { + let mem = size_of::() * ct + size_of::>() * ct + size_of::() * cs_ct; + let s: String = format!("{k}"); + println!("Op {s:>20}, Count {ct:>8}, Children {cs_ct:>8}, Ave {ave:>8.2}, Mem {mem:>20}"); + } +}