tigerbeetle-node 0.11.12 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +212 -196
- package/dist/bin/aarch64-linux-gnu/client.node +0 -0
- package/dist/bin/aarch64-linux-musl/client.node +0 -0
- package/dist/bin/aarch64-macos/client.node +0 -0
- package/dist/bin/x86_64-linux-gnu/client.node +0 -0
- package/dist/bin/x86_64-linux-musl/client.node +0 -0
- package/dist/bin/x86_64-macos/client.node +0 -0
- package/dist/index.js +33 -1
- package/dist/index.js.map +1 -1
- package/package-lock.json +66 -0
- package/package.json +8 -17
- package/src/index.ts +56 -1
- package/src/node.zig +10 -9
- package/dist/.client.node.sha256 +0 -1
- package/scripts/build_lib.sh +0 -61
- package/scripts/download_node_headers.sh +0 -32
- package/src/tigerbeetle/scripts/benchmark.bat +0 -48
- package/src/tigerbeetle/scripts/benchmark.sh +0 -66
- package/src/tigerbeetle/scripts/confirm_image.sh +0 -44
- package/src/tigerbeetle/scripts/fuzz_loop.sh +0 -15
- package/src/tigerbeetle/scripts/fuzz_unique_errors.sh +0 -7
- package/src/tigerbeetle/scripts/install.bat +0 -7
- package/src/tigerbeetle/scripts/install.sh +0 -21
- package/src/tigerbeetle/scripts/install_zig.bat +0 -113
- package/src/tigerbeetle/scripts/install_zig.sh +0 -90
- package/src/tigerbeetle/scripts/lint.zig +0 -199
- package/src/tigerbeetle/scripts/pre-commit.sh +0 -9
- package/src/tigerbeetle/scripts/scripts/benchmark.bat +0 -48
- package/src/tigerbeetle/scripts/scripts/benchmark.sh +0 -66
- package/src/tigerbeetle/scripts/scripts/confirm_image.sh +0 -44
- package/src/tigerbeetle/scripts/scripts/fuzz_loop.sh +0 -15
- package/src/tigerbeetle/scripts/scripts/fuzz_unique_errors.sh +0 -7
- package/src/tigerbeetle/scripts/scripts/install.bat +0 -7
- package/src/tigerbeetle/scripts/scripts/install.sh +0 -21
- package/src/tigerbeetle/scripts/scripts/install_zig.bat +0 -113
- package/src/tigerbeetle/scripts/scripts/install_zig.sh +0 -90
- package/src/tigerbeetle/scripts/scripts/lint.zig +0 -199
- package/src/tigerbeetle/scripts/scripts/pre-commit.sh +0 -9
- package/src/tigerbeetle/scripts/scripts/shellcheck.sh +0 -5
- package/src/tigerbeetle/scripts/scripts/tests_on_alpine.sh +0 -10
- package/src/tigerbeetle/scripts/scripts/tests_on_ubuntu.sh +0 -14
- package/src/tigerbeetle/scripts/scripts/upgrade_ubuntu_kernel.sh +0 -48
- package/src/tigerbeetle/scripts/scripts/validate_docs.sh +0 -23
- package/src/tigerbeetle/scripts/scripts/vr_state_enumerate +0 -46
- package/src/tigerbeetle/scripts/shellcheck.sh +0 -5
- package/src/tigerbeetle/scripts/tests_on_alpine.sh +0 -10
- package/src/tigerbeetle/scripts/tests_on_ubuntu.sh +0 -14
- package/src/tigerbeetle/scripts/upgrade_ubuntu_kernel.sh +0 -48
- package/src/tigerbeetle/scripts/validate_docs.sh +0 -23
- package/src/tigerbeetle/scripts/vr_state_enumerate +0 -46
- package/src/tigerbeetle/src/benchmark.zig +0 -314
- package/src/tigerbeetle/src/config.zig +0 -234
- package/src/tigerbeetle/src/constants.zig +0 -436
- package/src/tigerbeetle/src/ewah.zig +0 -286
- package/src/tigerbeetle/src/ewah_benchmark.zig +0 -120
- package/src/tigerbeetle/src/ewah_fuzz.zig +0 -130
- package/src/tigerbeetle/src/fifo.zig +0 -120
- package/src/tigerbeetle/src/io/benchmark.zig +0 -213
- package/src/tigerbeetle/src/io/darwin.zig +0 -814
- package/src/tigerbeetle/src/io/linux.zig +0 -1062
- package/src/tigerbeetle/src/io/test.zig +0 -643
- package/src/tigerbeetle/src/io/windows.zig +0 -1183
- package/src/tigerbeetle/src/io.zig +0 -34
- package/src/tigerbeetle/src/iops.zig +0 -107
- package/src/tigerbeetle/src/lsm/README.md +0 -308
- package/src/tigerbeetle/src/lsm/binary_search.zig +0 -341
- package/src/tigerbeetle/src/lsm/bloom_filter.zig +0 -125
- package/src/tigerbeetle/src/lsm/compaction.zig +0 -603
- package/src/tigerbeetle/src/lsm/composite_key.zig +0 -77
- package/src/tigerbeetle/src/lsm/direction.zig +0 -11
- package/src/tigerbeetle/src/lsm/eytzinger.zig +0 -587
- package/src/tigerbeetle/src/lsm/eytzinger_benchmark.zig +0 -330
- package/src/tigerbeetle/src/lsm/forest.zig +0 -204
- package/src/tigerbeetle/src/lsm/forest_fuzz.zig +0 -401
- package/src/tigerbeetle/src/lsm/grid.zig +0 -573
- package/src/tigerbeetle/src/lsm/groove.zig +0 -972
- package/src/tigerbeetle/src/lsm/k_way_merge.zig +0 -474
- package/src/tigerbeetle/src/lsm/level_iterator.zig +0 -332
- package/src/tigerbeetle/src/lsm/manifest.zig +0 -617
- package/src/tigerbeetle/src/lsm/manifest_level.zig +0 -877
- package/src/tigerbeetle/src/lsm/manifest_log.zig +0 -789
- package/src/tigerbeetle/src/lsm/manifest_log_fuzz.zig +0 -691
- package/src/tigerbeetle/src/lsm/merge_iterator.zig +0 -106
- package/src/tigerbeetle/src/lsm/node_pool.zig +0 -235
- package/src/tigerbeetle/src/lsm/posted_groove.zig +0 -378
- package/src/tigerbeetle/src/lsm/segmented_array.zig +0 -1328
- package/src/tigerbeetle/src/lsm/segmented_array_benchmark.zig +0 -148
- package/src/tigerbeetle/src/lsm/segmented_array_fuzz.zig +0 -9
- package/src/tigerbeetle/src/lsm/set_associative_cache.zig +0 -850
- package/src/tigerbeetle/src/lsm/table.zig +0 -1031
- package/src/tigerbeetle/src/lsm/table_immutable.zig +0 -203
- package/src/tigerbeetle/src/lsm/table_iterator.zig +0 -340
- package/src/tigerbeetle/src/lsm/table_mutable.zig +0 -220
- package/src/tigerbeetle/src/lsm/test.zig +0 -438
- package/src/tigerbeetle/src/lsm/tree.zig +0 -1193
- package/src/tigerbeetle/src/lsm/tree_fuzz.zig +0 -474
- package/src/tigerbeetle/src/message_bus.zig +0 -1012
- package/src/tigerbeetle/src/message_pool.zig +0 -156
- package/src/tigerbeetle/src/ring_buffer.zig +0 -399
- package/src/tigerbeetle/src/simulator.zig +0 -569
- package/src/tigerbeetle/src/state_machine/auditor.zig +0 -577
- package/src/tigerbeetle/src/state_machine/workload.zig +0 -883
- package/src/tigerbeetle/src/state_machine.zig +0 -1881
- package/src/tigerbeetle/src/static_allocator.zig +0 -65
- package/src/tigerbeetle/src/stdx.zig +0 -162
- package/src/tigerbeetle/src/storage.zig +0 -393
- package/src/tigerbeetle/src/testing/cluster/message_bus.zig +0 -82
- package/src/tigerbeetle/src/testing/cluster/network.zig +0 -237
- package/src/tigerbeetle/src/testing/cluster/state_checker.zig +0 -169
- package/src/tigerbeetle/src/testing/cluster/storage_checker.zig +0 -202
- package/src/tigerbeetle/src/testing/cluster.zig +0 -443
- package/src/tigerbeetle/src/testing/fuzz.zig +0 -140
- package/src/tigerbeetle/src/testing/hash_log.zig +0 -66
- package/src/tigerbeetle/src/testing/id.zig +0 -99
- package/src/tigerbeetle/src/testing/packet_simulator.zig +0 -364
- package/src/tigerbeetle/src/testing/priority_queue.zig +0 -645
- package/src/tigerbeetle/src/testing/reply_sequence.zig +0 -139
- package/src/tigerbeetle/src/testing/state_machine.zig +0 -249
- package/src/tigerbeetle/src/testing/storage.zig +0 -757
- package/src/tigerbeetle/src/testing/table.zig +0 -247
- package/src/tigerbeetle/src/testing/time.zig +0 -84
- package/src/tigerbeetle/src/tigerbeetle.zig +0 -227
- package/src/tigerbeetle/src/time.zig +0 -112
- package/src/tigerbeetle/src/tracer.zig +0 -529
- package/src/tigerbeetle/src/unit_tests.zig +0 -42
- package/src/tigerbeetle/src/vopr.zig +0 -495
- package/src/tigerbeetle/src/vsr/README.md +0 -209
- package/src/tigerbeetle/src/vsr/client.zig +0 -544
- package/src/tigerbeetle/src/vsr/clock.zig +0 -853
- package/src/tigerbeetle/src/vsr/journal.zig +0 -2413
- package/src/tigerbeetle/src/vsr/journal_format_fuzz.zig +0 -111
- package/src/tigerbeetle/src/vsr/marzullo.zig +0 -309
- package/src/tigerbeetle/src/vsr/replica.zig +0 -6381
- package/src/tigerbeetle/src/vsr/replica_format.zig +0 -219
- package/src/tigerbeetle/src/vsr/superblock.zig +0 -1631
- package/src/tigerbeetle/src/vsr/superblock_client_table.zig +0 -256
- package/src/tigerbeetle/src/vsr/superblock_free_set.zig +0 -929
- package/src/tigerbeetle/src/vsr/superblock_free_set_fuzz.zig +0 -334
- package/src/tigerbeetle/src/vsr/superblock_fuzz.zig +0 -390
- package/src/tigerbeetle/src/vsr/superblock_manifest.zig +0 -615
- package/src/tigerbeetle/src/vsr/superblock_quorums.zig +0 -394
- package/src/tigerbeetle/src/vsr/superblock_quorums_fuzz.zig +0 -314
- package/src/tigerbeetle/src/vsr.zig +0 -1352
|
@@ -1,330 +0,0 @@
|
|
|
1
|
-
const std = @import("std");
|
|
2
|
-
const assert = std.debug.assert;
|
|
3
|
-
const math = std.math;
|
|
4
|
-
|
|
5
|
-
const binary_search_keys_raw = @import("./binary_search.zig").binary_search_keys_raw;
|
|
6
|
-
const binary_search_values_raw = @import("./binary_search.zig").binary_search_values_raw;
|
|
7
|
-
const eytzinger = @import("./eytzinger.zig").eytzinger;
|
|
8
|
-
|
|
9
|
-
const GiB = 1 << 30;
|
|
10
|
-
const searches = 500_000;
|
|
11
|
-
|
|
12
|
-
const kv_types = .{
|
|
13
|
-
.{ .key_size = 8, .value_size = 128 },
|
|
14
|
-
.{ .key_size = 8, .value_size = 64 },
|
|
15
|
-
.{ .key_size = 16, .value_size = 16 },
|
|
16
|
-
.{ .key_size = 32, .value_size = 32 },
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
// keys_per_summary = values_per_page / summary_fraction
|
|
20
|
-
const summary_fractions = .{ 4, 8, 16, 32 };
|
|
21
|
-
const values_per_page = .{ 128, 256, 512, 1024, 2048, 4096, 8192 };
|
|
22
|
-
const body_fmt = "{:_>2}B/{:_>3}B {:_>4}/{:_>4} {s}{s}: WT={:_>6}ns UT={:_>6}ns" ++
|
|
23
|
-
" CY={:_>6} IN={:_>6} CR={:_>5} CM={:_>5} BM={}\n";
|
|
24
|
-
|
|
25
|
-
const summary_sizes = blk: {
|
|
26
|
-
var sizes: [values_per_page.len][summary_fractions.len]usize = undefined;
|
|
27
|
-
for (values_per_page) |values_count, v| {
|
|
28
|
-
for (summary_fractions) |fraction, k| {
|
|
29
|
-
// Set in reverse order so that the summary sizes ascend.
|
|
30
|
-
sizes[v][summary_fractions.len - k - 1] = values_count / fraction;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
break :blk sizes;
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
pub fn main() !void {
|
|
37
|
-
std.log.info("Samples: {}", .{searches});
|
|
38
|
-
std.log.info("WT: Wall time/search", .{});
|
|
39
|
-
std.log.info("UT: utime time/search", .{});
|
|
40
|
-
std.log.info("CY: CPU cycles/search", .{});
|
|
41
|
-
std.log.info("IN: instructions/search", .{});
|
|
42
|
-
std.log.info("CR: cache references/search", .{});
|
|
43
|
-
std.log.info("CM: cache misses/search", .{});
|
|
44
|
-
std.log.info("BM: branch misses/search", .{});
|
|
45
|
-
|
|
46
|
-
var seed: u64 = undefined;
|
|
47
|
-
try std.os.getrandom(std.mem.asBytes(&seed));
|
|
48
|
-
var prng = std.rand.DefaultPrng.init(seed);
|
|
49
|
-
|
|
50
|
-
// Allocate on the heap just once.
|
|
51
|
-
// All page allocations reuse this buffer to speed up the run time.
|
|
52
|
-
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
|
53
|
-
defer arena.deinit();
|
|
54
|
-
|
|
55
|
-
const blob_size = GiB;
|
|
56
|
-
var blob = try arena.allocator().alloc(u8, blob_size);
|
|
57
|
-
|
|
58
|
-
inline for (kv_types) |kv| {
|
|
59
|
-
inline for (values_per_page) |values_count, v| {
|
|
60
|
-
inline for (summary_sizes[v]) |keys_count| {
|
|
61
|
-
try run_benchmark(.{
|
|
62
|
-
.blob_size = blob_size,
|
|
63
|
-
.key_size = kv.key_size,
|
|
64
|
-
.value_size = kv.value_size,
|
|
65
|
-
.keys_count = keys_count,
|
|
66
|
-
.values_count = values_count,
|
|
67
|
-
.searches = searches,
|
|
68
|
-
}, blob, prng.random());
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
fn run_benchmark(comptime layout: Layout, blob: []u8, random: std.rand.Random) !void {
|
|
75
|
-
assert(blob.len == layout.blob_size);
|
|
76
|
-
const Eytzinger = eytzinger(layout.keys_count - 1, layout.values_count);
|
|
77
|
-
const V = Value(layout);
|
|
78
|
-
const K = V.Key;
|
|
79
|
-
const Page = struct {
|
|
80
|
-
keys: [layout.keys_count]K,
|
|
81
|
-
values: [layout.values_count]V,
|
|
82
|
-
};
|
|
83
|
-
const page_count = layout.blob_size / @sizeOf(Page);
|
|
84
|
-
|
|
85
|
-
// Search pages and keys in random order.
|
|
86
|
-
var page_picker = shuffled_index(page_count, random);
|
|
87
|
-
var value_picker = shuffled_index(layout.values_count, random);
|
|
88
|
-
|
|
89
|
-
// Generate 1GiB worth of 24KiB pages.
|
|
90
|
-
var blob_alloc = std.heap.FixedBufferAllocator.init(blob);
|
|
91
|
-
var pages = try blob_alloc.allocator().alloc(Page, page_count);
|
|
92
|
-
random.bytes(std.mem.sliceAsBytes(pages));
|
|
93
|
-
for (pages) |*page| {
|
|
94
|
-
for (page.values) |*value, i| value.key = i;
|
|
95
|
-
Eytzinger.layout_from_keys_or_values(K, V, V.key_from_value, V.max_key, &page.values, &page.keys);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
const stdout = std.io.getStdOut().writer();
|
|
99
|
-
{
|
|
100
|
-
var benchmark = try Benchmark.begin();
|
|
101
|
-
var i: usize = 0;
|
|
102
|
-
var v: usize = 0;
|
|
103
|
-
while (i < layout.searches) : (i += 1) {
|
|
104
|
-
const page_index = page_picker[i % page_picker.len];
|
|
105
|
-
const target = value_picker[v % value_picker.len];
|
|
106
|
-
const page = &pages[page_index];
|
|
107
|
-
const bounds = Eytzinger.search_values(K, V, V.key_compare, &page.keys, &page.values, target);
|
|
108
|
-
const hit = bounds[
|
|
109
|
-
binary_search_values_raw(
|
|
110
|
-
K,
|
|
111
|
-
V,
|
|
112
|
-
V.key_from_value,
|
|
113
|
-
V.key_compare,
|
|
114
|
-
bounds,
|
|
115
|
-
target,
|
|
116
|
-
.{},
|
|
117
|
-
)
|
|
118
|
-
];
|
|
119
|
-
|
|
120
|
-
assert(hit.key == target);
|
|
121
|
-
if (i % pages.len == 0) v += 1;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
const result = try benchmark.end(layout.searches);
|
|
125
|
-
try stdout.print(body_fmt, .{
|
|
126
|
-
layout.key_size,
|
|
127
|
-
layout.value_size,
|
|
128
|
-
layout.keys_count,
|
|
129
|
-
layout.values_count,
|
|
130
|
-
"E",
|
|
131
|
-
"B",
|
|
132
|
-
result.wall_time,
|
|
133
|
-
result.utime,
|
|
134
|
-
result.cpu_cycles,
|
|
135
|
-
result.instructions,
|
|
136
|
-
result.cache_references,
|
|
137
|
-
result.cache_misses,
|
|
138
|
-
result.branch_misses,
|
|
139
|
-
});
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
{
|
|
143
|
-
var benchmark = try Benchmark.begin();
|
|
144
|
-
var i: usize = 0;
|
|
145
|
-
var v: usize = 0;
|
|
146
|
-
while (i < layout.searches) : (i += 1) {
|
|
147
|
-
const target = value_picker[v % value_picker.len];
|
|
148
|
-
const page = &pages[page_picker[i % page_picker.len]];
|
|
149
|
-
const hit = page.values[
|
|
150
|
-
binary_search_values_raw(
|
|
151
|
-
K,
|
|
152
|
-
V,
|
|
153
|
-
V.key_from_value,
|
|
154
|
-
V.key_compare,
|
|
155
|
-
page.values[0..],
|
|
156
|
-
target,
|
|
157
|
-
.{},
|
|
158
|
-
)
|
|
159
|
-
];
|
|
160
|
-
|
|
161
|
-
assert(hit.key == target);
|
|
162
|
-
if (i % pages.len == 0) v += 1;
|
|
163
|
-
}
|
|
164
|
-
const result = try benchmark.end(layout.searches);
|
|
165
|
-
try stdout.print(body_fmt, .{
|
|
166
|
-
layout.key_size,
|
|
167
|
-
layout.value_size,
|
|
168
|
-
layout.keys_count,
|
|
169
|
-
layout.values_count,
|
|
170
|
-
"_",
|
|
171
|
-
"B",
|
|
172
|
-
result.wall_time,
|
|
173
|
-
result.utime,
|
|
174
|
-
result.cpu_cycles,
|
|
175
|
-
result.instructions,
|
|
176
|
-
result.cache_references,
|
|
177
|
-
result.cache_misses,
|
|
178
|
-
result.branch_misses,
|
|
179
|
-
});
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
const Layout = struct {
|
|
184
|
-
blob_size: usize, // bytes allocated for all pages
|
|
185
|
-
key_size: usize, // bytes per key
|
|
186
|
-
value_size: usize, // bytes per value
|
|
187
|
-
keys_count: usize, // keys per page (in the summary)
|
|
188
|
-
values_count: usize, // values per page
|
|
189
|
-
searches: usize,
|
|
190
|
-
};
|
|
191
|
-
|
|
192
|
-
fn Value(comptime layout: Layout) type {
|
|
193
|
-
return struct {
|
|
194
|
-
pub const max_key = 1 << (8 * layout.key_size) - 1;
|
|
195
|
-
pub const Key = math.IntFittingRange(0, max_key);
|
|
196
|
-
const Self = @This();
|
|
197
|
-
key: Key,
|
|
198
|
-
body: [layout.value_size - layout.key_size]u8,
|
|
199
|
-
|
|
200
|
-
comptime {
|
|
201
|
-
assert(@sizeOf(Key) == layout.key_size);
|
|
202
|
-
assert(@sizeOf(Self) == layout.value_size);
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
inline fn key_from_value(self: *const Self) Key {
|
|
206
|
-
return self.key;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
inline fn key_compare(a: Key, b: Key) math.Order {
|
|
210
|
-
return math.order(a, b);
|
|
211
|
-
}
|
|
212
|
-
};
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
const BenchmarkResult = struct {
|
|
216
|
-
wall_time: u64, // nanoseconds
|
|
217
|
-
utime: u64, // nanoseconds
|
|
218
|
-
cpu_cycles: usize,
|
|
219
|
-
instructions: usize,
|
|
220
|
-
cache_references: usize,
|
|
221
|
-
cache_misses: usize,
|
|
222
|
-
branch_misses: usize,
|
|
223
|
-
};
|
|
224
|
-
|
|
225
|
-
const PERF = std.os.linux.PERF;
|
|
226
|
-
const perf_counters = [_]PERF.COUNT.HW{
|
|
227
|
-
PERF.COUNT.HW.CPU_CYCLES,
|
|
228
|
-
PERF.COUNT.HW.INSTRUCTIONS,
|
|
229
|
-
PERF.COUNT.HW.CACHE_REFERENCES,
|
|
230
|
-
PERF.COUNT.HW.CACHE_MISSES,
|
|
231
|
-
PERF.COUNT.HW.BRANCH_MISSES,
|
|
232
|
-
};
|
|
233
|
-
|
|
234
|
-
const Benchmark = struct {
|
|
235
|
-
timer: std.time.Timer,
|
|
236
|
-
rusage: std.os.rusage,
|
|
237
|
-
perf_fds: [perf_counters.len]std.os.fd_t,
|
|
238
|
-
|
|
239
|
-
fn begin() !Benchmark {
|
|
240
|
-
var perf_fds = [1]std.os.fd_t{-1} ** perf_counters.len;
|
|
241
|
-
for (perf_counters) |counter, i| {
|
|
242
|
-
var attr: std.os.linux.perf_event_attr = .{
|
|
243
|
-
.type = PERF.TYPE.HARDWARE,
|
|
244
|
-
.config = @enumToInt(counter),
|
|
245
|
-
.flags = .{
|
|
246
|
-
.disabled = true,
|
|
247
|
-
.exclude_kernel = true,
|
|
248
|
-
.exclude_hv = true,
|
|
249
|
-
},
|
|
250
|
-
};
|
|
251
|
-
perf_fds[i] = try std.os.perf_event_open(&attr, 0, -1, perf_fds[0], PERF.FLAG.FD_CLOEXEC);
|
|
252
|
-
}
|
|
253
|
-
const err = std.os.linux.ioctl(perf_fds[0], PERF.EVENT_IOC.ENABLE, PERF.IOC_FLAG_GROUP);
|
|
254
|
-
if (err == -1) return error.Unexpected;
|
|
255
|
-
|
|
256
|
-
// Start the wall clock after perf, since setup is slow.
|
|
257
|
-
const timer = try std.time.Timer.start();
|
|
258
|
-
return Benchmark{
|
|
259
|
-
.timer = timer,
|
|
260
|
-
// TODO pass std.os.linux.rusage.SELF once Zig is upgraded
|
|
261
|
-
.rusage = std.os.getrusage(0),
|
|
262
|
-
.perf_fds = perf_fds,
|
|
263
|
-
};
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
fn end(self: *Benchmark, samples: usize) !BenchmarkResult {
|
|
267
|
-
defer {
|
|
268
|
-
for (perf_counters) |_, i| {
|
|
269
|
-
std.os.close(self.perf_fds[i]);
|
|
270
|
-
self.perf_fds[i] = -1;
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
const rusage = std.os.getrusage(0);
|
|
275
|
-
const err = std.os.linux.ioctl(self.perf_fds[0], PERF.EVENT_IOC.DISABLE, PERF.IOC_FLAG_GROUP);
|
|
276
|
-
if (err == -1) return error.Unexpected;
|
|
277
|
-
return BenchmarkResult{
|
|
278
|
-
.wall_time = self.timer.read() / samples,
|
|
279
|
-
.utime = (timeval_to_ns(rusage.utime) - timeval_to_ns(self.rusage.utime)) / samples,
|
|
280
|
-
.cpu_cycles = (try readPerfFd(self.perf_fds[0])) / samples,
|
|
281
|
-
.instructions = (try readPerfFd(self.perf_fds[1])) / samples,
|
|
282
|
-
.cache_references = (try readPerfFd(self.perf_fds[2])) / samples,
|
|
283
|
-
.cache_misses = (try readPerfFd(self.perf_fds[3])) / samples,
|
|
284
|
-
.branch_misses = (try readPerfFd(self.perf_fds[4])) / samples,
|
|
285
|
-
};
|
|
286
|
-
}
|
|
287
|
-
};
|
|
288
|
-
|
|
289
|
-
// shuffle([0,1,…,n-1])
|
|
290
|
-
fn shuffled_index(comptime n: usize, rand: std.rand.Random) [n]usize {
|
|
291
|
-
var indices: [n]usize = undefined;
|
|
292
|
-
for (indices) |*i, j| i.* = j;
|
|
293
|
-
rand.shuffle(usize, indices[0..]);
|
|
294
|
-
return indices;
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
fn timeval_to_ns(tv: std.os.timeval) u64 {
|
|
298
|
-
const ns_per_us = std.time.ns_per_s / std.time.us_per_s;
|
|
299
|
-
return @bitCast(u64, tv.tv_sec) * std.time.ns_per_s +
|
|
300
|
-
@bitCast(u64, tv.tv_usec) * ns_per_us;
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
fn readPerfFd(fd: std.os.fd_t) !usize {
|
|
304
|
-
var result: usize = 0;
|
|
305
|
-
const n = try std.os.read(fd, std.mem.asBytes(&result));
|
|
306
|
-
assert(n == @sizeOf(usize));
|
|
307
|
-
|
|
308
|
-
return result;
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
fn binary_search_keys(
|
|
312
|
-
comptime layout: Layout,
|
|
313
|
-
comptime Key: type,
|
|
314
|
-
comptime V: type,
|
|
315
|
-
comptime compare_keys: fn (Key, Key) math.Order,
|
|
316
|
-
keys: []const Key,
|
|
317
|
-
values: []const V,
|
|
318
|
-
key: Key,
|
|
319
|
-
) []const V {
|
|
320
|
-
assert(keys.len == layout.keys_count);
|
|
321
|
-
assert(values.len == layout.values_count);
|
|
322
|
-
|
|
323
|
-
const key_index = binary_search_keys_raw(Key, compare_keys, keys, key, .{});
|
|
324
|
-
const key_stride = layout.values_count / layout.keys_count;
|
|
325
|
-
const high = key_index * key_stride;
|
|
326
|
-
if (key_index < keys.len and keys[key_index] == key) {
|
|
327
|
-
return if (high == 0) values[0..1] else values[high - 1 .. high];
|
|
328
|
-
}
|
|
329
|
-
return values[high - key_stride .. high];
|
|
330
|
-
}
|
|
@@ -1,204 +0,0 @@
|
|
|
1
|
-
const std = @import("std");
|
|
2
|
-
const builtin = @import("builtin");
|
|
3
|
-
const assert = std.debug.assert;
|
|
4
|
-
const math = std.math;
|
|
5
|
-
const mem = std.mem;
|
|
6
|
-
|
|
7
|
-
const constants = @import("../constants.zig");
|
|
8
|
-
const vsr = @import("../vsr.zig");
|
|
9
|
-
|
|
10
|
-
const GridType = @import("grid.zig").GridType;
|
|
11
|
-
const NodePool = @import("node_pool.zig").NodePool(constants.lsm_manifest_node_size, 16);
|
|
12
|
-
|
|
13
|
-
pub fn ForestType(comptime Storage: type, comptime groove_config: anytype) type {
|
|
14
|
-
var groove_fields: []const std.builtin.TypeInfo.StructField = &.{};
|
|
15
|
-
var groove_options_fields: []const std.builtin.TypeInfo.StructField = &.{};
|
|
16
|
-
|
|
17
|
-
for (std.meta.fields(@TypeOf(groove_config))) |field| {
|
|
18
|
-
const Groove = @field(groove_config, field.name);
|
|
19
|
-
groove_fields = groove_fields ++ [_]std.builtin.TypeInfo.StructField{
|
|
20
|
-
.{
|
|
21
|
-
.name = field.name,
|
|
22
|
-
.field_type = Groove,
|
|
23
|
-
.default_value = null,
|
|
24
|
-
.is_comptime = false,
|
|
25
|
-
.alignment = @alignOf(Groove),
|
|
26
|
-
},
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
groove_options_fields = groove_options_fields ++ [_]std.builtin.TypeInfo.StructField{
|
|
30
|
-
.{
|
|
31
|
-
.name = field.name,
|
|
32
|
-
.field_type = Groove.Options,
|
|
33
|
-
.default_value = null,
|
|
34
|
-
.is_comptime = false,
|
|
35
|
-
.alignment = @alignOf(Groove),
|
|
36
|
-
},
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const Grooves = @Type(.{
|
|
41
|
-
.Struct = .{
|
|
42
|
-
.layout = .Auto,
|
|
43
|
-
.fields = groove_fields,
|
|
44
|
-
.decls = &.{},
|
|
45
|
-
.is_tuple = false,
|
|
46
|
-
},
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
const _GroovesOptions = @Type(.{
|
|
50
|
-
.Struct = .{
|
|
51
|
-
.layout = .Auto,
|
|
52
|
-
.fields = groove_options_fields,
|
|
53
|
-
.decls = &.{},
|
|
54
|
-
.is_tuple = false,
|
|
55
|
-
},
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
return struct {
|
|
59
|
-
const Forest = @This();
|
|
60
|
-
|
|
61
|
-
const Grid = GridType(Storage);
|
|
62
|
-
|
|
63
|
-
const Callback = fn (*Forest) void;
|
|
64
|
-
const JoinOp = enum {
|
|
65
|
-
compacting,
|
|
66
|
-
checkpoint,
|
|
67
|
-
open,
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
pub const GroovesOptions = _GroovesOptions;
|
|
71
|
-
|
|
72
|
-
join_op: ?JoinOp = null,
|
|
73
|
-
join_pending: usize = 0,
|
|
74
|
-
join_callback: ?Callback = null,
|
|
75
|
-
|
|
76
|
-
grid: *Grid,
|
|
77
|
-
grooves: Grooves,
|
|
78
|
-
node_pool: *NodePool,
|
|
79
|
-
|
|
80
|
-
pub fn init(
|
|
81
|
-
allocator: mem.Allocator,
|
|
82
|
-
grid: *Grid,
|
|
83
|
-
node_count: u32,
|
|
84
|
-
// (e.g.) .{ .transfers = .{ .cache_entries_max = 128, … }, .accounts = … }
|
|
85
|
-
grooves_options: GroovesOptions,
|
|
86
|
-
) !Forest {
|
|
87
|
-
// NodePool must be allocated to pass in a stable address for the Grooves.
|
|
88
|
-
const node_pool = try allocator.create(NodePool);
|
|
89
|
-
errdefer allocator.destroy(node_pool);
|
|
90
|
-
|
|
91
|
-
// TODO: look into using lsm_table_size_max for the node_count.
|
|
92
|
-
node_pool.* = try NodePool.init(allocator, node_count);
|
|
93
|
-
errdefer node_pool.deinit(allocator);
|
|
94
|
-
|
|
95
|
-
var grooves: Grooves = undefined;
|
|
96
|
-
var grooves_initialized: usize = 0;
|
|
97
|
-
|
|
98
|
-
errdefer inline for (std.meta.fields(Grooves)) |field, field_index| {
|
|
99
|
-
if (grooves_initialized >= field_index + 1) {
|
|
100
|
-
@field(grooves, field.name).deinit(allocator);
|
|
101
|
-
}
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
inline for (std.meta.fields(Grooves)) |groove_field| {
|
|
105
|
-
const groove = &@field(grooves, groove_field.name);
|
|
106
|
-
const Groove = @TypeOf(groove.*);
|
|
107
|
-
const groove_options: Groove.Options = @field(grooves_options, groove_field.name);
|
|
108
|
-
|
|
109
|
-
groove.* = try Groove.init(
|
|
110
|
-
allocator,
|
|
111
|
-
node_pool,
|
|
112
|
-
grid,
|
|
113
|
-
groove_options,
|
|
114
|
-
);
|
|
115
|
-
|
|
116
|
-
grooves_initialized += 1;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
return Forest{
|
|
120
|
-
.grid = grid,
|
|
121
|
-
.grooves = grooves,
|
|
122
|
-
.node_pool = node_pool,
|
|
123
|
-
};
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
pub fn deinit(forest: *Forest, allocator: mem.Allocator) void {
|
|
127
|
-
inline for (std.meta.fields(Grooves)) |field| {
|
|
128
|
-
@field(forest.grooves, field.name).deinit(allocator);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
forest.node_pool.deinit(allocator);
|
|
132
|
-
allocator.destroy(forest.node_pool);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
fn JoinType(comptime join_op: JoinOp) type {
|
|
136
|
-
return struct {
|
|
137
|
-
pub fn start(forest: *Forest, callback: Callback) void {
|
|
138
|
-
assert(forest.join_op == null);
|
|
139
|
-
assert(forest.join_pending == 0);
|
|
140
|
-
assert(forest.join_callback == null);
|
|
141
|
-
|
|
142
|
-
forest.join_op = join_op;
|
|
143
|
-
forest.join_pending = std.meta.fields(Grooves).len;
|
|
144
|
-
forest.join_callback = callback;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
fn GrooveFor(comptime groove_field_name: []const u8) type {
|
|
148
|
-
return @TypeOf(@field(@as(Grooves, undefined), groove_field_name));
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
pub fn groove_callback(
|
|
152
|
-
comptime groove_field_name: []const u8,
|
|
153
|
-
) fn (*GrooveFor(groove_field_name)) void {
|
|
154
|
-
return struct {
|
|
155
|
-
fn groove_cb(groove: *GrooveFor(groove_field_name)) void {
|
|
156
|
-
const grooves = @fieldParentPtr(Grooves, groove_field_name, groove);
|
|
157
|
-
const forest = @fieldParentPtr(Forest, "grooves", grooves);
|
|
158
|
-
|
|
159
|
-
assert(forest.join_op == join_op);
|
|
160
|
-
assert(forest.join_callback != null);
|
|
161
|
-
assert(forest.join_pending <= std.meta.fields(Grooves).len);
|
|
162
|
-
|
|
163
|
-
forest.join_pending -= 1;
|
|
164
|
-
if (forest.join_pending > 0) return;
|
|
165
|
-
|
|
166
|
-
const callback = forest.join_callback.?;
|
|
167
|
-
forest.join_op = null;
|
|
168
|
-
forest.join_callback = null;
|
|
169
|
-
callback(forest);
|
|
170
|
-
}
|
|
171
|
-
}.groove_cb;
|
|
172
|
-
}
|
|
173
|
-
};
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
pub fn open(forest: *Forest, callback: Callback) void {
|
|
177
|
-
const Join = JoinType(.open);
|
|
178
|
-
Join.start(forest, callback);
|
|
179
|
-
|
|
180
|
-
inline for (std.meta.fields(Grooves)) |field| {
|
|
181
|
-
@field(forest.grooves, field.name).open(Join.groove_callback(field.name));
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
pub fn compact(forest: *Forest, callback: Callback, op: u64) void {
|
|
186
|
-
// Start a compacting join.
|
|
187
|
-
const Join = JoinType(.compacting);
|
|
188
|
-
Join.start(forest, callback);
|
|
189
|
-
|
|
190
|
-
inline for (std.meta.fields(Grooves)) |field| {
|
|
191
|
-
@field(forest.grooves, field.name).compact(Join.groove_callback(field.name), op);
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
pub fn checkpoint(forest: *Forest, callback: Callback) void {
|
|
196
|
-
const Join = JoinType(.checkpoint);
|
|
197
|
-
Join.start(forest, callback);
|
|
198
|
-
|
|
199
|
-
inline for (std.meta.fields(Grooves)) |field| {
|
|
200
|
-
@field(forest.grooves, field.name).checkpoint(Join.groove_callback(field.name));
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
};
|
|
204
|
-
}
|