From 0f394e13d8c9a3a3d8de2f902194e570894eea72 Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Fri, 20 Apr 2018 14:01:38 +0800 Subject: [PATCH 01/11] csv-format: top --- Cargo.lock | 47 +++++++++++++++- analyze/Cargo.toml | 4 +- analyze/analyze.rs | 56 +++++++++++++++++++- traits/Cargo.toml | 1 + traits/traits.rs | 23 ++++++-- twiggy/tests/expectations/top_2_csv | 5 ++ twiggy/tests/expectations/top_2_csv_retained | 5 ++ twiggy/tests/tests.rs | 34 ++++++++++++ 8 files changed, 166 insertions(+), 9 deletions(-) create mode 100644 twiggy/tests/expectations/top_2_csv create mode 100644 twiggy/tests/expectations/top_2_csv_retained diff --git a/Cargo.lock b/Cargo.lock index 1cb63f7a..284b51f7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -87,6 +87,23 @@ dependencies = [ "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "csv" +version = "1.0.0-beta.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "csv-core 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "csv-core" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "diff" version = "0.1.11" @@ -146,6 +163,22 @@ name = "libc" version = "0.2.40" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "log" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "log" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "memchr" version = "2.0.1" @@ -154,6 +187,11 @@ dependencies = [ "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "num-traits" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "ordermap" version = "0.3.5" @@ -264,7 +302,6 @@ dependencies = [ name = "strsim" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "structopt" version = "0.2.8" @@ -366,7 +403,9 @@ dependencies = [ name = "twiggy-analyze" version = "0.1.0" dependencies = [ - "petgraph 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "csv 1.0.0-beta.5 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "twiggy-ir 0.1.0", "twiggy-opt 0.1.0", "twiggy-traits 0.1.0", @@ -406,6 +445,7 @@ dependencies = [ name = "twiggy-traits" version = "0.1.0" dependencies = [ + "csv 1.0.0-beta.5 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "parity-wasm 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)", "twiggy-ir 0.1.0", @@ -549,7 +589,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c069bbec61e1ca5a596166e55dfe4773ff745c3d16b700013bcaff9a6df2c682" "checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d" "checksum libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)" = "6fd41f331ac7c5b8ac259b8bf82c75c0fb2e469bbf37d2becbba9a6a2221965b" +"checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" +"checksum log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "89f010e843f2b1a31dbd316b3b8d443758bc634bed37aabade59c686d644e0a2" "checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d" +"checksum num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dee092fcdf725aee04dd7da1d21debff559237d49ef1cb3e69bcb8ece44c7364" "checksum ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a86ed3f5f244b372d6b1a00b72ef7f8876d0bc6a78a4c9985c53614041512063" "checksum parity-wasm 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)" = "79df7454d764da3aaf4e8f696e5c4b97eb82b47abfc89850bfdcf7badfad357e" "checksum petgraph 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "8b30dc85588cd02b9b76f5e386535db546d21dc68506cff2abebee0b6445e8e4" diff --git a/analyze/Cargo.toml b/analyze/Cargo.toml index ef8db122..fb560fa0 100644 --- a/analyze/Cargo.toml +++ b/analyze/Cargo.toml @@ -15,4 +15,6 @@ path = "./analyze.rs" twiggy-ir = { version = "0.1.0", path = "../ir" } twiggy-opt = { version = "0.1.0", path = "../opt", default-features = false } twiggy-traits = { version = "0.1.0", path = "../traits" } -petgraph = "0.4.12" +csv = "1.0.0-beta.5" +serde = "1.0.40" +serde_derive = "1.0.40" diff --git a/analyze/analyze.rs b/analyze/analyze.rs index 723e54e2..d3e96d0c 100644 --- a/analyze/analyze.rs +++ b/analyze/analyze.rs @@ -3,7 +3,9 @@ #![deny(missing_docs)] #![deny(missing_debug_implementations)] -extern crate petgraph; +extern crate csv; +#[macro_use] +extern crate serde_derive; extern crate twiggy_ir as ir; extern crate twiggy_opt as opt; extern crate twiggy_traits as traits; @@ -178,6 +180,46 @@ impl traits::Emit for Top { Ok(()) } + + fn emit_csv(&self, items: &ir::Items, dest: &mut io::Write) -> Result<(), traits::Error> { + let mut wtr = csv::Writer::from_writer(dest); + + #[derive(Debug, Serialize)] + struct Record { + name: String, + shallow_size: u32, + shallow_size_percent: f64, + retained_size: Option, + retained_size_percent: Option, + } + + for &id in &self.items { + let item = &items[id]; + + let (shallow_size, shallow_size_percent) = { + let size = item.size(); + let size_percent = (size as f64) / (items.size() as f64) * 100.0; + (size, size_percent) + }; + let (retained_size, retained_size_percent) = if self.opts.retained { + let size = items.retained_size(id); + let size_percent = (size as f64) / (items.size() as f64) * 100.0; + (Some(size), Some(size_percent)) + } else { + (None, None) + }; + + wtr.serialize(Record { + name: item.name().to_string(), + shallow_size: shallow_size, + shallow_size_percent: shallow_size_percent, + retained_size: retained_size, + retained_size_percent: retained_size_percent, + })?; + wtr.flush()?; + } + Ok(()) + } } /// Run the `top` analysis on the given IR items. @@ -353,6 +395,10 @@ impl traits::Emit for DominatorTree { let mut obj = json::object(dest)?; recursive_add_children(items, &self.opts, &self.tree, self.root_id, &mut obj) } + + fn emit_csv(&self, _items: &ir::Items, _dest: &mut io::Write) -> Result<(), traits::Error> { + unimplemented!(); + } } /// Compute the dominator tree for the given IR graph. @@ -527,6 +573,10 @@ impl traits::Emit for Paths { Ok(()) } + + fn emit_csv(&self, _items: &ir::Items, _dest: &mut io::Write) -> Result<(), traits::Error> { + unimplemented!(); + } } /// Find all retaining paths for the given items. @@ -677,6 +727,10 @@ impl traits::Emit for Monos { Ok(()) } + + fn emit_csv(&self, _items: &ir::Items, _dest: &mut io::Write) -> Result<(), traits::Error> { + unimplemented!(); + } } /// Find bloaty monomorphizations of generic functions. diff --git a/traits/Cargo.toml b/traits/Cargo.toml index c912887e..8c72cd41 100644 --- a/traits/Cargo.toml +++ b/traits/Cargo.toml @@ -15,3 +15,4 @@ path = "./traits.rs" failure = "0.1.1" parity-wasm = "0.28.0" twiggy-ir = { version = "0.1.0", path = "../ir" } +csv = "1.0.0-beta.5" diff --git a/traits/traits.rs b/traits/traits.rs index 87f9bcea..f1a46ba6 100644 --- a/traits/traits.rs +++ b/traits/traits.rs @@ -3,6 +3,7 @@ #![deny(missing_docs)] #![deny(missing_debug_implementations)] +extern crate csv; #[macro_use] extern crate failure; @@ -49,6 +50,9 @@ enum ErrorInner { #[fail(display = "formatting error: {}", _0)] Fmt(#[cause] fmt::Error), + + #[fail(display = "CSV error: {}", _0)] + Csv(#[cause] csv::Error), } impl From for Error { @@ -75,6 +79,14 @@ impl From for Error { } } +impl From for Error { + fn from(e: csv::Error) -> Error { + Error { + inner: Box::new(ErrorInner::Csv(e)), + } + } +} + impl Error { /// Create an error with the given message. pub fn with_msg>(msg: S) -> Error { @@ -111,8 +123,8 @@ pub enum OutputFormat { // /// Graphviz dot format. // Dot, - // /// Comma-separated values (CSV) format. - // Csv, + /// Comma-separated values (CSV) format. + Csv, /// JavaScript Object Notation format. Json, } @@ -130,6 +142,7 @@ impl FromStr for OutputFormat { match s { "text" => Ok(OutputFormat::Text), "json" => Ok(OutputFormat::Json), + "csv" => Ok(OutputFormat::Csv), _ => Err(Error::with_msg(format!("Unknown output format: {}", s))), } } @@ -149,7 +162,7 @@ pub trait Emit { OutputFormat::Text => self.emit_text(items, destination), // OutputFormat::Html => self.emit_html(destination), // OutputFormat::Dot => self.emit_dot(destination), - // OutputFormat::Csv => self.emit_csv(destination), + OutputFormat::Csv => self.emit_csv(items, destination), OutputFormat::Json => self.emit_json(items, destination), } } @@ -163,8 +176,8 @@ pub trait Emit { // /// Emit Graphviz's dot format. // fn emit_dot(&self, destination: &mut io::Write) -> Result<(), Error>; - // /// Emit CSV. - // fn emit_csv(&self, destination: &mut io::Write) -> Result<(), Error>; + /// Emit CSV. + fn emit_csv(&self, items: &ir::Items, destination: &mut io::Write) -> Result<(), Error>; /// Emit JSON. fn emit_json(&self, items: &ir::Items, destination: &mut io::Write) -> Result<(), Error>; diff --git a/twiggy/tests/expectations/top_2_csv b/twiggy/tests/expectations/top_2_csv new file mode 100644 index 00000000..4ddfdc84 --- /dev/null +++ b/twiggy/tests/expectations/top_2_csv @@ -0,0 +1,5 @@ +name,shallow_size,shallow_size_percent,retained_size,retained_size_percent +data[3],1034,36.7057152999645,, +"""function names"" subsection",774,27.47603833865815,, +wee_alloc::alloc_first_fit::h9a72de3af77ef93f,225,7.987220447284344,, +hello,164,5.8217962371317,, diff --git a/twiggy/tests/expectations/top_2_csv_retained b/twiggy/tests/expectations/top_2_csv_retained new file mode 100644 index 00000000..d5aeb4d7 --- /dev/null +++ b/twiggy/tests/expectations/top_2_csv_retained @@ -0,0 +1,5 @@ +name,shallow_size,shallow_size_percent,retained_size,retained_size_percent +data[3],1034,36.7057152999645,1034,36.7057152999645 +"""function names"" subsection",774,27.47603833865815,774,27.47603833865815 +"export ""hello""",8,0.2839900603478878,573,20.340788072417464 +func[8],1,0.03549875754348598,565,20.056798012069578 diff --git a/twiggy/tests/tests.rs b/twiggy/tests/tests.rs index 8116c4fa..c4f43779 100644 --- a/twiggy/tests/tests.rs +++ b/twiggy/tests/tests.rs @@ -241,6 +241,40 @@ test!( "json" ); +test!( + top_2_csv, + "top", + "./fixtures/wee_alloc.wasm", + "-n", + "4", + "-f", + "csv" +); + +test!( + top_2_csv_retained, + "top", + "./fixtures/wee_alloc.wasm", + "--retained", + "-n", + "4", + "-f", + "csv" +); + +test!( + paths_json, + "paths", + "./fixtures/wee_alloc.wasm", + "wee_alloc::alloc_first_fit::h9a72de3af77ef93f", + "hello", + "goodbye", + "-d", + "3", + "-f", + "json" +); + test!( issue_16, "paths", From 14a842d060dc635f8db794d0983e40e8f1040bd9 Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Wed, 25 Apr 2018 20:50:38 +0800 Subject: [PATCH 02/11] csv-format: refactor csv into mod --- Cargo.lock | 4 +++- analyze/analyze.rs | 17 +++++------------ analyze/csv.rs | 16 ++++++++++++++++ ir/Cargo.toml | 2 ++ ir/ir.rs | 3 ++- 5 files changed, 28 insertions(+), 14 deletions(-) create mode 100644 analyze/csv.rs diff --git a/Cargo.lock b/Cargo.lock index 284b51f7..8ddcb16a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -418,7 +418,9 @@ dependencies = [ "cpp_demangle 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", "frozen 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "petgraph 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] diff --git a/analyze/analyze.rs b/analyze/analyze.rs index d3e96d0c..f23a8906 100644 --- a/analyze/analyze.rs +++ b/analyze/analyze.rs @@ -3,13 +3,14 @@ #![deny(missing_docs)] #![deny(missing_debug_implementations)] -extern crate csv; +extern crate csv as csv_sys; #[macro_use] extern crate serde_derive; extern crate twiggy_ir as ir; extern crate twiggy_opt as opt; extern crate twiggy_traits as traits; +mod csv; mod json; use std::cmp; @@ -182,16 +183,7 @@ impl traits::Emit for Top { } fn emit_csv(&self, items: &ir::Items, dest: &mut io::Write) -> Result<(), traits::Error> { - let mut wtr = csv::Writer::from_writer(dest); - - #[derive(Debug, Serialize)] - struct Record { - name: String, - shallow_size: u32, - shallow_size_percent: f64, - retained_size: Option, - retained_size_percent: Option, - } + let mut wtr = csv_sys::Writer::from_writer(dest); for &id in &self.items { let item = &items[id]; @@ -209,12 +201,13 @@ impl traits::Emit for Top { (None, None) }; - wtr.serialize(Record { + wtr.serialize(csv::CsvRecord { name: item.name().to_string(), shallow_size: shallow_size, shallow_size_percent: shallow_size_percent, retained_size: retained_size, retained_size_percent: retained_size_percent, + ..Default::default() })?; wtr.flush()?; } diff --git a/analyze/csv.rs b/analyze/csv.rs new file mode 100644 index 00000000..5c4eddfe --- /dev/null +++ b/analyze/csv.rs @@ -0,0 +1,16 @@ +use ir::Id; + +#[derive(Debug, Default, Serialize)] +pub struct CsvRecord { + pub name: String, + pub shallow_size: u32, + pub shallow_size_percent: f64, + #[serde(skip_serializing_if = "Option::is_none")] + pub retained_size: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub retained_size_percent: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub next_dominator: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub path: Option +} \ No newline at end of file diff --git a/ir/Cargo.toml b/ir/Cargo.toml index 8a338e2e..33c7487d 100644 --- a/ir/Cargo.toml +++ b/ir/Cargo.toml @@ -16,3 +16,5 @@ cpp_demangle = { version = "0.2.7", default-features = false } frozen = "1" petgraph = "0.4.12" rustc-demangle = "0.1.5" +serde = "1.0.40" +serde_derive = "1.0.40" diff --git a/ir/ir.rs b/ir/ir.rs index 653d35c7..b2da2c5a 100644 --- a/ir/ir.rs +++ b/ir/ir.rs @@ -7,6 +7,7 @@ extern crate cpp_demangle; extern crate frozen; extern crate petgraph; extern crate rustc_demangle; +#[macro_use] extern crate serde_derive; mod graph_impl; @@ -368,7 +369,7 @@ impl<'a> Iterator for Iter<'a> { } /// An item's unique identifier. -#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)] pub struct Id(u32, u32); impl Id { From 545d8cd5a2f04aa82f7065f1e946b1c22b8e5579 Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Thu, 26 Apr 2018 11:49:07 +0800 Subject: [PATCH 03/11] csv-format: dominators --- analyze/analyze.rs | 47 ++++++++++++++++++- analyze/csv.rs | 6 +-- ir/ir.rs | 5 +- .../expectations/dominators_wee_alloc_csv | 19 ++++++++ twiggy/tests/expectations/top_2_csv | 10 ++-- twiggy/tests/tests.rs | 8 ++++ 6 files changed, 82 insertions(+), 13 deletions(-) create mode 100644 twiggy/tests/expectations/dominators_wee_alloc_csv diff --git a/analyze/analyze.rs b/analyze/analyze.rs index f23a8906..93ca8cd0 100644 --- a/analyze/analyze.rs +++ b/analyze/analyze.rs @@ -389,8 +389,51 @@ impl traits::Emit for DominatorTree { recursive_add_children(items, &self.opts, &self.tree, self.root_id, &mut obj) } - fn emit_csv(&self, _items: &ir::Items, _dest: &mut io::Write) -> Result<(), traits::Error> { - unimplemented!(); + fn emit_csv(&self, items: &ir::Items, dest: &mut io::Write) -> Result<(), traits::Error> { + let mut wtr = csv_sys::Writer::from_writer(dest); + fn recursive_add_children<'a>( + items: &ir::Items, + opts: &opt::Dominators, + dominator_tree: &BTreeMap>, + id: ir::Id, + wtr: &mut csv_sys::Writer<&mut io::Write> + ) -> Result<(), traits::Error> { + let item = &items[id]; + let (size, size_percent) = ( + item.size(), + (item.size() as f64) / (items.size() as f64) * 100.0, + ); + let (retained_size, retained_size_percent) = ( + items.retained_size(id), + (items.retained_size(id) as f64) / (items.size() as f64) * 100.0, + ); + + let rc = csv::CsvRecord { + id: Some(item.id().0), + name: item.name().to_string(), + shallow_size: size, + shallow_size_percent: size_percent, + retained_size: Some(retained_size), + retained_size_percent: Some(retained_size_percent), + // TODO CSMOE: find immediate dominator + immediate_dominator: Some(id.0), + ..Default::default() + }; + + wtr.serialize(rc)?; + wtr.flush()?; + if let Some(children) = dominator_tree.get(&id) { + let mut children: Vec<_> = children.iter().cloned().collect(); + children.sort_by(|a, b| items.retained_size(*b).cmp(&items.retained_size(*a))); + for child in children { + recursive_add_children(items, opts, dominator_tree, child, wtr)?; + } + } + Ok(()) + } + + recursive_add_children(items, &self.opts, &self.tree, items.meta_root(), &mut wtr)?; + Ok(()) } } diff --git a/analyze/csv.rs b/analyze/csv.rs index 5c4eddfe..83493410 100644 --- a/analyze/csv.rs +++ b/analyze/csv.rs @@ -1,7 +1,7 @@ -use ir::Id; - #[derive(Debug, Default, Serialize)] pub struct CsvRecord { + #[serde(skip_serializing_if = "Option::is_none")] + pub id: Option, pub name: String, pub shallow_size: u32, pub shallow_size_percent: f64, @@ -10,7 +10,7 @@ pub struct CsvRecord { #[serde(skip_serializing_if = "Option::is_none")] pub retained_size_percent: Option, #[serde(skip_serializing_if = "Option::is_none")] - pub next_dominator: Option, + pub immediate_dominator: Option, #[serde(skip_serializing_if = "Option::is_none")] pub path: Option } \ No newline at end of file diff --git a/ir/ir.rs b/ir/ir.rs index b2da2c5a..fabab8d0 100644 --- a/ir/ir.rs +++ b/ir/ir.rs @@ -7,7 +7,6 @@ extern crate cpp_demangle; extern crate frozen; extern crate petgraph; extern crate rustc_demangle; -#[macro_use] extern crate serde_derive; mod graph_impl; @@ -369,8 +368,8 @@ impl<'a> Iterator for Iter<'a> { } /// An item's unique identifier. -#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)] -pub struct Id(u32, u32); +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct Id(pub u32, u32); impl Id { /// Create an `Id` for a the given section. diff --git a/twiggy/tests/expectations/dominators_wee_alloc_csv b/twiggy/tests/expectations/dominators_wee_alloc_csv new file mode 100644 index 00000000..4be91093 --- /dev/null +++ b/twiggy/tests/expectations/dominators_wee_alloc_csv @@ -0,0 +1,19 @@ +id,name,shallow_size,shallow_size_percent,retained_size,retained_size_percent,immediate_dominator +4294967295,,0,0,1417,50.30173943911963,4294967295 +8,"""function names"" subsection",774,27.47603833865815,774,27.47603833865815,8 +4,"export ""hello""",8,0.2839900603478878,573,20.340788072417464,4 +1,func[8],1,0.03549875754348598,565,20.056798012069578,1 +6,hello,164,5.8217962371317,560,19.879304224352147,6 +1,func[2],1,0.03549875754348598,387,13.738019169329075,1 +6,wee_alloc::alloc_with_refill::hb32c1bbce9ebda8e,152,5.395811146609868,378,13.418530351437699,6 +1,func[3],1,0.03549875754348598,226,8.022719204827832,1 +6,wee_alloc::alloc_first_fit::h9a72de3af77ef93f,225,7.987220447284344,225,7.987220447284344,6 +0,type[4],8,0.2839900603478878,8,0.2839900603478878,0 +7,data[0],9,0.3194888178913738,9,0.3194888178913738,7 +0,type[5],4,0.1419950301739439,4,0.1419950301739439,0 +4,"export ""goodbye""",10,0.3549875754348598,59,2.0944266950656725,4 +1,func[9],1,0.03549875754348598,49,1.7394391196308128,1 +6,goodbye,44,1.5619453319133831,44,1.5619453319133831,6 +0,type[3],4,0.1419950301739439,4,0.1419950301739439,0 +4,"export ""memory""",9,0.3194888178913738,11,0.3904863329783458,4 +3,memory[0],2,0.07099751508697195,2,0.07099751508697195,3 diff --git a/twiggy/tests/expectations/top_2_csv b/twiggy/tests/expectations/top_2_csv index 4ddfdc84..45acd028 100644 --- a/twiggy/tests/expectations/top_2_csv +++ b/twiggy/tests/expectations/top_2_csv @@ -1,5 +1,5 @@ -name,shallow_size,shallow_size_percent,retained_size,retained_size_percent -data[3],1034,36.7057152999645,, -"""function names"" subsection",774,27.47603833865815,, -wee_alloc::alloc_first_fit::h9a72de3af77ef93f,225,7.987220447284344,, -hello,164,5.8217962371317,, +id,name,shallow_size,shallow_size_percent +0,data[3],1034,36.7057152999645 +0,"""function names"" subsection",774,27.47603833865815 +0,wee_alloc::alloc_first_fit::h9a72de3af77ef93f,225,7.987220447284344 +0,hello,164,5.8217962371317 diff --git a/twiggy/tests/tests.rs b/twiggy/tests/tests.rs index c4f43779..b386dc0c 100644 --- a/twiggy/tests/tests.rs +++ b/twiggy/tests/tests.rs @@ -114,6 +114,14 @@ test!( "json" ); +test!( + dominators_wee_alloc_csv, + "dominators", + "./fixtures/wee_alloc.wasm", + "-f", + "csv" +); + test!( dominators_wee_alloc_with_depth_and_row, "dominators", From 28cc3b1e2f14a68a6231014292755a60d2e38205 Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Thu, 26 Apr 2018 18:10:25 +0800 Subject: [PATCH 04/11] csv-format: monos --- analyze/analyze.rs | 46 ++++++++++++++++++++++-- twiggy/tests/expectations/monos_wasm_csv | 1 + 2 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 twiggy/tests/expectations/monos_wasm_csv diff --git a/analyze/analyze.rs b/analyze/analyze.rs index 93ca8cd0..109e3c29 100644 --- a/analyze/analyze.rs +++ b/analyze/analyze.rs @@ -764,8 +764,50 @@ impl traits::Emit for Monos { Ok(()) } - fn emit_csv(&self, _items: &ir::Items, _dest: &mut io::Write) -> Result<(), traits::Error> { - unimplemented!(); + fn emit_csv(&self, items: &ir::Items, dest: &mut io::Write) -> Result<(), traits::Error> { + #[derive(Debug, Default, Serialize)] + struct Record { + generic: Option, + approximate_monomorphization_bloat_bytes: Option, + approximate_monomorphization_bloat_percent: Option, + total_size: Option, + total_size_percent: Option, + monomorphizations: csv::CsvRecord, + } + + let mut wtr = csv_sys::Writer::from_writer(dest); + + for entry in &self.monos { + let approx_potential_savings_percent = + (f64::from(entry.approx_potential_savings)) / (f64::from(items.size())) * 100.0; + + let total_percent = (f64::from(entry.total)) / (f64::from(items.size())) * 100.0; + let mut rc = Record { + generic: Some(entry.generic[..].to_string()), + approximate_monomorphization_bloat_bytes: Some(entry.approx_potential_savings), + approximate_monomorphization_bloat_percent: Some(approx_potential_savings_percent), + total_size: Some(entry.total), + total_size_percent: Some(total_percent), + ..Default::default() + }; + + for &id in &entry.insts { + let item = &items[id]; + let size = item.size(); + let size_percent = (f64::from(size)) / (f64::from(items.size())) * 100.0; + rc.monomorphizations = csv::CsvRecord { + name: item.name().to_string(), + shallow_size: size, + shallow_size_percent: size_percent, + ..Default::default() + } + } + + wtr.serialize(rc)?; + wtr.flush()?; + } + + Ok(()) } } diff --git a/twiggy/tests/expectations/monos_wasm_csv b/twiggy/tests/expectations/monos_wasm_csv new file mode 100644 index 00000000..cd5082bc --- /dev/null +++ b/twiggy/tests/expectations/monos_wasm_csv @@ -0,0 +1 @@ +generic,approximate_monomorphization_bloat_bytes,approximate_monomorphization_bloat_percent,total_size,total_size_percent,monomorphizations \ No newline at end of file From 0159521877c1a0132d2d23308a03403974893463 Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Sat, 28 Apr 2018 19:50:27 +0800 Subject: [PATCH 05/11] csv-format: fix top_2_csv --- twiggy/tests/expectations/top_2_csv | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/twiggy/tests/expectations/top_2_csv b/twiggy/tests/expectations/top_2_csv index 45acd028..e7e3b518 100644 --- a/twiggy/tests/expectations/top_2_csv +++ b/twiggy/tests/expectations/top_2_csv @@ -1,5 +1,5 @@ -id,name,shallow_size,shallow_size_percent -0,data[3],1034,36.7057152999645 -0,"""function names"" subsection",774,27.47603833865815 -0,wee_alloc::alloc_first_fit::h9a72de3af77ef93f,225,7.987220447284344 -0,hello,164,5.8217962371317 +name,shallow_size,shallow_size_percent +data[3],1034,36.7057152999645 +"""function names"" subsection",774,27.47603833865815 +wee_alloc::alloc_first_fit::h9a72de3af77ef93f,225,7.987220447284344 +hello,164,5.8217962371317 From 2420c14d80b875d5ee193e270c4d534f4034bc3d Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Sat, 28 Apr 2018 19:50:47 +0800 Subject: [PATCH 06/11] csv-format: path --- analyze/analyze.rs | 62 ++++++++++++++++++- twiggy/tests/expectations/paths_wee_alloc_csv | 17 +++++ twiggy/tests/tests.rs | 25 +++++++- 3 files changed, 100 insertions(+), 4 deletions(-) create mode 100644 twiggy/tests/expectations/paths_wee_alloc_csv diff --git a/analyze/analyze.rs b/analyze/analyze.rs index 109e3c29..a0c7f3a3 100644 --- a/analyze/analyze.rs +++ b/analyze/analyze.rs @@ -396,7 +396,7 @@ impl traits::Emit for DominatorTree { opts: &opt::Dominators, dominator_tree: &BTreeMap>, id: ir::Id, - wtr: &mut csv_sys::Writer<&mut io::Write> + wtr: &mut csv_sys::Writer<&mut io::Write>, ) -> Result<(), traits::Error> { let item = &items[id]; let (size, size_percent) = ( @@ -610,8 +610,64 @@ impl traits::Emit for Paths { Ok(()) } - fn emit_csv(&self, _items: &ir::Items, _dest: &mut io::Write) -> Result<(), traits::Error> { - unimplemented!(); + fn emit_csv(&self, items: &ir::Items, dest: &mut io::Write) -> Result<(), traits::Error> { + let mut wtr = csv_sys::Writer::from_writer(dest); + fn recursive_callers( + items: &ir::Items, + seen: &mut BTreeSet, + depth: u32, + mut paths: &mut u32, + opts: &opt::Paths, + id: ir::Id, + wtr: &mut csv_sys::Writer<&mut io::Write>, + ) -> io::Result<()> { + let item = &items[id]; + let size = item.size(); + let size_percent = (size as f64) / (items.size() as f64) * 100.0; + let mut path = String::with_capacity(item.name().len()); + path.push_str(item.name()); + + let record = csv::CsvRecord { + name: item.name().to_owned(), + shallow_size: size, + shallow_size_percent: size_percent, + path: Some(path), + ..Default::default() + }; + + wtr.serialize(record)?; + wtr.flush()?; + + let depth = depth + 1; + if depth <= opts.max_depth { + seen.insert(id); + for (i, caller) in items.predecessors(id).enumerate() { + if seen.contains(&caller) || items.meta_root() == caller { + continue; + } + + if i > 0 { + *paths += 1; + } + if opts.max_paths == *paths { + break; + } + + recursive_callers(items, seen, depth, &mut paths, &opts, caller, wtr)?; + } + seen.remove(&id); + } + + Ok(()) + } + + for id in &self.items { + let mut paths = 0 as u32; + let mut seen = BTreeSet::new(); + recursive_callers(items, &mut seen, 0, &mut paths, &self.opts, *id, &mut wtr)?; + } + + Ok(()) } } diff --git a/twiggy/tests/expectations/paths_wee_alloc_csv b/twiggy/tests/expectations/paths_wee_alloc_csv new file mode 100644 index 00000000..d4c17f4d --- /dev/null +++ b/twiggy/tests/expectations/paths_wee_alloc_csv @@ -0,0 +1,17 @@ +name,shallow_size,shallow_size_percent,path +wee_alloc::alloc_first_fit::h9a72de3af77ef93f,225,7.987220447284344,wee_alloc::alloc_first_fit::h9a72de3af77ef93f +func[3],1,0.03549875754348598,func[3] +wee_alloc::alloc_with_refill::hb32c1bbce9ebda8e,152,5.395811146609868,wee_alloc::alloc_with_refill::hb32c1bbce9ebda8e +func[2],1,0.03549875754348598,func[2] + as wee_alloc::AllocPolicy>::new_cell_for_free_list::h3987e3054b8224e6,136,4.827831025914093, as wee_alloc::AllocPolicy>::new_cell_for_free_list::h3987e3054b8224e6 +func[5],1,0.03549875754348598,func[5] +elem[0],12,0.42598509052183176,elem[0] +hello,164,5.8217962371317,hello +func[8],1,0.03549875754348598,func[8] +"export ""hello""",8,0.2839900603478878,"export ""hello""" +hello,164,5.8217962371317,hello +func[8],1,0.03549875754348598,func[8] +"export ""hello""",8,0.2839900603478878,"export ""hello""" +goodbye,44,1.5619453319133831,goodbye +func[9],1,0.03549875754348598,func[9] +"export ""goodbye""",10,0.3549875754348598,"export ""goodbye""" diff --git a/twiggy/tests/tests.rs b/twiggy/tests/tests.rs index b386dc0c..7a1f1792 100644 --- a/twiggy/tests/tests.rs +++ b/twiggy/tests/tests.rs @@ -193,6 +193,17 @@ test!( "goodbye" ); +test!( + paths_wee_alloc_csv, + "paths", + "./fixtures/wee_alloc.wasm", + "wee_alloc::alloc_first_fit::h9a72de3af77ef93f", + "hello", + "goodbye", + "-f", + "csv" +); + test!( paths_wee_alloc_with_depth_and_paths, "paths", @@ -307,7 +318,7 @@ test!( test!(monos_only_generics, "monos", "./fixtures/monos.wasm", "-g"); test!( - monos_json, + monos_csv, "monos", "./fixtures/monos.wasm", "-m", @@ -353,3 +364,15 @@ test!( "-f", "json" ); + +test!( + monos_json, + "monos", + "./fixtures/monos.wasm", + "-m", + "2", + "-n", + "1", + "-f", + "csv" +); From 5f865e129bf842682a071eeb5260cdedd6fa966c Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Wed, 9 May 2018 23:43:34 +0800 Subject: [PATCH 07/11] csv-format: dominator:idom --- analyze/analyze.rs | 9 +++-- analyze/csv.rs | 2 +- .../expectations/dominators_wee_alloc_csv | 34 +++++++++---------- 3 files changed, 25 insertions(+), 20 deletions(-) diff --git a/analyze/analyze.rs b/analyze/analyze.rs index a0c7f3a3..43cc26c3 100644 --- a/analyze/analyze.rs +++ b/analyze/analyze.rs @@ -407,7 +407,11 @@ impl traits::Emit for DominatorTree { items.retained_size(id), (items.retained_size(id) as f64) / (items.size() as f64) * 100.0, ); - + let idom = if let Some(idom) = items.predecessors(id).last() { + idom.0 + } else { + id.0 + }; let rc = csv::CsvRecord { id: Some(item.id().0), name: item.name().to_string(), @@ -416,7 +420,7 @@ impl traits::Emit for DominatorTree { retained_size: Some(retained_size), retained_size_percent: Some(retained_size_percent), // TODO CSMOE: find immediate dominator - immediate_dominator: Some(id.0), + immediate_dominator: Some(idom), ..Default::default() }; @@ -444,6 +448,7 @@ pub fn dominators( ) -> Result, traits::Error> { items.compute_dominator_tree(); items.compute_retained_sizes(); + items.compute_predecessors(); let subtree = opts.subtree(); let root_id = match subtree.is_empty() { diff --git a/analyze/csv.rs b/analyze/csv.rs index 83493410..9601b90d 100644 --- a/analyze/csv.rs +++ b/analyze/csv.rs @@ -13,4 +13,4 @@ pub struct CsvRecord { pub immediate_dominator: Option, #[serde(skip_serializing_if = "Option::is_none")] pub path: Option -} \ No newline at end of file +} diff --git a/twiggy/tests/expectations/dominators_wee_alloc_csv b/twiggy/tests/expectations/dominators_wee_alloc_csv index 4be91093..61a61f85 100644 --- a/twiggy/tests/expectations/dominators_wee_alloc_csv +++ b/twiggy/tests/expectations/dominators_wee_alloc_csv @@ -1,19 +1,19 @@ id,name,shallow_size,shallow_size_percent,retained_size,retained_size_percent,immediate_dominator 4294967295,,0,0,1417,50.30173943911963,4294967295 -8,"""function names"" subsection",774,27.47603833865815,774,27.47603833865815,8 -4,"export ""hello""",8,0.2839900603478878,573,20.340788072417464,4 -1,func[8],1,0.03549875754348598,565,20.056798012069578,1 -6,hello,164,5.8217962371317,560,19.879304224352147,6 -1,func[2],1,0.03549875754348598,387,13.738019169329075,1 -6,wee_alloc::alloc_with_refill::hb32c1bbce9ebda8e,152,5.395811146609868,378,13.418530351437699,6 -1,func[3],1,0.03549875754348598,226,8.022719204827832,1 -6,wee_alloc::alloc_first_fit::h9a72de3af77ef93f,225,7.987220447284344,225,7.987220447284344,6 -0,type[4],8,0.2839900603478878,8,0.2839900603478878,0 -7,data[0],9,0.3194888178913738,9,0.3194888178913738,7 -0,type[5],4,0.1419950301739439,4,0.1419950301739439,0 -4,"export ""goodbye""",10,0.3549875754348598,59,2.0944266950656725,4 -1,func[9],1,0.03549875754348598,49,1.7394391196308128,1 -6,goodbye,44,1.5619453319133831,44,1.5619453319133831,6 -0,type[3],4,0.1419950301739439,4,0.1419950301739439,0 -4,"export ""memory""",9,0.3194888178913738,11,0.3904863329783458,4 -3,memory[0],2,0.07099751508697195,2,0.07099751508697195,3 +8,"""function names"" subsection",774,27.47603833865815,774,27.47603833865815,4294967295 +4,"export ""hello""",8,0.2839900603478878,573,20.340788072417464,4294967295 +1,func[8],1,0.03549875754348598,565,20.056798012069578,4 +6,hello,164,5.8217962371317,560,19.879304224352147,1 +1,func[2],1,0.03549875754348598,387,13.738019169329075,6 +6,wee_alloc::alloc_with_refill::hb32c1bbce9ebda8e,152,5.395811146609868,378,13.418530351437699,1 +1,func[3],1,0.03549875754348598,226,8.022719204827832,6 +6,wee_alloc::alloc_first_fit::h9a72de3af77ef93f,225,7.987220447284344,225,7.987220447284344,1 +0,type[4],8,0.2839900603478878,8,0.2839900603478878,1 +7,data[0],9,0.3194888178913738,9,0.3194888178913738,6 +0,type[5],4,0.1419950301739439,4,0.1419950301739439,1 +4,"export ""goodbye""",10,0.3549875754348598,59,2.0944266950656725,4294967295 +1,func[9],1,0.03549875754348598,49,1.7394391196308128,4 +6,goodbye,44,1.5619453319133831,44,1.5619453319133831,1 +0,type[3],4,0.1419950301739439,4,0.1419950301739439,1 +4,"export ""memory""",9,0.3194888178913738,11,0.3904863329783458,4294967295 +3,memory[0],2,0.07099751508697195,2,0.07099751508697195,4 From 84c4eae35ccdf05b6dc94c5e1aa31bc45da93361 Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Thu, 10 May 2018 12:51:22 +0800 Subject: [PATCH 08/11] csv-format: paths:path --- analyze/analyze.rs | 6 ++-- twiggy/tests/expectations/paths_wee_alloc_csv | 30 +++++++++---------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/analyze/analyze.rs b/analyze/analyze.rs index 43cc26c3..cadf727b 100644 --- a/analyze/analyze.rs +++ b/analyze/analyze.rs @@ -419,7 +419,6 @@ impl traits::Emit for DominatorTree { shallow_size_percent: size_percent, retained_size: Some(retained_size), retained_size_percent: Some(retained_size_percent), - // TODO CSMOE: find immediate dominator immediate_dominator: Some(idom), ..Default::default() }; @@ -629,8 +628,9 @@ impl traits::Emit for Paths { let item = &items[id]; let size = item.size(); let size_percent = (size as f64) / (items.size() as f64) * 100.0; - let mut path = String::with_capacity(item.name().len()); - path.push_str(item.name()); + let mut callers = items.predecessors(id).into_iter().map(|i| items[i].name()).collect::>(); + callers.push(item.name()); + let path = callers.join(" -> "); let record = csv::CsvRecord { name: item.name().to_owned(), diff --git a/twiggy/tests/expectations/paths_wee_alloc_csv b/twiggy/tests/expectations/paths_wee_alloc_csv index d4c17f4d..f0c75857 100644 --- a/twiggy/tests/expectations/paths_wee_alloc_csv +++ b/twiggy/tests/expectations/paths_wee_alloc_csv @@ -1,17 +1,17 @@ name,shallow_size,shallow_size_percent,path -wee_alloc::alloc_first_fit::h9a72de3af77ef93f,225,7.987220447284344,wee_alloc::alloc_first_fit::h9a72de3af77ef93f -func[3],1,0.03549875754348598,func[3] -wee_alloc::alloc_with_refill::hb32c1bbce9ebda8e,152,5.395811146609868,wee_alloc::alloc_with_refill::hb32c1bbce9ebda8e -func[2],1,0.03549875754348598,func[2] - as wee_alloc::AllocPolicy>::new_cell_for_free_list::h3987e3054b8224e6,136,4.827831025914093, as wee_alloc::AllocPolicy>::new_cell_for_free_list::h3987e3054b8224e6 -func[5],1,0.03549875754348598,func[5] +wee_alloc::alloc_first_fit::h9a72de3af77ef93f,225,7.987220447284344,func[3] -> wee_alloc::alloc_first_fit::h9a72de3af77ef93f +func[3],1,0.03549875754348598,wee_alloc::alloc_with_refill::hb32c1bbce9ebda8e -> func[3] +wee_alloc::alloc_with_refill::hb32c1bbce9ebda8e,152,5.395811146609868,func[2] -> wee_alloc::alloc_with_refill::hb32c1bbce9ebda8e +func[2],1,0.03549875754348598, as wee_alloc::AllocPolicy>::new_cell_for_free_list::h3987e3054b8224e6 -> hello -> func[2] + as wee_alloc::AllocPolicy>::new_cell_for_free_list::h3987e3054b8224e6,136,4.827831025914093,func[5] -> as wee_alloc::AllocPolicy>::new_cell_for_free_list::h3987e3054b8224e6 +func[5],1,0.03549875754348598,elem[0] -> func[5] elem[0],12,0.42598509052183176,elem[0] -hello,164,5.8217962371317,hello -func[8],1,0.03549875754348598,func[8] -"export ""hello""",8,0.2839900603478878,"export ""hello""" -hello,164,5.8217962371317,hello -func[8],1,0.03549875754348598,func[8] -"export ""hello""",8,0.2839900603478878,"export ""hello""" -goodbye,44,1.5619453319133831,goodbye -func[9],1,0.03549875754348598,func[9] -"export ""goodbye""",10,0.3549875754348598,"export ""goodbye""" +hello,164,5.8217962371317,func[8] -> hello +func[8],1,0.03549875754348598,"export ""hello"" -> func[8]" +"export ""hello""",8,0.2839900603478878," -> export ""hello""" +hello,164,5.8217962371317,func[8] -> hello +func[8],1,0.03549875754348598,"export ""hello"" -> func[8]" +"export ""hello""",8,0.2839900603478878," -> export ""hello""" +goodbye,44,1.5619453319133831,func[9] -> goodbye +func[9],1,0.03549875754348598,"export ""goodbye"" -> func[9]" +"export ""goodbye""",10,0.3549875754348598," -> export ""goodbye""" From cd718737b527dcf572d4899d9b7e479bf14eec9b Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Thu, 10 May 2018 18:17:22 +0800 Subject: [PATCH 09/11] rebase --- Cargo.lock | 38 +++----------- analyze/Cargo.toml | 1 + analyze/analyze.rs | 49 ++++++++++--------- analyze/csv.rs | 4 +- ir/ir.rs | 7 ++- .../expectations/dominators_wee_alloc_csv | 2 +- twiggy/tests/expectations/monos_wasm_csv | 12 ++++- twiggy/tests/expectations/paths_wee_alloc_csv | 2 +- twiggy/tests/expectations/top_2_csv | 2 +- twiggy/tests/expectations/top_2_csv_retained | 2 +- twiggy/tests/tests.rs | 10 ++-- 11 files changed, 62 insertions(+), 67 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8ddcb16a..4f7da6bb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -93,7 +93,7 @@ version = "1.0.0-beta.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "csv-core 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.52 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -163,22 +163,6 @@ name = "libc" version = "0.2.40" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "log" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "log" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "memchr" version = "2.0.1" @@ -187,11 +171,6 @@ dependencies = [ "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "num-traits" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "ordermap" version = "0.3.5" @@ -302,6 +281,7 @@ dependencies = [ name = "strsim" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "structopt" version = "0.2.8" @@ -404,8 +384,9 @@ name = "twiggy-analyze" version = "0.1.0" dependencies = [ "csv 1.0.0-beta.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "petgraph 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.52 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.52 (registry+https://github.com/rust-lang/crates.io-index)", "twiggy-ir 0.1.0", "twiggy-opt 0.1.0", "twiggy-traits 0.1.0", @@ -418,9 +399,9 @@ dependencies = [ "cpp_demangle 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", "frozen 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "petgraph 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.52 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.52 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -591,10 +572,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c069bbec61e1ca5a596166e55dfe4773ff745c3d16b700013bcaff9a6df2c682" "checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d" "checksum libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)" = "6fd41f331ac7c5b8ac259b8bf82c75c0fb2e469bbf37d2becbba9a6a2221965b" -"checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" -"checksum log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "89f010e843f2b1a31dbd316b3b8d443758bc634bed37aabade59c686d644e0a2" "checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d" -"checksum num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dee092fcdf725aee04dd7da1d21debff559237d49ef1cb3e69bcb8ece44c7364" "checksum ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a86ed3f5f244b372d6b1a00b72ef7f8876d0bc6a78a4c9985c53614041512063" "checksum parity-wasm 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)" = "79df7454d764da3aaf4e8f696e5c4b97eb82b47abfc89850bfdcf7badfad357e" "checksum petgraph 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "8b30dc85588cd02b9b76f5e386535db546d21dc68506cff2abebee0b6445e8e4" diff --git a/analyze/Cargo.toml b/analyze/Cargo.toml index fb560fa0..47cd16e3 100644 --- a/analyze/Cargo.toml +++ b/analyze/Cargo.toml @@ -18,3 +18,4 @@ twiggy-traits = { version = "0.1.0", path = "../traits" } csv = "1.0.0-beta.5" serde = "1.0.40" serde_derive = "1.0.40" +petgraph = "0.4.12" diff --git a/analyze/analyze.rs b/analyze/analyze.rs index cadf727b..ab46bf75 100644 --- a/analyze/analyze.rs +++ b/analyze/analyze.rs @@ -6,6 +6,7 @@ extern crate csv as csv_sys; #[macro_use] extern crate serde_derive; +extern crate petgraph; extern crate twiggy_ir as ir; extern crate twiggy_opt as opt; extern crate twiggy_traits as traits; @@ -193,7 +194,7 @@ impl traits::Emit for Top { let size_percent = (size as f64) / (items.size() as f64) * 100.0; (size, size_percent) }; - let (retained_size, retained_size_percent) = if self.opts.retained { + let (retained_size, retained_size_percent) = if self.opts.retained() { let size = items.retained_size(id); let size_percent = (size as f64) / (items.size() as f64) * 100.0; (Some(size), Some(size_percent)) @@ -408,12 +409,12 @@ impl traits::Emit for DominatorTree { (items.retained_size(id) as f64) / (items.size() as f64) * 100.0, ); let idom = if let Some(idom) = items.predecessors(id).last() { - idom.0 + idom.real_id() } else { - id.0 + id.real_id() }; let rc = csv::CsvRecord { - id: Some(item.id().0), + id: Some(item.id().real_id()), name: item.name().to_string(), shallow_size: size, shallow_size_percent: size_percent, @@ -628,7 +629,11 @@ impl traits::Emit for Paths { let item = &items[id]; let size = item.size(); let size_percent = (size as f64) / (items.size() as f64) * 100.0; - let mut callers = items.predecessors(id).into_iter().map(|i| items[i].name()).collect::>(); + let mut callers = items + .predecessors(id) + .into_iter() + .map(|i| items[i].name()) + .collect::>(); callers.push(item.name()); let path = callers.join(" -> "); @@ -644,7 +649,7 @@ impl traits::Emit for Paths { wtr.flush()?; let depth = depth + 1; - if depth <= opts.max_depth { + if depth <= opts.max_depth() { seen.insert(id); for (i, caller) in items.predecessors(id).enumerate() { if seen.contains(&caller) || items.meta_root() == caller { @@ -654,7 +659,7 @@ impl traits::Emit for Paths { if i > 0 { *paths += 1; } - if opts.max_paths == *paths { + if opts.max_paths() == *paths { break; } @@ -827,23 +832,24 @@ impl traits::Emit for Monos { fn emit_csv(&self, items: &ir::Items, dest: &mut io::Write) -> Result<(), traits::Error> { #[derive(Debug, Default, Serialize)] + #[serde(rename_all = "PascalCase")] struct Record { generic: Option, approximate_monomorphization_bloat_bytes: Option, approximate_monomorphization_bloat_percent: Option, total_size: Option, total_size_percent: Option, - monomorphizations: csv::CsvRecord, + monomorphizations: Option, } let mut wtr = csv_sys::Writer::from_writer(dest); - + let mut rc; for entry in &self.monos { let approx_potential_savings_percent = (f64::from(entry.approx_potential_savings)) / (f64::from(items.size())) * 100.0; let total_percent = (f64::from(entry.total)) / (f64::from(items.size())) * 100.0; - let mut rc = Record { + rc = Record { generic: Some(entry.generic[..].to_string()), approximate_monomorphization_bloat_bytes: Some(entry.approx_potential_savings), approximate_monomorphization_bloat_percent: Some(approx_potential_savings_percent), @@ -852,22 +858,11 @@ impl traits::Emit for Monos { ..Default::default() }; - for &id in &entry.insts { - let item = &items[id]; - let size = item.size(); - let size_percent = (f64::from(size)) / (f64::from(items.size())) * 100.0; - rc.monomorphizations = csv::CsvRecord { - name: item.name().to_string(), - shallow_size: size, - shallow_size_percent: size_percent, - ..Default::default() - } - } - + let monos: Vec<&str> = entry.insts.iter().map(|id| items[*id].name()).collect(); + rc.monomorphizations = Some(monos.join(", ")); wtr.serialize(rc)?; wtr.flush()?; } - Ok(()) } } @@ -986,6 +981,10 @@ impl traits::Emit for Diff { Ok(()) } + + fn emit_csv(&self, _items: &ir::Items, _dest: &mut io::Write) -> Result<(), traits::Error> { + unimplemented!(); + } } /// Compute the diff between two sets of items. @@ -1085,6 +1084,10 @@ impl traits::Emit for Garbage { Ok(()) } + + fn emit_csv(&self, _items: &ir::Items, _dest: &mut io::Write) -> Result<(), traits::Error> { + unimplemented!(); + } } /// Find items that are not transitively referenced by any exports or public functions. diff --git a/analyze/csv.rs b/analyze/csv.rs index 9601b90d..6d6feb01 100644 --- a/analyze/csv.rs +++ b/analyze/csv.rs @@ -1,4 +1,5 @@ #[derive(Debug, Default, Serialize)] +#[serde(rename_all = "PascalCase")] pub struct CsvRecord { #[serde(skip_serializing_if = "Option::is_none")] pub id: Option, @@ -12,5 +13,6 @@ pub struct CsvRecord { #[serde(skip_serializing_if = "Option::is_none")] pub immediate_dominator: Option, #[serde(skip_serializing_if = "Option::is_none")] - pub path: Option + pub path: Option, } + diff --git a/ir/ir.rs b/ir/ir.rs index fabab8d0..8349091c 100644 --- a/ir/ir.rs +++ b/ir/ir.rs @@ -369,7 +369,7 @@ impl<'a> Iterator for Iter<'a> { /// An item's unique identifier. #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct Id(pub u32, u32); +pub struct Id(u32, u32); impl Id { /// Create an `Id` for a the given section. @@ -389,6 +389,11 @@ impl Id { pub fn root() -> Id { Id(u32::MAX, u32::MAX) } + + /// Get the real id of a item. + pub fn real_id(&self) -> u32 { + self.0 + } } /// An item in the binary. diff --git a/twiggy/tests/expectations/dominators_wee_alloc_csv b/twiggy/tests/expectations/dominators_wee_alloc_csv index 61a61f85..e93a9f91 100644 --- a/twiggy/tests/expectations/dominators_wee_alloc_csv +++ b/twiggy/tests/expectations/dominators_wee_alloc_csv @@ -1,4 +1,4 @@ -id,name,shallow_size,shallow_size_percent,retained_size,retained_size_percent,immediate_dominator +Id,Name,ShallowSize,ShallowSizePercent,RetainedSize,RetainedSizePercent,ImmediateDominator 4294967295,,0,0,1417,50.30173943911963,4294967295 8,"""function names"" subsection",774,27.47603833865815,774,27.47603833865815,4294967295 4,"export ""hello""",8,0.2839900603478878,573,20.340788072417464,4294967295 diff --git a/twiggy/tests/expectations/monos_wasm_csv b/twiggy/tests/expectations/monos_wasm_csv index cd5082bc..d3d3b173 100644 --- a/twiggy/tests/expectations/monos_wasm_csv +++ b/twiggy/tests/expectations/monos_wasm_csv @@ -1 +1,11 @@ -generic,approximate_monomorphization_bloat_bytes,approximate_monomorphization_bloat_percent,total_size,total_size_percent,monomorphizations \ No newline at end of file +Generic,ApproximateMonomorphizationBloatBytes,ApproximateMonomorphizationBloatPercent,TotalSize,TotalSizePercent,Monomorphizations +alloc::slice::merge_sort,1977,3.396673768125902,3003,5.159439213799739,"alloc::slice::merge_sort::hb3d195f9800bdad6, alloc::slice::merge_sort::hfcf2318d7dc71d03, alloc::slice::merge_sort::hcfca67f5c75a52ef" +<&'a T as core::fmt::Debug>::fmt,1302,2.2369596591299565,3996,6.865507525255995,"<&'a T as core::fmt::Debug>::fmt::h1c27955d8de3ff17, <&'a T as core::fmt::Debug>::fmt::hea6a77c4dcddb7ac, <&'a T as core::fmt::Debug>::fmt::hfbacf6f5c9f53bb2, <&'a T as core::fmt::Debug>::fmt::h199e8e1c5752e6f1" +core::result::unwrap_failed,973,1.6717064119304514,1118,1.9208301834925434,"core::result::unwrap_failed::h9bd27c3a9ad7c001, core::result::unwrap_failed::h4cc73eb9bf19ce32, core::result::unwrap_failed::h137aa4f433aba1a9, core::result::unwrap_failed::ha3e58cfc7f422ab4, core::result::unwrap_failed::h9a7678774db14d67, core::result::unwrap_failed::hcb258ce32bda3d85, core::result::unwrap_failed::ha7651fcaac40f701, core::result::unwrap_failed::hcfddf900474e698a" +">::double",558,0.9586969967699815,714,1.2267198130712667,">::double::h28f86621ee2a10aa, >::double::h956450b93bdc9e1e, >::double::hcb2fb5861b96a3b0, >::double::ha715b4e5cc3c60ae, >::double::h77ff8547127c5db2" +std::thread::local::os::destroy_value,512,0.8796646278606282,798,1.3710397910796508,"std::thread::local::os::destroy_value::hca8124786bee4a79, std::thread::local::os::destroy_value::h094cf4f2a025ba2b, std::thread::local::os::destroy_value::h453d41f6c315da32" +alloc::slice::insert_head,234,0.4020342244519277,354,0.6082056216067624,"alloc::slice::insert_head::haf6e08236bab8bde, alloc::slice::insert_head::h2cdb84a455761146, alloc::slice::insert_head::hed0e79da03eeec8b" +" as core::fmt::Write>::write_fmt",196,0.33674661535289674,294,0.505119923029345," as core::fmt::Write>::write_fmt::h1b74a5fafe15c8eb, as core::fmt::Write>::write_fmt::h24034d1c07bfae93, as core::fmt::Write>::write_fmt::h5ebed3e159974658" +>::push,195,0.3350285203766064,270,0.46388564359837814,">::push::h98b02eda22d1ca25, >::push::hc927b4bedb35b00d, >::push::h5729b9e7651ef67b, >::push::h9415ef699ccc65d8" + as core::slice::SliceIndex<[T]>>::index_mut,119,0.20445330217854443,180,0.3092570957322521," as core::slice::SliceIndex<[T]>>::index_mut::hba42cce6d0c0099b, as core::slice::SliceIndex<[T]>>::index_mut::hbf8fcfe76c1f6657, as core::slice::SliceIndex<[T]>>::index_mut::h1c053f01b6f95d93" +core::fmt::Write::write_fmt,95,0.1632190227475775,190,0.326438045495155,"core::fmt::Write::write_fmt::ha5ae3249cacba520, core::fmt::Write::write_fmt::hef4632e1398f5ac8" diff --git a/twiggy/tests/expectations/paths_wee_alloc_csv b/twiggy/tests/expectations/paths_wee_alloc_csv index f0c75857..2fdb4798 100644 --- a/twiggy/tests/expectations/paths_wee_alloc_csv +++ b/twiggy/tests/expectations/paths_wee_alloc_csv @@ -1,4 +1,4 @@ -name,shallow_size,shallow_size_percent,path +Name,ShallowSize,ShallowSizePercent,Path wee_alloc::alloc_first_fit::h9a72de3af77ef93f,225,7.987220447284344,func[3] -> wee_alloc::alloc_first_fit::h9a72de3af77ef93f func[3],1,0.03549875754348598,wee_alloc::alloc_with_refill::hb32c1bbce9ebda8e -> func[3] wee_alloc::alloc_with_refill::hb32c1bbce9ebda8e,152,5.395811146609868,func[2] -> wee_alloc::alloc_with_refill::hb32c1bbce9ebda8e diff --git a/twiggy/tests/expectations/top_2_csv b/twiggy/tests/expectations/top_2_csv index e7e3b518..86a51e4a 100644 --- a/twiggy/tests/expectations/top_2_csv +++ b/twiggy/tests/expectations/top_2_csv @@ -1,4 +1,4 @@ -name,shallow_size,shallow_size_percent +Name,ShallowSize,ShallowSizePercent data[3],1034,36.7057152999645 """function names"" subsection",774,27.47603833865815 wee_alloc::alloc_first_fit::h9a72de3af77ef93f,225,7.987220447284344 diff --git a/twiggy/tests/expectations/top_2_csv_retained b/twiggy/tests/expectations/top_2_csv_retained index d5aeb4d7..6ecf40b8 100644 --- a/twiggy/tests/expectations/top_2_csv_retained +++ b/twiggy/tests/expectations/top_2_csv_retained @@ -1,4 +1,4 @@ -name,shallow_size,shallow_size_percent,retained_size,retained_size_percent +Name,ShallowSize,ShallowSizePercent,RetainedSize,RetainedSizePercent data[3],1034,36.7057152999645,1034,36.7057152999645 """function names"" subsection",774,27.47603833865815,774,27.47603833865815 "export ""hello""",8,0.2839900603478878,573,20.340788072417464 diff --git a/twiggy/tests/tests.rs b/twiggy/tests/tests.rs index 7a1f1792..5a7c476a 100644 --- a/twiggy/tests/tests.rs +++ b/twiggy/tests/tests.rs @@ -318,15 +318,11 @@ test!( test!(monos_only_generics, "monos", "./fixtures/monos.wasm", "-g"); test!( - monos_csv, + monos_wasm_csv, "monos", "./fixtures/monos.wasm", - "-m", - "2", - "-n", - "1", "-f", - "json" + "csv" ); test!( @@ -374,5 +370,5 @@ test!( "-n", "1", "-f", - "csv" + "json" ); From ce2a921eaf7a15683e20244f350ad35bff408499 Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Sun, 20 May 2018 18:50:17 +0800 Subject: [PATCH 10/11] address suggestions --- Cargo.lock | 52 +++++++++++++++++----------------- analyze/Cargo.toml | 6 ++-- analyze/analyze.rs | 70 ++++++++++++++++++++++++++++++++-------------- analyze/csv.rs | 18 ------------ ir/ir.rs | 33 ++++++++++++++++++++-- 5 files changed, 110 insertions(+), 69 deletions(-) delete mode 100644 analyze/csv.rs diff --git a/Cargo.lock b/Cargo.lock index 4f7da6bb..8ec3d126 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -75,7 +75,7 @@ dependencies = [ "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -89,11 +89,11 @@ dependencies = [ [[package]] name = "csv" -version = "1.0.0-beta.5" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "csv-core 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.52 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -254,17 +254,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.55" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.55" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.13.10 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -274,7 +274,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.55 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -298,7 +298,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.13.10 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -313,7 +313,7 @@ dependencies = [ [[package]] name = "syn" -version = "0.13.10" +version = "0.13.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -353,7 +353,7 @@ name = "textwrap" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -383,10 +383,10 @@ dependencies = [ name = "twiggy-analyze" version = "0.1.0" dependencies = [ - "csv 1.0.0-beta.5 (registry+https://github.com/rust-lang/crates.io-index)", + "csv 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "petgraph 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.52 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.52 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", "twiggy-ir 0.1.0", "twiggy-opt 0.1.0", "twiggy-traits 0.1.0", @@ -400,8 +400,8 @@ dependencies = [ "frozen 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "petgraph 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.52 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.52 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -428,7 +428,7 @@ dependencies = [ name = "twiggy-traits" version = "0.1.0" dependencies = [ - "csv 1.0.0-beta.5 (registry+https://github.com/rust-lang/crates.io-index)", + "csv 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "parity-wasm 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)", "twiggy-ir 0.1.0", @@ -453,7 +453,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "unicode-width" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -505,7 +505,7 @@ dependencies = [ "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.13.10 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)", "wasm-bindgen-shared 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -517,7 +517,7 @@ dependencies = [ "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.13.10 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)", "wasm-bindgen-backend 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "wasm-bindgen-shared 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -527,8 +527,8 @@ name = "wasm-bindgen-shared" version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.55 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.55 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -562,6 +562,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "405216fd8fe65f718daa7102ea808a946b6ce40c742998fbfd3463645552de18" "checksum clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0f16b89cbb9ee36d87483dc939fe9f1e13c05898d56d7b230a0d4dff033a536" "checksum cpp_demangle 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "59f21019cf64a5de42e82a006df0a925ad5dc49b44e5a33aa5475d16f7ba0224" +"checksum csv 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71903184af9960c555e7f3b32ff17390d20ecaaf17d4f18c4a0993f2df8a49e3" +"checksum csv-core 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4dd8e6d86f7ba48b4276ef1317edc8cc36167546d8972feb4a2b5fec0b374105" "checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a" "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab" "checksum failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "934799b6c1de475a012a02dab0ace1ace43789ee4b99bcfbf1a2e3e8ced5de82" @@ -584,21 +586,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum regex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "75ecf88252dce580404a22444fc7d626c01815debba56a7f4f536772a5ff19d3" "checksum regex-syntax 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8f1ac0f60d675cc6cf13a20ec076568254472551051ad5dd050364d70671bf6b" "checksum rustc-demangle 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "76d7ba1feafada44f2d38eed812bd2489a03c0f5abb975799251518b68848649" -"checksum serde 1.0.55 (registry+https://github.com/rust-lang/crates.io-index)" = "97f6a6c3caba0cf8f883b53331791036404ce3c1bd895961cf8bb2f8cecfd84b" -"checksum serde_derive 1.0.55 (registry+https://github.com/rust-lang/crates.io-index)" = "f51b0ef935cf8a41a77bce553da1f8751a739b7ad82dd73669475a22e6ecedb0" +"checksum serde 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)" = "34e9df8efbe7a2c12ceec1fc8744d56ae3374d8ae325f4a0028949d16433d554" +"checksum serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)" = "ac38f51a52a556cd17545798e29536885fb1a3fa63d6399f5ef650f4a7d35901" "checksum serde_json 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)" = "f3ad6d546e765177cf3dded3c2e424a8040f870083a0e64064746b958ece9cb1" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" "checksum structopt 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b96fc11ba8cf80bfa5cdd6de538c9f7c66f519f83e8caabc554e431bf3e36d" "checksum structopt-derive 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "95063e55a45976cfce9f03fcd26dff356ee622f1a14147bfae068ab8bed153a6" "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" -"checksum syn 0.13.10 (registry+https://github.com/rust-lang/crates.io-index)" = "77961dcdac942fa8bc033c16f3a790b311c8a27d00811b878ebd8cf9b7ba39d5" +"checksum syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)" = "14f9bf6292f3a61d2c716723fdb789a41bbe104168e6f496dc6497e531ea1b9b" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" "checksum synstructure 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a761d12e6d8dcb4dcf952a7a89b475e3a9d69e4a69307e01a470977642914bd" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693" "checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963" "checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d" -"checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f" +"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" diff --git a/analyze/Cargo.toml b/analyze/Cargo.toml index 47cd16e3..126b7c4e 100644 --- a/analyze/Cargo.toml +++ b/analyze/Cargo.toml @@ -15,7 +15,7 @@ path = "./analyze.rs" twiggy-ir = { version = "0.1.0", path = "../ir" } twiggy-opt = { version = "0.1.0", path = "../opt", default-features = false } twiggy-traits = { version = "0.1.0", path = "../traits" } -csv = "1.0.0-beta.5" -serde = "1.0.40" -serde_derive = "1.0.40" +csv = "1.0.0" +serde = "1.0.58" +serde_derive = "1.0.58" petgraph = "0.4.12" diff --git a/analyze/analyze.rs b/analyze/analyze.rs index ab46bf75..7d0eb1e0 100644 --- a/analyze/analyze.rs +++ b/analyze/analyze.rs @@ -3,15 +3,14 @@ #![deny(missing_docs)] #![deny(missing_debug_implementations)] -extern crate csv as csv_sys; #[macro_use] extern crate serde_derive; extern crate petgraph; extern crate twiggy_ir as ir; extern crate twiggy_opt as opt; extern crate twiggy_traits as traits; +extern crate csv; -mod csv; mod json; use std::cmp; @@ -184,7 +183,17 @@ impl traits::Emit for Top { } fn emit_csv(&self, items: &ir::Items, dest: &mut io::Write) -> Result<(), traits::Error> { - let mut wtr = csv_sys::Writer::from_writer(dest); + let mut wtr = csv::Writer::from_writer(dest); + + #[derive(Serialize, Debug)] + #[serde(rename_all = "PascalCase")] + struct CsvRecord { + name: String, + shallow_size: u32, + shallow_size_percent: f64, + retained_size: Option, + retained_size_percent: Option, + } for &id in &self.items { let item = &items[id]; @@ -202,13 +211,12 @@ impl traits::Emit for Top { (None, None) }; - wtr.serialize(csv::CsvRecord { + wtr.serialize(CsvRecord { name: item.name().to_string(), shallow_size: shallow_size, shallow_size_percent: shallow_size_percent, retained_size: retained_size, retained_size_percent: retained_size_percent, - ..Default::default() })?; wtr.flush()?; } @@ -391,14 +399,26 @@ impl traits::Emit for DominatorTree { } fn emit_csv(&self, items: &ir::Items, dest: &mut io::Write) -> Result<(), traits::Error> { - let mut wtr = csv_sys::Writer::from_writer(dest); + let mut wtr = csv::Writer::from_writer(dest); fn recursive_add_children<'a>( items: &ir::Items, opts: &opt::Dominators, dominator_tree: &BTreeMap>, id: ir::Id, - wtr: &mut csv_sys::Writer<&mut io::Write>, + wtr: &mut csv::Writer<&mut io::Write>, ) -> Result<(), traits::Error> { + + #[derive(Serialize, Debug)] + #[serde(rename_all = "PascalCase")] + struct CsvRecord { + name: String, + shallow_size: u32, + shallow_size_percent: f64, + retained_size: u32, + retained_size_percent: f64, + immediate_dominator: u64, + } + let item = &items[id]; let (size, size_percent) = ( item.size(), @@ -408,20 +428,19 @@ impl traits::Emit for DominatorTree { items.retained_size(id), (items.retained_size(id) as f64) / (items.size() as f64) * 100.0, ); - let idom = if let Some(idom) = items.predecessors(id).last() { - idom.real_id() + let idom = if let Some(idom) = items.immediate_dominators().get(&id) { + idom.serializable() } else { - id.real_id() + id.serializable() }; - let rc = csv::CsvRecord { - id: Some(item.id().real_id()), + + let rc = CsvRecord { name: item.name().to_string(), shallow_size: size, shallow_size_percent: size_percent, - retained_size: Some(retained_size), - retained_size_percent: Some(retained_size_percent), - immediate_dominator: Some(idom), - ..Default::default() + retained_size: retained_size, + retained_size_percent: retained_size_percent, + immediate_dominator: idom, }; wtr.serialize(rc)?; @@ -447,6 +466,7 @@ pub fn dominators( opts: &opt::Dominators, ) -> Result, traits::Error> { items.compute_dominator_tree(); + items.compute_dominators(); items.compute_retained_sizes(); items.compute_predecessors(); @@ -616,7 +636,7 @@ impl traits::Emit for Paths { } fn emit_csv(&self, items: &ir::Items, dest: &mut io::Write) -> Result<(), traits::Error> { - let mut wtr = csv_sys::Writer::from_writer(dest); + let mut wtr = csv::Writer::from_writer(dest); fn recursive_callers( items: &ir::Items, seen: &mut BTreeSet, @@ -624,8 +644,17 @@ impl traits::Emit for Paths { mut paths: &mut u32, opts: &opt::Paths, id: ir::Id, - wtr: &mut csv_sys::Writer<&mut io::Write>, + wtr: &mut csv::Writer<&mut io::Write>, ) -> io::Result<()> { + #[derive(Serialize, Debug)] + #[serde(rename_all = "PascalCase")] + struct CsvRecord { + name: String, + shallow_size: u32, + shallow_size_percent: f64, + path: Option, + } + let item = &items[id]; let size = item.size(); let size_percent = (size as f64) / (items.size() as f64) * 100.0; @@ -637,12 +666,11 @@ impl traits::Emit for Paths { callers.push(item.name()); let path = callers.join(" -> "); - let record = csv::CsvRecord { + let record = CsvRecord { name: item.name().to_owned(), shallow_size: size, shallow_size_percent: size_percent, path: Some(path), - ..Default::default() }; wtr.serialize(record)?; @@ -842,7 +870,7 @@ impl traits::Emit for Monos { monomorphizations: Option, } - let mut wtr = csv_sys::Writer::from_writer(dest); + let mut wtr = csv::Writer::from_writer(dest); let mut rc; for entry in &self.monos { let approx_potential_savings_percent = diff --git a/analyze/csv.rs b/analyze/csv.rs deleted file mode 100644 index 6d6feb01..00000000 --- a/analyze/csv.rs +++ /dev/null @@ -1,18 +0,0 @@ -#[derive(Debug, Default, Serialize)] -#[serde(rename_all = "PascalCase")] -pub struct CsvRecord { - #[serde(skip_serializing_if = "Option::is_none")] - pub id: Option, - pub name: String, - pub shallow_size: u32, - pub shallow_size_percent: f64, - #[serde(skip_serializing_if = "Option::is_none")] - pub retained_size: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub retained_size_percent: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub immediate_dominator: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub path: Option, -} - diff --git a/ir/ir.rs b/ir/ir.rs index 8349091c..ca0e0a3c 100644 --- a/ir/ir.rs +++ b/ir/ir.rs @@ -113,6 +113,7 @@ impl ItemsBuilder { dominator_tree: None, retained_sizes: None, predecessors: None, + immediate_dominators: None, items: Frozen::freeze(self.items), edges: Frozen::freeze( self.edges @@ -134,6 +135,7 @@ impl ItemsBuilder { pub struct Items { size: u32, dominator_tree: Option>>, + immediate_dominators: Option>, retained_sizes: Option>, predecessors: Option>>, items: Frozen>, @@ -214,6 +216,31 @@ impl Items { ); } + /// Compute dominators for each item. + pub fn compute_dominators(&mut self) { + if self.immediate_dominators.is_some() { + return; + } + + let mut immediate_dominators = BTreeMap::new(); + let dominators = petgraph::algo::dominators::simple_fast(&*self, self.meta_root); + + for item in self.iter() { + if let Some(idom) = dominators.immediate_dominator(item.id()) { + immediate_dominators.insert(item.id(), idom); + } + } + + self.immediate_dominators = Some(immediate_dominators); + } + + /// Get a refercence to immediate dominators + pub fn immediate_dominators(&self) -> &BTreeMap { + self.immediate_dominators + .as_ref() + .expect("must call compute_immediate_dominators before calling immediate_dominators") + } + /// Force computation of the dominator tree. pub fn compute_dominator_tree(&mut self) { if self.dominator_tree.is_some() { @@ -368,6 +395,7 @@ impl<'a> Iterator for Iter<'a> { } /// An item's unique identifier. +/// (section index, item within that section index) #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Id(u32, u32); @@ -391,8 +419,9 @@ impl Id { } /// Get the real id of a item. - pub fn real_id(&self) -> u32 { - self.0 + pub fn serializable(&self) -> u64 { + let top = (self.0 as u64) << 32; + top | (self.1 as u64) } } From 3ca7ff4f0c90180d68b4eac614df6f6d9f6a0746 Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Sun, 20 May 2018 20:19:31 +0800 Subject: [PATCH 11/11] fix test --- analyze/analyze.rs | 2 ++ .../expectations/dominators_wee_alloc_csv | 36 +++++++++---------- twiggy/tests/expectations/top_2_csv | 10 +++--- twiggy/tests/tests.rs | 13 ------- 4 files changed, 25 insertions(+), 36 deletions(-) diff --git a/analyze/analyze.rs b/analyze/analyze.rs index 7d0eb1e0..f25eacd5 100644 --- a/analyze/analyze.rs +++ b/analyze/analyze.rs @@ -411,6 +411,7 @@ impl traits::Emit for DominatorTree { #[derive(Serialize, Debug)] #[serde(rename_all = "PascalCase")] struct CsvRecord { + id: u64, name: String, shallow_size: u32, shallow_size_percent: f64, @@ -435,6 +436,7 @@ impl traits::Emit for DominatorTree { }; let rc = CsvRecord { + id: item.id().serializable(), name: item.name().to_string(), shallow_size: size, shallow_size_percent: size_percent, diff --git a/twiggy/tests/expectations/dominators_wee_alloc_csv b/twiggy/tests/expectations/dominators_wee_alloc_csv index e93a9f91..6caff421 100644 --- a/twiggy/tests/expectations/dominators_wee_alloc_csv +++ b/twiggy/tests/expectations/dominators_wee_alloc_csv @@ -1,19 +1,19 @@ Id,Name,ShallowSize,ShallowSizePercent,RetainedSize,RetainedSizePercent,ImmediateDominator -4294967295,,0,0,1417,50.30173943911963,4294967295 -8,"""function names"" subsection",774,27.47603833865815,774,27.47603833865815,4294967295 -4,"export ""hello""",8,0.2839900603478878,573,20.340788072417464,4294967295 -1,func[8],1,0.03549875754348598,565,20.056798012069578,4 -6,hello,164,5.8217962371317,560,19.879304224352147,1 -1,func[2],1,0.03549875754348598,387,13.738019169329075,6 -6,wee_alloc::alloc_with_refill::hb32c1bbce9ebda8e,152,5.395811146609868,378,13.418530351437699,1 -1,func[3],1,0.03549875754348598,226,8.022719204827832,6 -6,wee_alloc::alloc_first_fit::h9a72de3af77ef93f,225,7.987220447284344,225,7.987220447284344,1 -0,type[4],8,0.2839900603478878,8,0.2839900603478878,1 -7,data[0],9,0.3194888178913738,9,0.3194888178913738,6 -0,type[5],4,0.1419950301739439,4,0.1419950301739439,1 -4,"export ""goodbye""",10,0.3549875754348598,59,2.0944266950656725,4294967295 -1,func[9],1,0.03549875754348598,49,1.7394391196308128,4 -6,goodbye,44,1.5619453319133831,44,1.5619453319133831,1 -0,type[3],4,0.1419950301739439,4,0.1419950301739439,1 -4,"export ""memory""",9,0.3194888178913738,11,0.3904863329783458,4294967295 -3,memory[0],2,0.07099751508697195,2,0.07099751508697195,4 +18446744073709551615,,0,0,1417,50.30173943911963,18446744073709551615 +38654705663,"""function names"" subsection",774,27.47603833865815,774,27.47603833865815,18446744073709551615 +17179869185,"export ""hello""",8,0.2839900603478878,573,20.340788072417464,18446744073709551615 +4294967304,func[8],1,0.03549875754348598,565,20.056798012069578,17179869185 +25769803784,hello,164,5.8217962371317,560,19.879304224352147,4294967304 +4294967298,func[2],1,0.03549875754348598,387,13.738019169329075,25769803784 +25769803778,wee_alloc::alloc_with_refill::hb32c1bbce9ebda8e,152,5.395811146609868,378,13.418530351437699,4294967298 +4294967299,func[3],1,0.03549875754348598,226,8.022719204827832,25769803778 +25769803779,wee_alloc::alloc_first_fit::h9a72de3af77ef93f,225,7.987220447284344,225,7.987220447284344,4294967299 +4,type[4],8,0.2839900603478878,8,0.2839900603478878,4294967298 +30064771072,data[0],9,0.3194888178913738,9,0.3194888178913738,25769803784 +5,type[5],4,0.1419950301739439,4,0.1419950301739439,4294967304 +17179869186,"export ""goodbye""",10,0.3549875754348598,59,2.0944266950656725,18446744073709551615 +4294967305,func[9],1,0.03549875754348598,49,1.7394391196308128,17179869186 +25769803785,goodbye,44,1.5619453319133831,44,1.5619453319133831,4294967305 +3,type[3],4,0.1419950301739439,4,0.1419950301739439,4294967305 +17179869184,"export ""memory""",9,0.3194888178913738,11,0.3904863329783458,18446744073709551615 +12884901888,memory[0],2,0.07099751508697195,2,0.07099751508697195,17179869184 diff --git a/twiggy/tests/expectations/top_2_csv b/twiggy/tests/expectations/top_2_csv index 86a51e4a..0a33cfab 100644 --- a/twiggy/tests/expectations/top_2_csv +++ b/twiggy/tests/expectations/top_2_csv @@ -1,5 +1,5 @@ -Name,ShallowSize,ShallowSizePercent -data[3],1034,36.7057152999645 -"""function names"" subsection",774,27.47603833865815 -wee_alloc::alloc_first_fit::h9a72de3af77ef93f,225,7.987220447284344 -hello,164,5.8217962371317 +Name,ShallowSize,ShallowSizePercent,RetainedSize,RetainedSizePercent +data[3],1034,36.7057152999645,, +"""function names"" subsection",774,27.47603833865815,, +wee_alloc::alloc_first_fit::h9a72de3af77ef93f,225,7.987220447284344,, +hello,164,5.8217962371317,, diff --git a/twiggy/tests/tests.rs b/twiggy/tests/tests.rs index 5a7c476a..0d913c80 100644 --- a/twiggy/tests/tests.rs +++ b/twiggy/tests/tests.rs @@ -281,19 +281,6 @@ test!( "csv" ); -test!( - paths_json, - "paths", - "./fixtures/wee_alloc.wasm", - "wee_alloc::alloc_first_fit::h9a72de3af77ef93f", - "hello", - "goodbye", - "-d", - "3", - "-f", - "json" -); - test!( issue_16, "paths",