From 4fd17202fa03783386cbc2c4d29fa9782ffc31bb Mon Sep 17 00:00:00 2001 From: Jean Privat Date: Fri, 24 Jun 2016 08:59:07 -0400 Subject: [PATCH] contrib/memplot: to visualize output of --trace-memory Signed-off-by: Jean Privat --- contrib/memplot/memplot.nit | 198 +++++++++++++++++++++++++++++++++++++++++++ contrib/memplot/memplot.r | 29 +++++++ contrib/memplot/package.ini | 11 +++ 3 files changed, 238 insertions(+) create mode 100644 contrib/memplot/memplot.nit create mode 100644 contrib/memplot/memplot.r create mode 100644 contrib/memplot/package.ini diff --git a/contrib/memplot/memplot.nit b/contrib/memplot/memplot.nit new file mode 100644 index 0000000..2bd1727 --- /dev/null +++ b/contrib/memplot/memplot.nit @@ -0,0 +1,198 @@ +# This file is part of NIT ( http://www.nitlanguage.org ). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Program to transform `memory.log` files produced by `nitc --trace-memory` into a csv file +module memplot + +import counter +import template + +# An aggregated time-slice +class Aggreg + # The start time of the slice + var time: Float + + # Number of allocations + var acpt = new Counter[String] + + # Number of allocated bytes + var asiz = new Counter[String] + + # Number of deallocations + var dcpt = new Counter[String] + + # Number of deallocated bytes + var dsiz = new Counter[String] + + # Total number of allocations since the beginning + var cpttot = new Counter[String] + + # Total number of allocated bytes since the beginning + var siztot = new Counter[String] + + # Map of all the various counters. + var fields = new Map[String, Counter[String]] + + init do + fields["acpt"] = acpt + fields["asiz"] = asiz + fields["dcpt"] = dcpt + fields["dsiz"] = dsiz + fields["cpttot"] = cpttot + fields["siztot"] = siztot + end +end + +# Main class that does the job +class MemProg + # The `memory.log` file. + var filepath: String + + # The delay of an aggregation + var time_slice: Float + + # Total number of events + var events = 0 + + # List a all time aggregations + var aggregs = new Array[Aggreg] + + # Total number of allocations + var cpttot = new Counter[String] + + # Total number of allocated bytes + var siztot = new Counter[String] + + # Parse the log file `filepath` and fill `aggregs`. + fun parse do + # Current lines (not yet put in an aggreg) + var lines = new Counter[String] + + var time = 0.0 + var dt = 100.0 + dt = 100.0 + for l in "memory.log".to_path.each_line do + if l[0] == '#' then + var t = l.substring_from(2).to_f + + while t > time + dt do + aggreg(lines, time) + time += dt + end + #if time > 1000.0 then break + continue + end + events += 1 + lines.inc(l) + end + aggreg(lines, time) + end + + # Create and register a new aggregation + fun aggreg(lines: Counter[String], t1: Float) do + var aggreg = new Aggreg(t1) + aggregs.add aggreg + print "events:{events} aggregs:{aggregs.length} {t1}ms" + + # Process each distinct line + for l, v in lines do + var a = l.split('\t') + if a.length != 3 then + print "Error {a.length}. {l}" + continue + end + var c = a[0] + var s = a[1].to_i + var e = a[2] + if c == "+" then + aggreg.acpt[e] += v + aggreg.asiz[e] += v * s + else if c == "-" then + aggreg.dcpt[e] += v + aggreg.dsiz[e] += v * s + else abort + end + lines.clear + + # Sum all information + for e, v in aggreg.acpt do cpttot[e] += v + for e, v in aggreg.asiz do siztot[e] += v + for e, v in aggreg.dcpt do cpttot[e] -= v + for e, v in aggreg.dsiz do siztot[e] -= v + + # Copy current total + aggreg.cpttot.add_all cpttot + aggreg.siztot.add_all siztot + + cpttot.print_elements(2) + end + + # Generate a *long* CVS file, to use with statistical tools + fun tolong: Writable + do + var res = new Template + + # Write the header + res.add "time, class" + for f, c in aggregs.first.fields do + res.add ", " + res.add f + end + res.add "\n" + + # Collect the largest tags, add add an `other` tag. + var elts = siztot.sort.reversed.sub(0,10).reversed + elts.add "other" + + for a in aggregs do + var t = a.time.to_s + + # For each field compute the value of `other` + for f, c in a.fields do + var o = c.sum + for e in elts do + if e == "other" then continue + o -= c[e] + end + c["other"] = o + end + + # For each tag (incl. other) produce a line + for e in elts do + res.add t + res.add ", " + res.add e + + for f, v in a.fields do + res.add ", " + res.add v[e].to_s + end + res.add "\n" + end + end + return res + end +end + +var m = new MemProg("memory.log", 100.0) +m.parse + +m.cpttot.print_summary +m.siztot.print_summary + +m.tolong.write_to_file "memory.csv" + +if "memplot.r".file_exists then + system("r memplot.r") +end diff --git a/contrib/memplot/memplot.r b/contrib/memplot/memplot.r new file mode 100644 index 0000000..adda5b8 --- /dev/null +++ b/contrib/memplot/memplot.r @@ -0,0 +1,29 @@ +# This file is part of NIT ( http://www.nitlanguage.org ). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# R program to draw a nice plot diagram + +mem <- read.csv("memory.csv") + +library(ggplot2) + +order <- rev(unique(mem$class)) + +ggplot(mem, aes(x=time, y=siztot, fill=class)) + + geom_area(color='black', size=0.02) + + scale_fill_brewer(palette="Spectral", breaks=order) + + theme(legend.text=element_text(size=7)) + +ggsave("memory.pdf") +ggsave("memory.png") diff --git a/contrib/memplot/package.ini b/contrib/memplot/package.ini new file mode 100644 index 0000000..fa7a860 --- /dev/null +++ b/contrib/memplot/package.ini @@ -0,0 +1,11 @@ +[package] +name=memplot +tags=devel +maintainer=Jean Privat +license=Apache-2.0 +[upstream] +browse=https://github.com/nitlang/nit/tree/master/contrib/memplot/ +git=https://github.com/nitlang/nit.git +git.directory=contrib/memplot/ +homepage=http://nitlanguage.org +issues=https://github.com/nitlang/nit/issues -- 1.7.9.5