Skip to content

Commit 5483cbf

Browse files
authored
Annotate throughput with OS/Arch/Fwk (#589)
* info * endl * rem paren ---------
1 parent df9eb53 commit 5483cbf

File tree

1 file changed

+196
-175
lines changed

1 file changed

+196
-175
lines changed
Lines changed: 196 additions & 175 deletions
Original file line numberDiff line numberDiff line change
@@ -1,175 +1,196 @@
1-
using System;
2-
using System.Collections.Generic;
3-
using System.Data;
4-
using System.Globalization;
5-
using System.IO;
6-
using System.Linq;
7-
using CsvHelper;
8-
using Microsoft.FSharp.Core;
9-
using Plotly.NET;
10-
using Plotly.NET.ImageExport;
11-
using Plotly.NET.LayoutObjects;
12-
13-
namespace BitFaster.Caching.ThroughputAnalysis
14-
{
15-
public class Exporter
16-
{
17-
DataTable resultTable = new DataTable();
18-
19-
public Exporter(int minThreads, int maxThreads)
20-
{
21-
// output:
22-
// ThreadCount 1 2 3 4 5
23-
// Classic 5 6 7 7 8
24-
// Concurrent 5 6 7 7 8
25-
26-
resultTable.Clear();
27-
resultTable.Columns.Add("ThreadCount");
28-
foreach (var tc in Enumerable.Range(minThreads, maxThreads - (minThreads-1)).ToArray())
29-
{
30-
resultTable.Columns.Add(tc.ToString());
31-
}
32-
}
33-
34-
public void Initialize(IEnumerable<ICacheFactory> caches)
35-
{
36-
foreach (var c in caches)
37-
{
38-
c.DataRow = resultTable.NewRow();
39-
c.DataRow["ThreadCount"] = c.Name;
40-
}
41-
}
42-
43-
public void CaptureRows(IEnumerable<ICacheFactory> caches)
44-
{
45-
foreach (var c in caches)
46-
{
47-
resultTable.Rows.Add(c.DataRow);
48-
}
49-
}
50-
51-
public void ExportCsv(Mode mode, int cacheSize)
52-
{
53-
using (var textWriter = File.CreateText($"Results_{mode}_{cacheSize}.csv"))
54-
using (var csv = new CsvWriter(textWriter, CultureInfo.InvariantCulture))
55-
{
56-
foreach (DataColumn column in resultTable.Columns)
57-
{
58-
csv.WriteField(column.ColumnName);
59-
}
60-
csv.NextRecord();
61-
62-
foreach (DataRow row in resultTable.Rows)
63-
{
64-
for (var i = 0; i < resultTable.Columns.Count; i++)
65-
{
66-
csv.WriteField(row[i]);
67-
}
68-
csv.NextRecord();
69-
}
70-
}
71-
}
72-
73-
public void ExportPlot(Mode mode, int cacheSize)
74-
{
75-
var columns = new List<int>();
76-
77-
for(int i = 1; i < resultTable.Columns.Count; i++)
78-
{
79-
columns.Add(int.Parse(resultTable.Columns[i].ColumnName));
80-
}
81-
82-
List<GenericChart.GenericChart> charts = new List<GenericChart.GenericChart>();
83-
84-
foreach (DataRow row in resultTable.Rows)
85-
{
86-
var rowData = new List<double>();
87-
string name = row[0].ToString();
88-
for (var i = 1; i < resultTable.Columns.Count; i++)
89-
{
90-
// convert back to millions
91-
rowData.Add(double.Parse(row[i].ToString()) * 1_000_000);
92-
}
93-
94-
// var chart = Chart.Line<int, double, string>(columns, rowData, Name: name, MarkerColor: MapColor(name));
95-
var chart = Chart2D.Chart.Line<int, double, string>(columns, rowData, Name: name, MarkerColor: MapColor(name));
96-
charts.Add(chart);
97-
98-
var combined = Chart.Combine(charts);
99-
100-
combined
101-
.WithLayout(MapTitle(mode, cacheSize))
102-
.WithoutVerticalGridlines()
103-
.WithAxisTitles("Number of threads", "Ops/sec")
104-
.SaveSVG($"Results_{mode}_{cacheSize}", Width: 1000, Height: 600);
105-
}
106-
}
107-
108-
public string MapTitle(Mode mode, int cacheSize)
109-
{
110-
switch (mode)
111-
{
112-
case Mode.Read:
113-
return $"Read throughput (100% cache hit)";
114-
case Mode.ReadWrite:
115-
return $"Read + Write throughput";
116-
case Mode.Update:
117-
return $"Update throughput";
118-
case Mode.Evict:
119-
return $"Eviction throughput (100% cache miss)";
120-
default:
121-
return $"{mode} {cacheSize}";
122-
}
123-
}
124-
125-
public Color MapColor(string name)
126-
{
127-
switch (name)
128-
{
129-
case "ClassicLru":
130-
return Plotly.NET.Color.fromKeyword(Plotly.NET.ColorKeyword.Limegreen);
131-
case "MemoryCache":
132-
return Plotly.NET.Color.fromKeyword(Plotly.NET.ColorKeyword.FireBrick);
133-
case "FastConcurrentLru":
134-
return Plotly.NET.Color.fromKeyword(Plotly.NET.ColorKeyword.Silver);
135-
case "ConcurrentLru":
136-
return Plotly.NET.Color.fromKeyword(Plotly.NET.ColorKeyword.RoyalBlue);
137-
case "ConcurrentLfu":
138-
return Plotly.NET.Color.fromRGB(255, 192, 0);
139-
default:
140-
return Plotly.NET.Color.fromKeyword(Plotly.NET.ColorKeyword.FireBrick);
141-
}
142-
}
143-
}
144-
145-
public static class PlotExt
146-
{
147-
public static GenericChart.GenericChart WithAxisTitles(this GenericChart.GenericChart chart, string xTitle, string yTitle)
148-
{
149-
var font = new FSharpOption<Font>(Font.init(Size: new FSharpOption<double>(16)));
150-
FSharpOption<string> xt = new FSharpOption<string>(xTitle);
151-
FSharpOption<string> yt = new FSharpOption<string>(yTitle);
152-
return chart.WithXAxisStyle(Title.init(xt, Font: font)).WithYAxisStyle(Title.init(yt, Font: font));
153-
}
154-
155-
public static GenericChart.GenericChart WithoutVerticalGridlines(this GenericChart.GenericChart chart)
156-
{
157-
var gridColor = new FSharpOption<Color>(Color.fromKeyword(ColorKeyword.Gainsboro));
158-
var yaxis = LinearAxis.init<IConvertible, IConvertible, IConvertible, IConvertible, IConvertible, IConvertible>(
159-
GridColor: gridColor,
160-
ZeroLineColor: gridColor);
161-
162-
var axis = LinearAxis.init<IConvertible, IConvertible, IConvertible, IConvertible, IConvertible, IConvertible>(ShowGrid: new FSharpOption<bool>(false));
163-
return chart.WithXAxis(axis).WithYAxis(yaxis);
164-
}
165-
166-
public static GenericChart.GenericChart WithLayout(this GenericChart.GenericChart chart, string title)
167-
{
168-
var font = new FSharpOption<Font>(Font.init(Size: new FSharpOption<double>(24)));
169-
FSharpOption<Title> t = Title.init(Text: title, X: 0.5, Font: font);
170-
FSharpOption<Color> plotBGColor = new FSharpOption<Color>(Color.fromKeyword(ColorKeyword.WhiteSmoke));
171-
Layout layout = Layout.init<IConvertible>(PaperBGColor: plotBGColor, PlotBGColor: plotBGColor, Title: t);
172-
return chart.WithLayout(layout);
173-
}
174-
}
175-
}
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Data;
4+
using System.Globalization;
5+
using System.IO;
6+
using System.Linq;
7+
using System.Runtime.InteropServices;
8+
using CsvHelper;
9+
using Microsoft.FSharp.Core;
10+
using Plotly.NET;
11+
using Plotly.NET.ImageExport;
12+
using Plotly.NET.LayoutObjects;
13+
14+
namespace BitFaster.Caching.ThroughputAnalysis
15+
{
16+
public class Exporter
17+
{
18+
DataTable resultTable = new DataTable();
19+
20+
public Exporter(int minThreads, int maxThreads)
21+
{
22+
// output:
23+
// ThreadCount 1 2 3 4 5
24+
// Classic 5 6 7 7 8
25+
// Concurrent 5 6 7 7 8
26+
27+
resultTable.Clear();
28+
resultTable.Columns.Add("ThreadCount");
29+
foreach (var tc in Enumerable.Range(minThreads, maxThreads - (minThreads-1)).ToArray())
30+
{
31+
resultTable.Columns.Add(tc.ToString());
32+
}
33+
}
34+
35+
public void Initialize(IEnumerable<ICacheFactory> caches)
36+
{
37+
foreach (var c in caches)
38+
{
39+
c.DataRow = resultTable.NewRow();
40+
c.DataRow["ThreadCount"] = c.Name;
41+
}
42+
}
43+
44+
public void CaptureRows(IEnumerable<ICacheFactory> caches)
45+
{
46+
foreach (var c in caches)
47+
{
48+
resultTable.Rows.Add(c.DataRow);
49+
}
50+
}
51+
52+
public void ExportCsv(Mode mode, int cacheSize)
53+
{
54+
using (var textWriter = File.CreateText($"Results_{mode}_{cacheSize}.csv"))
55+
using (var csv = new CsvWriter(textWriter, CultureInfo.InvariantCulture))
56+
{
57+
foreach (DataColumn column in resultTable.Columns)
58+
{
59+
csv.WriteField(column.ColumnName);
60+
}
61+
csv.NextRecord();
62+
63+
foreach (DataRow row in resultTable.Rows)
64+
{
65+
for (var i = 0; i < resultTable.Columns.Count; i++)
66+
{
67+
csv.WriteField(row[i]);
68+
}
69+
csv.NextRecord();
70+
}
71+
}
72+
}
73+
74+
public void ExportPlot(Mode mode, int cacheSize)
75+
{
76+
var columns = new List<int>();
77+
78+
for(int i = 1; i < resultTable.Columns.Count; i++)
79+
{
80+
columns.Add(int.Parse(resultTable.Columns[i].ColumnName));
81+
}
82+
83+
List<GenericChart.GenericChart> charts = new List<GenericChart.GenericChart>();
84+
85+
foreach (DataRow row in resultTable.Rows)
86+
{
87+
var rowData = new List<double>();
88+
string name = row[0].ToString();
89+
for (var i = 1; i < resultTable.Columns.Count; i++)
90+
{
91+
// convert back to millions
92+
rowData.Add(double.Parse(row[i].ToString()) * 1_000_000);
93+
}
94+
95+
// var chart = Chart.Line<int, double, string>(columns, rowData, Name: name, MarkerColor: MapColor(name));
96+
var chart = Chart2D.Chart.Line<int, double, string>(columns, rowData, Name: name, MarkerColor: MapColor(name));
97+
charts.Add(chart);
98+
99+
var combined = Chart.Combine(charts);
100+
101+
combined
102+
.WithLayout(MapTitle(mode, cacheSize))
103+
.WithoutVerticalGridlines()
104+
.WithAxisTitles("Number of threads", "Ops/sec")
105+
.SaveSVG($"Results_{mode}_{cacheSize}", Width: 1000, Height: 600);
106+
}
107+
}
108+
109+
public string MapTitle(Mode mode, int cacheSize)
110+
{
111+
string arch = System.Runtime.InteropServices.RuntimeInformation.ProcessArchitecture.ToString();
112+
string fwk = RuntimeInformation.FrameworkDescription.ToString();
113+
114+
string os = "Win";
115+
116+
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
117+
{
118+
os = "Mac";
119+
}
120+
121+
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
122+
{
123+
os = "Linux";
124+
}
125+
126+
if (RuntimeInformation.IsOSPlatform(OSPlatform.FreeBSD))
127+
{
128+
os = "BSD";
129+
}
130+
131+
switch (mode)
132+
{
133+
case Mode.Read:
134+
return $"Read throughput, 100% cache hit ({os}/{arch}/{fwk})";
135+
case Mode.ReadWrite:
136+
return $"Read + Write throughput ({os}/{arch}/{fwk})";
137+
case Mode.Update:
138+
return $"Update throughput ({os}/{arch}/{fwk})";
139+
case Mode.Evict:
140+
return $"Eviction throughput, 100% cache miss ({os}/{arch}/{fwk})";
141+
default:
142+
return $"{mode} {cacheSize}";
143+
}
144+
}
145+
146+
public Color MapColor(string name)
147+
{
148+
switch (name)
149+
{
150+
case "ClassicLru":
151+
return Plotly.NET.Color.fromKeyword(Plotly.NET.ColorKeyword.Limegreen);
152+
case "MemoryCache":
153+
return Plotly.NET.Color.fromKeyword(Plotly.NET.ColorKeyword.FireBrick);
154+
case "FastConcurrentLru":
155+
return Plotly.NET.Color.fromKeyword(Plotly.NET.ColorKeyword.Silver);
156+
case "ConcurrentLru":
157+
return Plotly.NET.Color.fromKeyword(Plotly.NET.ColorKeyword.RoyalBlue);
158+
case "ConcurrentLfu":
159+
return Plotly.NET.Color.fromRGB(255, 192, 0);
160+
default:
161+
return Plotly.NET.Color.fromKeyword(Plotly.NET.ColorKeyword.FireBrick);
162+
}
163+
}
164+
}
165+
166+
public static class PlotExt
167+
{
168+
public static GenericChart.GenericChart WithAxisTitles(this GenericChart.GenericChart chart, string xTitle, string yTitle)
169+
{
170+
var font = new FSharpOption<Font>(Font.init(Size: new FSharpOption<double>(16)));
171+
FSharpOption<string> xt = new FSharpOption<string>(xTitle);
172+
FSharpOption<string> yt = new FSharpOption<string>(yTitle);
173+
return chart.WithXAxisStyle(Title.init(xt, Font: font)).WithYAxisStyle(Title.init(yt, Font: font));
174+
}
175+
176+
public static GenericChart.GenericChart WithoutVerticalGridlines(this GenericChart.GenericChart chart)
177+
{
178+
var gridColor = new FSharpOption<Color>(Color.fromKeyword(ColorKeyword.Gainsboro));
179+
var yaxis = LinearAxis.init<IConvertible, IConvertible, IConvertible, IConvertible, IConvertible, IConvertible>(
180+
GridColor: gridColor,
181+
ZeroLineColor: gridColor);
182+
183+
var axis = LinearAxis.init<IConvertible, IConvertible, IConvertible, IConvertible, IConvertible, IConvertible>(ShowGrid: new FSharpOption<bool>(false));
184+
return chart.WithXAxis(axis).WithYAxis(yaxis);
185+
}
186+
187+
public static GenericChart.GenericChart WithLayout(this GenericChart.GenericChart chart, string title)
188+
{
189+
var font = new FSharpOption<Font>(Font.init(Size: new FSharpOption<double>(24)));
190+
FSharpOption<Title> t = Title.init(Text: title, X: 0.5, Font: font);
191+
FSharpOption<Color> plotBGColor = new FSharpOption<Color>(Color.fromKeyword(ColorKeyword.WhiteSmoke));
192+
Layout layout = Layout.init<IConvertible>(PaperBGColor: plotBGColor, PlotBGColor: plotBGColor, Title: t);
193+
return chart.WithLayout(layout);
194+
}
195+
}
196+
}

0 commit comments

Comments
 (0)