Last active
November 4, 2018 12:16
-
-
Save holyjak/4b22d6810ea16df940224a77f0db9dcc to your computer and use it in GitHub Desktop.
Comparison of gnuplot, Incanter, oz/vega-lite for plotting usage data - Incanter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns clj-charting.incanter | |
(:require | |
[incanter.core :refer :all] | |
[incanter.charts :refer :all] | |
[clj-charting.usage-chart-preparation :refer [read-usage-data moving-window-means]]) | |
(:import | |
[org.jfree.chart JFreeChart] | |
[org.jfree.chart.plot XYPlot] | |
(org.jfree.chart.axis ValueAxis NumberAxis NumberTickUnit TickUnitSource TickUnit) | |
(java.text NumberFormat DecimalFormat FieldPosition))) | |
(defn merge-y-axis | |
"Merge the Y axis of two line / time series charts. The former chart will have | |
the left Y axis, and the latter will have the right. Incanter does not support 2 Y | |
axes out of the box. | |
Source: https://matthewdowney.github.io/clojure-incanter-plot-multiple-y-axis.html" | |
[^JFreeChart chart ^JFreeChart chart-to-merge] | |
(let [^XYPlot plot (.getPlot chart-to-merge)] | |
(doto ^XYPlot (.getPlot chart) | |
(.setRangeAxis 1 (.getRangeAxis plot)) | |
(.setDataset 1 (.getDataset plot)) | |
(.mapDatasetToRangeAxis 1 1) | |
(.setRenderer 1 (.getRenderer plot))) | |
(-> (.getPlot chart) | |
(.getLegendItems) | |
(.addAll (.getLegendItems plot))) | |
chart)) | |
(defn byte-scale | |
"For the given number [in bytes] return [scale, scale suffix] so that we can divide it | |
by the scale and display with the corresponding suffix. | |
Example: 2333 -> [1024 \"kB\"]" | |
[num] | |
(let [k 1024 | |
m (int (Math/pow 1024 2)) | |
g (int (Math/pow 1024 3))] | |
(condp <= num | |
g [g "GB"] | |
m [m "MB"] | |
k [k "kB"] | |
[1 ""]))) | |
(defn format-bytes | |
"For the given number [in bytes] return [the number scaled down, the scale suffix such as \"kB\"]. | |
Example: 2333 -> [2.278 \"kB\"]" | |
[num] | |
(let [[scale unit] (byte-scale num)] | |
[(/ num scale) unit])) | |
;; Instance of NumberFormat that displays a byte number scaled down and with the scale suffix | |
;; Example: 2333 -> \"2.3kB\"]" | |
(def byteFmt (let [dec-fmt (java.text.DecimalFormat. "#.#")] | |
(proxy [java.text.NumberFormat] [] | |
(format [^double number, ^StringBuffer toAppendTo, ^FieldPosition pos] | |
(let [[n u] (format-bytes number)] | |
(.append | |
(.format dec-fmt n toAppendTo pos) | |
u)))))) | |
(defn nearest-byte-tick | |
"For the given byte number, find out what tick to show on the axis; | |
e.g. we would rather see a tick such as '800MB' than '783.5MB' on it." | |
([^double size tick-fn] | |
(let [[scale] (byte-scale size)] | |
(NumberTickUnit. | |
(* scale | |
;; FIXME if size = 1000 upgrade to 1024 | |
(.getSize | |
(tick-fn | |
(NumberTickUnit. (/ size scale))))) | |
byteFmt)))) | |
(def byte-tick-source | |
"TickUnitSource suitable for byte values spanning multiple of kB - MB - GB" | |
;; TODO Instead of reusing IntegerTickUnits, reimplement it to support powers of 2 | |
(let [int-tick-units (NumberAxis/createIntegerTickUnits)] | |
(reify | |
TickUnitSource | |
(^TickUnit getLargerTickUnit [_ ^TickUnit unit] | |
(nearest-byte-tick | |
(.getSize unit) | |
#(.getLargerTickUnit int-tick-units %))) | |
(^TickUnit getCeilingTickUnit [me ^TickUnit unit] | |
(.getCeilingTickUnit me (.getSize unit))) | |
(^TickUnit getCeilingTickUnit [_ ^double size] | |
(nearest-byte-tick | |
size | |
#(.getCeilingTickUnit int-tick-units %)))))) | |
(defn set-bytes-tick-unit [^JFreeChart chart] | |
(let [^XYPlot plot (.getPlot chart) | |
^NumberAxis axis (.getRangeAxis plot)] | |
(.setStandardTickUnits axis byte-tick-source) | |
chart)) | |
(defn plot-usage [file] | |
(let [data (read-usage-data file) | |
time (sel data :cols 0) | |
mem (sel data :cols 1) | |
cpu (sel data :cols 2)] | |
(-> | |
(time-series-plot time cpu :title file :y-label "cpu [%]" :legend true) | |
(add-lines time (moving-window-means 60 cpu) :series-label "cpu (mean)") | |
(merge-y-axis | |
(set-bytes-tick-unit | |
(time-series-plot time mem :series-label "Memory"))) | |
(view)))) | |
(plot-usage "siege-c10-all-urls-async-node11.dat") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment