-
Notifications
You must be signed in to change notification settings - Fork 48
Expand file tree
/
Copy pathResultsParser.cs
More file actions
165 lines (142 loc) · 5.78 KB
/
ResultsParser.cs
File metadata and controls
165 lines (142 loc) · 5.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
using System.Runtime.Serialization;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace _1brc
{
/// <summary>
/// Extract results from https://github.com/buybackoff/1brc-bench/ to a csv
/// </summary>
public class ResultsParser
{
private record struct ResultKey(string Cpu, string Dataset, string User, int Cores, int Threads);
private readonly Dictionary<ResultKey, List<double>> _results = new();
public void ExtractToCsv(string dirPath)
{
var batchDirs = Directory.EnumerateDirectories(dirPath);
foreach (string batchDir in batchDirs)
{
var dirName = Path.GetFileName(batchDir);
var cpu = dirName[..dirName.IndexOf('_')];
var batchDir1B = Path.Combine(batchDir, "1B");
if (Directory.Exists(batchDir1B))
ExtractBatch(cpu, "1B", batchDir1B);
var batchDir1B10K = Path.Combine(batchDir, "1B_10K");
if (Directory.Exists(batchDir1B10K))
ExtractBatch(cpu, "1B_10K", batchDir1B10K);
}
var summary =
_results
.OrderBy(x => x.Key.Cpu)
.ThenBy(x => x.Key.Dataset)
.ThenBy(x => x.Key.User)
.ThenBy(x => x.Key.Cores)
.ThenBy(x => x.Key.Threads)
.Select(x => (x.Key, Summarize(x.Value)));
var outputPath = Path.Combine(dirPath, "results.csv");
File.Delete(outputPath);
using var writer = File.AppendText(outputPath);
writer.WriteLine($"{nameof(ResultKey.Cpu)},{nameof(ResultKey.Dataset)},{nameof(ResultKey.User)},{nameof(ResultKey.Cores)},{nameof(ResultKey.Threads)},Min,Avg,StDev");
foreach ((ResultKey Key, (double Min, double Avg, double StDev)) in summary)
{
// https://github.com/buybackoff/1brc/issues/19
if (Min < 0.05) // NimaAra for 10K before fix
continue;
if (Key.User == "dzaima" && Key.Threads > 8) // Bad ENV with sudo
continue;
writer.WriteLine($"{Key.Cpu},{Key.Dataset},{Key.User},{Key.Cores},{Key.Threads},{Min:N3},{Avg:N3},{StDev:N3}");
}
}
private (double Min, double Avg, double StDev) Summarize(List<double> times)
{
var min = times[0];
var avg = min;
var stdDev = 0.0;
if (times.Count <= 3)
{
avg = times.Average();
stdDev = StdDev(times);
}
else if (times.Count < 25)
{
times = times.Skip(1).Take(times.Count - 2).ToList();
avg = times.Average();
stdDev = StdDev(times);
}
else
{
times = times.Skip(2).Take(times.Count - 5).ToList();
avg = times.Average();
stdDev = StdDev(times);
}
return (min, avg, stdDev);
}
public static double StdDev(IEnumerable<double> values)
{
double mean = 0.0;
double sum = 0.0;
double stdDev = 0.0;
int n = 0;
foreach (double val in values)
{
n++;
double delta = val - mean;
mean += delta / n;
sum += delta * (val - mean);
}
if (1 < n)
stdDev = Math.Sqrt(sum / (n - 1));
return stdDev;
}
private void ExtractBatch(string cpu, string dataset, string batchDir)
{
var userFiles = Directory.EnumerateFiles(batchDir);
foreach (var userFilePath in userFiles)
{
var fileName = Path.GetFileName(userFilePath);
var userName = fileName[..fileName.IndexOf('_')];
var coresStr = fileName.Substring(userName.Length + 1, fileName.IndexOf('_', userName.Length + 1) - (userName.Length + 1));
var threadsStr = fileName.Substring(userName.Length + 1 + coresStr.Length + 1,
fileName.IndexOf('_', userName.Length + 1 + coresStr.Length + 1) - (userName.Length + 1 + coresStr.Length + 1));
var cores = int.Parse(coresStr);
var threads = int.Parse(threadsStr);
List<Result>? results = null;
try
{
#pragma warning disable IL2026
#pragma warning disable IL3050
string json = File.ReadAllText(userFilePath);
var jsonWithResults = JsonSerializer.Deserialize<JsonWithResults>(json);
results = jsonWithResults?.Results;
#pragma warning restore IL3050
#pragma warning restore IL2026
}
catch
{
;
}
if (results != null && results.Count > 0 && results[0].Times.Count > 0)
{
var times = results[0].Times;
var key = new ResultKey(cpu, dataset, userName, cores, threads);
if (!_results.TryGetValue(key, out var resultTimes))
{
resultTimes = new List<double>();
_results[key] = resultTimes;
}
resultTimes.AddRange(times);
resultTimes.Sort();
}
}
}
public class JsonWithResults
{
[JsonPropertyName("results")]
public List<Result> Results { get; set; }
}
public class Result
{
[JsonPropertyName("times")]
public List<double> Times { get; set; }
}
}
}