Skip to content

Commit 8960e73

Browse files
committed
Refactor to use Docker
1 parent 259a634 commit 8960e73

473 files changed

Lines changed: 2961 additions & 3117 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Locals/Directory.Packages.props

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,6 @@
1919
<PackageVersion Include="Genbox.FastData.SourceGenerator" Version="0.2.0" />
2020
<PackageVersion Include="xunit.v3.extensibility.core" Version="3.2.2" />
2121
<PackageVersion Include="Mono.TextTemplating" Version="3.0.0" />
22+
<PackageVersion Include="Docker.DotNet" Version="3.125.15" />
2223
</ItemGroup>
2324
</Project>

Src/Directory.Packages.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,4 @@
1414
<!--benchmark packages-->
1515
<PackageVersion Include="BenchmarkDotNet" Version="0.15.8" />
1616
</ItemGroup>
17-
</Project>
17+
</Project>
Lines changed: 16 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,38 @@
1+
using System.Globalization;
12
using Genbox.FastData.Generator.CPlusPlus.TestHarness;
23
using Genbox.FastData.Generator.CSharp.TestHarness;
34
using Genbox.FastData.Generator.Rust.TestHarness;
45
using Genbox.FastData.InternalShared.Harness;
56
using Genbox.FastData.InternalShared.Helpers;
7+
using Genbox.FastData.InternalShared.TestClasses;
68

79
namespace Genbox.FastData.BenchmarkHarness.Runner;
810

911
internal static class Program
1012
{
11-
private const bool UseBencher = false;
12-
private const bool UseShell = true;
13-
14-
private static readonly BenchmarkBase[] Harnesses =
13+
private static readonly Func<DockerManager, BenchmarkBase>[] HarnessFactories =
1514
[
16-
CSharpBenchmark.Instance,
17-
CPlusPlusBenchmark.Instance,
18-
RustBenchmark.Instance
15+
x => new CSharpBenchmark(x),
16+
x => new CPlusPlusBenchmark(x),
17+
x => new RustBenchmark(x)
1918
];
2019

21-
private static void Main()
20+
private static async Task Main()
2221
{
23-
Parallel.ForEach(Harnesses, RunHarness);
22+
foreach (Func<DockerManager, BenchmarkBase> factory in HarnessFactories)
23+
await RunHarnessAsync(factory, CancellationToken.None);
2424
}
2525

26-
private static void RunHarness(BenchmarkBase harness)
26+
private static async ValueTask RunHarnessAsync(Func<DockerManager, BenchmarkBase> harnessFactory, CancellationToken cancellationToken)
2727
{
28-
BenchmarkSuite suite = harness.CreateFiles(TestVectorHelper.GetBenchmarkData());
29-
WriteSuite(harness.RootDir, suite);
30-
31-
Console.WriteLine($"Executing {harness.Name}");
32-
harness.Run(suite, UseBencher, UseShell);
33-
}
28+
await using DockerManager dockerManager = new DockerManager();
29+
BenchmarkBase harness = harnessFactory(dockerManager);
3430

35-
private static void WriteSuite(string rootDir, BenchmarkSuite suite)
36-
{
37-
string entryPath = Path.Combine(rootDir, suite.EntryFilename);
38-
FileHelper.TryWriteFile(entryPath, suite.EntrySource);
39-
40-
foreach (BenchmarkFile file in suite.AdditionalFiles)
31+
foreach (ITestData data in TestVectorHelper.GetBenchmarkData())
4132
{
42-
string filePath = Path.Combine(rootDir, file.Filename);
43-
string? fileDir = Path.GetDirectoryName(filePath);
44-
45-
if (fileDir != null && !Directory.Exists(fileDir))
46-
Directory.CreateDirectory(fileDir);
47-
48-
FileHelper.TryWriteFile(filePath, file.Source);
33+
double res = await harness.RunAsync(data, cancellationToken);
34+
string value = res.ToString("0.#################", CultureInfo.InvariantCulture);
35+
Console.WriteLine($"{harness.Name,-10} {data.Identifier,-30} {value}");
4936
}
5037
}
5138
}

Src/FastData.BenchmarkHarness.Runner/packages.lock.json

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,6 @@
5959
"fastdata.generator.cplusplus.testharness": {
6060
"type": "Project",
6161
"dependencies": {
62-
"FastData": "[1.0.0, )",
63-
"FastData.Generator": "[1.0.0, )",
6462
"FastData.Generator.CPlusPlus": "[1.0.0, )",
6563
"FastData.InternalShared": "[1.0.0, )"
6664
}
@@ -74,8 +72,6 @@
7472
"fastdata.generator.csharp.testharness": {
7573
"type": "Project",
7674
"dependencies": {
77-
"FastData": "[1.0.0, )",
78-
"FastData.Generator": "[1.0.0, )",
7975
"FastData.Generator.CSharp": "[1.0.0, )",
8076
"FastData.InternalShared": "[1.0.0, )"
8177
}
@@ -89,8 +85,6 @@
8985
"fastdata.generator.rust.testharness": {
9086
"type": "Project",
9187
"dependencies": {
92-
"FastData": "[1.0.0, )",
93-
"FastData.Generator": "[1.0.0, )",
9488
"FastData.Generator.Rust": "[1.0.0, )",
9589
"FastData.InternalShared": "[1.0.0, )"
9690
}
@@ -105,11 +99,21 @@
10599
"fastdata.internalshared": {
106100
"type": "Project",
107101
"dependencies": {
102+
"Docker.DotNet": "[3.125.15, )",
108103
"Microsoft.CodeAnalysis.CSharp": "[4.10.0, )",
109104
"Newtonsoft.Json": "[13.0.4, )",
110105
"xunit.v3.extensibility.core": "[3.2.2, )"
111106
}
112107
},
108+
"Docker.DotNet": {
109+
"type": "CentralTransitive",
110+
"requested": "[3.125.15, )",
111+
"resolved": "3.125.15",
112+
"contentHash": "XN8FKxVv8Mjmwu104/Hl9lM61pLY675s70gzwSj8KR5pwblo8HfWLcCuinh9kYsqujBkMH4HVRCEcRuU6al4BQ==",
113+
"dependencies": {
114+
"Newtonsoft.Json": "13.0.1"
115+
}
116+
},
113117
"Microsoft.CodeAnalysis.CSharp": {
114118
"type": "CentralTransitive",
115119
"requested": "[4.10.0, )",

Src/FastData.Benchmarks/Program.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ private static void DoStructure(Type type, int size)
6464
string[] data = Enumerable.Range(0, size).Select(_ => TestHelper.GenerateRandomString(rng, rng.Next(5, 10))).ToArray();
6565

6666
TestVector<string> vector = new TestVector<string>(type, data, []);
67-
GeneratorSpec spec = TestHelper.Generate(id => CSharpCodeGenerator.Create(new CSharpCodeGeneratorConfig(id)), vector);
68-
File.WriteAllText("Gen-" + type.GetCleanName() + "-" + size + ".cs", spec.Source);
67+
string source = TestGenerator.Generate(CSharpCodeGenerator.Create(new CSharpCodeGeneratorConfig("fastdata")), vector);
68+
File.WriteAllText("Gen-" + type.GetCleanName() + "-" + size + ".cs", source);
6969
}
7070
}

Src/FastData.Benchmarks/packages.lock.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,11 +199,21 @@
199199
"fastdata.internalshared": {
200200
"type": "Project",
201201
"dependencies": {
202+
"Docker.DotNet": "[3.125.15, )",
202203
"Microsoft.CodeAnalysis.CSharp": "[4.10.0, )",
203204
"Newtonsoft.Json": "[13.0.4, )",
204205
"xunit.v3.extensibility.core": "[3.2.2, )"
205206
}
206207
},
208+
"Docker.DotNet": {
209+
"type": "CentralTransitive",
210+
"requested": "[3.125.15, )",
211+
"resolved": "3.125.15",
212+
"contentHash": "XN8FKxVv8Mjmwu104/Hl9lM61pLY675s70gzwSj8KR5pwblo8HfWLcCuinh9kYsqujBkMH4HVRCEcRuU6al4BQ==",
213+
"dependencies": {
214+
"Newtonsoft.Json": "13.0.1"
215+
}
216+
},
207217
"Microsoft.CodeAnalysis.CSharp": {
208218
"type": "CentralTransitive",
209219
"requested": "[4.10.0, )",

Src/FastData.Cli.Tests/packages.lock.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,11 +277,21 @@
277277
"fastdata.internalshared": {
278278
"type": "Project",
279279
"dependencies": {
280+
"Docker.DotNet": "[3.125.15, )",
280281
"Microsoft.CodeAnalysis.CSharp": "[4.10.0, )",
281282
"Newtonsoft.Json": "[13.0.4, )",
282283
"xunit.v3.extensibility.core": "[3.2.2, )"
283284
}
284285
},
286+
"Docker.DotNet": {
287+
"type": "CentralTransitive",
288+
"requested": "[3.125.15, )",
289+
"resolved": "3.125.15",
290+
"contentHash": "XN8FKxVv8Mjmwu104/Hl9lM61pLY675s70gzwSj8KR5pwblo8HfWLcCuinh9kYsqujBkMH4HVRCEcRuU6al4BQ==",
291+
"dependencies": {
292+
"Newtonsoft.Json": "13.0.1"
293+
}
294+
},
285295
"Microsoft.CodeAnalysis.CSharp": {
286296
"type": "CentralTransitive",
287297
"requested": "[4.10.0, )",
Lines changed: 57 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -1,126 +1,67 @@
1-
using System.Globalization;
2-
using System.Text;
3-
using Genbox.FastData.Generator.CPlusPlus.TestHarness.Code;
4-
using Genbox.FastData.InternalShared;
1+
using Genbox.FastData.Generator.Extensions;
52
using Genbox.FastData.InternalShared.Harness;
63
using Genbox.FastData.InternalShared.Helpers;
7-
using Genbox.FastData.InternalShared.Misc;
84
using Genbox.FastData.InternalShared.TestClasses;
5+
using static System.Linq.Enumerable;
6+
using static Genbox.FastData.Generator.Helpers.FormatHelper;
97

108
namespace Genbox.FastData.Generator.CPlusPlus.TestHarness;
119

12-
public sealed class CPlusPlusBenchmark : BenchmarkBase<CPlusPlusBootstrap>
10+
public sealed class CPlusPlusBenchmark(DockerManager dockerManager) : BenchmarkBase<CPlusPlusBootstrap>(new CPlusPlusBootstrap(HarnessType.Benchmark), dockerManager)
1311
{
14-
private CPlusPlusBenchmark() : base(new CPlusPlusBootstrap(HarnessType.Benchmark)) {}
15-
16-
public static CPlusPlusBenchmark Instance { get; } = new CPlusPlusBenchmark();
17-
18-
public override BenchmarkSuite CreateFiles(IEnumerable<ITestData> data)
19-
{
20-
List<BenchmarkFile> files = new List<BenchmarkFile>();
21-
22-
foreach (ITestData item in data)
23-
{
24-
item.Generate(Bootstrap.GeneratorFactory, out GeneratorSpec spec);
25-
26-
string filename = "bench_" + spec.Identifier + ".cpp";
27-
files.Add(new BenchmarkFile(filename, $$"""
28-
#include <benchmark/benchmark.h>
29-
using namespace benchmark;
30-
31-
{{spec.Source}}
32-
33-
static void CPlusPlus_{{spec.Identifier}}(State& state)
34-
{
35-
for (auto _ : state)
36-
{
37-
{{RenderBenchmarkQueries(item, spec.Identifier)}}
38-
}
39-
}
40-
41-
BENCHMARK(CPlusPlus_{{spec.Identifier}});
42-
"""));
43-
}
44-
45-
files.Add(new BenchmarkFile("main.cpp", """
46-
#include <benchmark/benchmark.h>
47-
48-
BENCHMARK_MAIN();
49-
"""));
50-
51-
return new BenchmarkSuite("CMakeLists.txt", BuildCMakeLists(files.Select(x => x.Filename)), files);
52-
}
53-
54-
public override void Run(BenchmarkSuite suite, bool useBencher, bool useShell)
55-
{
56-
ProcessResult configureResult = ProcessHelper.RunProcess("cmake", "-S . -B build -DCMAKE_CXX_COMPILER=\"" + ClangCompiler.CompilerPath + "\"", Bootstrap.RootDir, 100_000);
57-
58-
if (configureResult.ExitCode != 0)
59-
throw new InvalidOperationException($"Failed to configure CMake. Exit code: {configureResult.ExitCode}\nSTDOUT:\n{configureResult.StandardOutput}\nSTDERR:\n{configureResult.StandardError}");
60-
61-
ProcessResult buildResult = ProcessHelper.RunProcess("cmake", "--build build --config Release", Bootstrap.RootDir, 100_000);
62-
63-
if (buildResult.ExitCode != 0)
64-
throw new InvalidOperationException($"Failed to build benchmarks. Exit code: {buildResult.ExitCode}\nSTDOUT:\n{buildResult.StandardOutput}\nSTDERR:\n{buildResult.StandardError}");
65-
66-
string executable = Path.Combine(Bootstrap.RootDir, "build", "out", "all_benchmarks.exe");
67-
68-
string args = useShell ? "--benchmark_min_time=5s" : "--benchmark_min_time=5s --benchmark_format=json";
69-
BenchmarkHelper.RunBenchmark(executable, args, Bootstrap.RootDir, "--adapter cpp_google --testbed CPlusPlus", useBencher, useShell);
70-
}
71-
72-
private string RenderBenchmarkQueries(ITestData data, string identifier)
73-
{
74-
StringBuilder sb = new StringBuilder();
75-
76-
for (int i = 0; i < 25; i++)
77-
sb.AppendLine(CultureInfo.InvariantCulture, $" DoNotOptimize({identifier}::contains({data.GetValueLabel(Bootstrap.Map)}));");
78-
79-
return sb.ToString();
80-
}
81-
82-
private static string BuildCMakeLists(IEnumerable<string> sources) =>
12+
protected override string Render(ITestData data) =>
8313
$$"""
84-
cmake_minimum_required(VERSION 3.20)
85-
86-
if(DEFINED ENV{FASTDATA_CLANGXX})
87-
set(_clangxx "$ENV{FASTDATA_CLANGXX}")
88-
if(IS_DIRECTORY "${_clangxx}")
89-
set(_clangxx "${_clangxx}/clang++")
90-
endif()
91-
if(WIN32 AND NOT EXISTS "${_clangxx}" AND EXISTS "${_clangxx}.exe")
92-
set(_clangxx "${_clangxx}.exe")
93-
endif()
94-
set(CMAKE_CXX_COMPILER "${_clangxx}" CACHE FILEPATH "" FORCE)
95-
endif()
96-
97-
project(fast_data_benchmarks LANGUAGES CXX)
98-
set(CMAKE_CXX_STANDARD 17)
99-
set(CMAKE_CXX_STANDARD_REQUIRED ON)
100-
set(CMAKE_CXX_EXTENSIONS OFF)
101-
102-
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/out")
103-
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/out")
104-
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/out")
105-
106-
add_compile_options(
107-
$<$<CONFIG:Release>:/O2>
108-
)
109-
110-
set(SOURCES
111-
{{string.Join(Environment.NewLine, sources.Select(source => $" {source}"))}}
112-
)
113-
114-
add_executable(all_benchmarks ${SOURCES})
115-
include(FetchContent)
116-
set(BENCHMARK_ENABLE_TESTING OFF CACHE BOOL "" FORCE)
117-
set(BENCHMARK_ENABLE_GTEST_TESTS OFF CACHE BOOL "" FORCE)
118-
119-
FetchContent_Declare(
120-
benchmark
121-
URL https://github.com/google/benchmark/archive/refs/tags/v1.9.5.zip
122-
)
123-
FetchContent_MakeAvailable(benchmark)
124-
target_link_libraries(all_benchmarks PRIVATE benchmark::benchmark)
14+
#include <array>
15+
#include <chrono>
16+
#include <cstdint>
17+
#include <iomanip>
18+
#include <iostream>
19+
#include <limits>
20+
#include <locale>
21+
#include <string>
22+
23+
template <class T>
24+
inline void DoNotOptimize(T& value) {
25+
asm volatile("" : "+g"(value) : : "memory");
26+
}
27+
28+
{{data.Generate(Bootstrap.Generator)}}
29+
30+
int main()
31+
{
32+
std::uint64_t found_count = 0;
33+
auto keys = std::array{ {{FormatList(Range(0, data.QueryCount)
34+
.Select(_ => data.GetRandomKey(Bootstrap.Map))
35+
.ToArray(), s => s, ", ")}} };
36+
std::size_t key_index = 0;
37+
auto start = std::chrono::steady_clock::now();
38+
39+
for (int i = 0; i < {{data.WorkIterations}}; i++)
40+
{
41+
{{FormatList(Range(0, data.QueryCount).ToArray(), _ =>
42+
"""
43+
{
44+
auto key = keys[key_index];
45+
if (++key_index == keys.size())
46+
key_index = 0;
47+
48+
DoNotOptimize(key);
49+
found_count += fastdata::contains(key) ? 1 : 0;
50+
}
51+
""", "\n")}}
52+
}
53+
54+
auto end = std::chrono::steady_clock::now();
55+
double elapsed_ns = std::chrono::duration<double, std::nano>(end - start).count();
56+
double elapsed_ns_per_call = elapsed_ns / {{Bootstrap.Map.ToValueLabel(data.WorkIterations * data.QueryCount)}};
57+
58+
DoNotOptimize(found_count);
59+
60+
std::cout.imbue(std::locale::classic());
61+
std::cout << std::setprecision(std::numeric_limits<double>::max_digits10)
62+
<< elapsed_ns_per_call << '\n';
63+
64+
return 0;
65+
}
12566
""";
12667
}

0 commit comments

Comments
 (0)