Skip to content

Commit 4a6ba2e

Browse files
author
Shubham Gupta
committed
Add benchmark image
1 parent 49340d1 commit 4a6ba2e

File tree

4 files changed

+337
-2
lines changed

4 files changed

+337
-2
lines changed

.gitignore

-1
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,4 @@
66
erl_crash.dump
77
*.ez
88
*.swp
9-
graphs/*
109
snapshots/*

README.md

+4
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,17 @@ The package can be installed as:
3737
MIX_ENV=test mix test
3838
```
3939

40+
## Benchmarks
41+
4042
- We use benchfella for the benchmark tests. Run it using the following
4143
```
4244
MIX_ENV=test mix bench
4345
MIX_ENV=test mix bench
4446
# Generate graphs of the above runs
4547
MIX_ENV=test mix bench.graph
4648
```
49+
- The report is available [here](http://htmlpreview.github.io/?https://github.com/scripbox/ex-xirr/blob/master/bench/graphs/index.html)
50+
4751
## Credits
4852

4953
This application is built on the fantastic [finance-elixir](https://github.com/tubedude/finance-elixir) package. Many thanks to [tubedude](https://github.com/tubedude) for his work.

bench/.gitignore

-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
1-
graphs/*
21
snapshots/*

bench/graphs/index.html

+333
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,333 @@
1+
<html>
2+
<head>
3+
<meta http-equiv="content-type" content="text/html; charset=utf-8">
4+
5+
<title>Index</title>
6+
7+
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
8+
9+
<script src="http://code.jquery.com/jquery-2.1.1.min.js" charset="utf-8"></script>
10+
<script src="http://underscorejs.org/underscore-min.js" charset="utf-8"></script>
11+
12+
<style>.data-axis path,
13+
.data-axis line {
14+
fill: none;
15+
stroke: black;
16+
shape-rendering: crispEdges;
17+
}
18+
19+
.data-axis text {
20+
font-family: sans-serif;
21+
font-size: 11px;
22+
}
23+
24+
.axis path,
25+
.axis line {
26+
fill: none;
27+
stroke: #000;
28+
shape-rendering: crispEdges;
29+
}
30+
31+
rect {
32+
stroke: black;
33+
shape-rendering: crispEdges;
34+
}
35+
</style>
36+
</head>
37+
<body>
38+
39+
<p>Scale:
40+
<select id="scale-selector">
41+
<option>linear</option>
42+
<option>log10</option>
43+
</select>
44+
</p>
45+
46+
<script id="json-data" type="application/json" charset="utf-8">{"bench/snapshots/2018-06-08_12-22-07.snapshot": {
47+
"options": {"duration":1.0,"mem stats":false,"sys mem stats":false},
48+
"tests": [{"elapsed":2878368,"iter":1000,"module":"XirrComparisonBench","tags":[],"test":"long investment bisection method"},{"elapsed":2126197,"iter":10000,"module":"XirrComparisonBench","tags":[],"test":"long investment newton method"}]
49+
},"bench/snapshots/2018-06-08_12-22-13.snapshot": {
50+
"options": {"duration":1.0,"mem stats":false,"sys mem stats":false},
51+
"tests": [{"elapsed":1430888,"iter":500,"module":"XirrComparisonBench","tags":[],"test":"long investment bisection method"},{"elapsed":2122958,"iter":10000,"module":"XirrComparisonBench","tags":[],"test":"long investment newton method"}]
52+
}}</script>
53+
54+
<script type="text/javascript">var CHART_OFFSET_X = 150;
55+
var CHART_WIDTH = 600;
56+
var DATA_LABEL_OFFSET_X = 10;
57+
var BAR_HEIGHT = 20;
58+
var BAR_SPACING = 10;
59+
var BAR_HEIGHT_TOTAL = BAR_HEIGHT + BAR_SPACING;
60+
61+
var BLUES = ["#deebf7", "#c6dbef", "#9ecae1", "#6baed6", "#4292c6", "#2171b5", "#08519c"];
62+
var GREENS = ["#e5f5e0", "#c7e9c0", "#a1d99b", "#74c476", "#41ab5d", "#238b45", "#006d2c"];
63+
var BLACKS = ["#f0f0f0", "#d9d9d9", "#bdbdbd", "#969696", "#737373", "#525252", "#252525"];
64+
var ORANGES = ["#fee6ce", "#fdd0a2", "#fdae6b", "#fd8d3c", "#f16913", "#d94801", "#a63603"];
65+
var VIOLETS = ["#efedf5", "#dadaeb", "#bcbddc", "#9e9ac8", "#807dba", "#6a51a3", "#54278f"];
66+
var REDS = ["#fee0d2", "#fcbba1", "#fc9272", "#fb6a4a", "#ef3b2c", "#cb181d", "#a50f15"];
67+
var NCOLORS = 7;
68+
var COLORS = [BLUES, GREENS, ORANGES, VIOLETS, REDS, BLACKS];
69+
70+
var PALETTE = ["#edf8fb", "#ccece6", "#99d8c9", "#66c2a4", "#2ca25f", "#006d2c"].reverse();
71+
//var PALETTE = ["#f1eef6", "#d4b9da", "#c994c7", "#df65b0", "#dd1c77", "#980043"].reverse();
72+
//var PALETTE = ["#fee5d9", "#fcbba1", "#fc9272", "#fb6a4a", "#de2d26", "#a50f15"].reverse();
73+
//var PALETTE = ["#f2f0f7", "#dadaeb", "#bcbddc", "#9e9ac8", "#756bb1", "#54278f"].reverse();
74+
//var PALETTE = ["#ffffcc", "#c7e9b4", "#7fcdbb", "#41b6c4", "#2c7fb8", "#253494"].reverse();
75+
76+
function color_at(i, j) {
77+
if (!j) j = 0;
78+
return PALETTE[(i+j)%PALETTE.length];
79+
//return COLORS[i % COLORS.length][NCOLORS - 1 - j % NCOLORS];
80+
}
81+
82+
function format_time(time) {
83+
return parseFloat(Math.round(time * 100) / 100).toFixed(2) + " µs/op";
84+
}
85+
86+
function add_chart(name, tests, scale) {
87+
d3.select("body").append("h2").text(name);
88+
var svg = d3.select("body").append("svg");
89+
make_chart(svg, name, tests, scale);
90+
}
91+
92+
function make_chart(svg, name, tests, scale) {
93+
var svgWidth = 1000;
94+
var svgHeight = _.keys(tests).length * BAR_HEIGHT_TOTAL + 50;
95+
svg.attr({
96+
width: svgWidth,
97+
height: svgHeight,
98+
});
99+
100+
var nums = _.map(tests, function(val) { return val.elapsed / val.n; });
101+
var names = _.map(tests, function(val, name) { return name; });
102+
103+
var dataScale;
104+
if (scale == "linear") {
105+
dataScale = d3.scale.linear().domain([0, d3.max(nums)]).range([0, CHART_WIDTH]);
106+
} else if (scale == "log10") {
107+
dataScale = d3.scale.log().domain([1, d3.max(nums)]).range([0, CHART_WIDTH]);
108+
}
109+
110+
svg.selectAll("rect")
111+
.data(nums)
112+
.enter()
113+
.append("rect")
114+
.attr({
115+
x: CHART_OFFSET_X,
116+
y: function(d, i) { return i * (BAR_HEIGHT + BAR_SPACING); },
117+
width: function(d) { return dataScale(d); },
118+
height: BAR_HEIGHT,
119+
fill: function(d, i) { return color_at(i, 0); },
120+
});
121+
122+
svg.selectAll("text.label")
123+
.data(names)
124+
.enter()
125+
.append("text")
126+
.attr({
127+
class: "label",
128+
y: function(d, i) { return i * BAR_HEIGHT_TOTAL + BAR_HEIGHT_TOTAL/2; },
129+
})
130+
.text(function(d) { return d; });
131+
132+
svg.selectAll("text.timing")
133+
.data(nums)
134+
.enter()
135+
.append("text")
136+
.attr({
137+
class: "timing",
138+
x: CHART_OFFSET_X + CHART_WIDTH + DATA_LABEL_OFFSET_X,
139+
y: function(d, i) { return i * 30 + 15; },
140+
})
141+
.text(function(d) { return format_time(d); });
142+
143+
var xAxis = d3.svg.axis()
144+
.scale(dataScale)
145+
.ticks(5);
146+
147+
var axisY = nums.length * 30;
148+
svg.append("g")
149+
.attr({transform: "translate("+CHART_OFFSET_X+", "+axisY+")"})
150+
.attr("class", "data-axis")
151+
.call(xAxis);
152+
}
153+
154+
function add_comparison_chart(name, categories, scale) {
155+
//d3.select("body").append("h2").text(name);
156+
var svg = d3.select("body").append("svg");
157+
make_comparison_chart(svg, categories, scale);
158+
}
159+
160+
function make_comparison_chart(svg, categories, scale) {
161+
var svgWidth = 1200;
162+
var svgHeight = 500;
163+
svg.attr({width: svgWidth, height: svgHeight});
164+
165+
var values = _.chain(categories)
166+
.map(function(snapshots) { return snapshots; })
167+
.flatten()
168+
.map(function(dict) { return dict.elapsed / dict.n; })
169+
.value();
170+
171+
var snapshotCount;
172+
for (var key in categories) {
173+
snapshotCount = categories[key].length;
174+
break;
175+
}
176+
177+
var catCount = _.size(categories);
178+
var xPadding = 0;
179+
var left = xPadding;
180+
var right = svgWidth-2*xPadding;
181+
var w0 = (right - left) / catCount;
182+
var pad = 0.3;
183+
var truePad = 1 - (1 - pad) / snapshotCount;
184+
185+
var xScale = d3.scale.ordinal()
186+
.domain(_.map(categories, function(x, key) { return key; }))
187+
.rangeBands([left, right-w0], truePad, 0);
188+
189+
//var nums = _.map(tests, function(val) { return val.elapsed / val.n; });
190+
//var names = _.map(tests, function(val, name) { return name; });
191+
192+
var dataScale;
193+
var yExtent = [0, svgHeight-50];
194+
if (scale == "linear") {
195+
dataScale = d3.scale.linear()
196+
.domain([d3.max(values), 0])
197+
.range(yExtent);
198+
} else if (scale == "log10") {
199+
dataScale = d3.scale.log()
200+
.domain([d3.max(values), 0.01])
201+
.range(yExtent);
202+
}
203+
204+
var xOffset = 60;
205+
var rectOffset = xOffset + 5;
206+
for (var i = 0; i < snapshotCount; i++) {
207+
// Go through the ith snapshot of each category
208+
var sample = _.map(categories, function(snapshots, key) {
209+
var val = snapshots[i];
210+
return {cat: key, val: val.elapsed / val.n};
211+
});
212+
213+
console.log(sample);
214+
215+
svg.append("g").selectAll("rect")
216+
.data(sample)
217+
.enter()
218+
.append("rect")
219+
.attr({
220+
x: function(d) { return rectOffset+xScale(d.cat); },
221+
y: function(d) { return dataScale(d.val); },
222+
width: xScale.rangeBand(),
223+
height: function(d) { return yExtent[1] - dataScale(d.val); },
224+
fill: color_at(i),
225+
});
226+
227+
rectOffset += xScale.rangeBand();
228+
}
229+
230+
var xAxis = d3.svg.axis()
231+
.scale(xScale)
232+
.orient("bottom");
233+
234+
svg.append("g")
235+
.attr("class", "x axis")
236+
.attr("transform", "translate("+xOffset+"," + (svgHeight-45) + ")")
237+
.call(xAxis)
238+
.selectAll(".tick text")
239+
.call(wordWrap, xScale.rangeBand());
240+
241+
var yAxis = d3.svg.axis()
242+
.scale(dataScale)
243+
.orient("left");
244+
245+
svg.append("g")
246+
.attr("class", "y axis")
247+
.attr("transform", "translate("+xOffset+",0)")
248+
.call(yAxis);
249+
}
250+
251+
function wordWrap(text, width) {
252+
text.each(function() {
253+
var text = d3.select(this),
254+
words = text.text().split(/\s+/).reverse(),
255+
word,
256+
line = [],
257+
lineNumber = 0,
258+
lineHeight = 1.1, // ems
259+
y = text.attr("y"),
260+
dy = parseFloat(text.attr("dy")),
261+
tspan = text.text(null).append("tspan").attr("x", 0).attr("y", y).attr("dy", dy + "em");
262+
while (word = words.pop()) {
263+
line.push(word);
264+
tspan.text(line.join(" "));
265+
if (tspan.node().getComputedTextLength() > width) {
266+
line.pop();
267+
tspan.text(line.join(" "));
268+
line = [word];
269+
tspan = text.append("tspan").attr("x", 0).attr("y", y).attr("dy", ++lineNumber * lineHeight + dy + "em").text(word);
270+
}
271+
}
272+
});
273+
}
274+
275+
var data = JSON.parse($("#json-data").html());
276+
277+
function make_tuple(size) {
278+
var tuple = [];
279+
for (var i = 0; i < size; i++) {
280+
tuple.push(null);
281+
}
282+
return tuple;
283+
}
284+
285+
286+
var allTests = {};
287+
var count = 0;
288+
// loop over snapshots
289+
_.each(data, function(dict, name) {
290+
// loop tests
291+
_.each(dict.tests, function(test) {
292+
var modName = test["module"];
293+
var testName = test["test"];
294+
//var fullName = modName + "." + testName;
295+
var fullName = testName;
296+
if (!allTests[fullName]) {
297+
allTests[fullName] = make_tuple(count);
298+
}
299+
var testCase = {
300+
elapsed: test["elapsed"],
301+
n: test["iter"],
302+
};
303+
allTests[fullName].push(testCase);
304+
});
305+
count++;
306+
307+
// fill missing snapshots
308+
_.each(allTests, function(snapshots) {
309+
while (snapshots.length < count) {
310+
snapshots.push(null);
311+
}
312+
});
313+
});
314+
315+
function redrawCharts(scale) {
316+
$("h1").remove();
317+
$("h2").remove();
318+
$("svg").remove();
319+
//add_chart(name, tests, scale);
320+
add_comparison_chart("Snapshotting", allTests, scale);
321+
}
322+
323+
$("#scale-selector").click(function() {
324+
var scale = $(this).val();
325+
redrawCharts(scale);
326+
});
327+
328+
$(function() {
329+
redrawCharts("linear");
330+
});
331+
</script>
332+
</body>
333+
</html>

0 commit comments

Comments
 (0)