tigerbeetle-node 0.11.13 → 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.
Files changed (146) hide show
  1. package/dist/bin/aarch64-linux-gnu/client.node +0 -0
  2. package/dist/bin/aarch64-linux-musl/client.node +0 -0
  3. package/dist/bin/aarch64-macos/client.node +0 -0
  4. package/dist/bin/x86_64-linux-gnu/client.node +0 -0
  5. package/dist/bin/x86_64-linux-musl/client.node +0 -0
  6. package/dist/bin/x86_64-macos/client.node +0 -0
  7. package/dist/index.js +33 -1
  8. package/dist/index.js.map +1 -1
  9. package/package-lock.json +66 -0
  10. package/package.json +6 -16
  11. package/src/index.ts +56 -1
  12. package/src/node.zig +9 -9
  13. package/dist/.client.node.sha256 +0 -1
  14. package/scripts/build_lib.sh +0 -61
  15. package/scripts/download_node_headers.sh +0 -32
  16. package/src/tigerbeetle/scripts/benchmark.bat +0 -55
  17. package/src/tigerbeetle/scripts/benchmark.sh +0 -66
  18. package/src/tigerbeetle/scripts/confirm_image.sh +0 -44
  19. package/src/tigerbeetle/scripts/fail_on_diff.sh +0 -9
  20. package/src/tigerbeetle/scripts/fuzz_loop.sh +0 -15
  21. package/src/tigerbeetle/scripts/fuzz_loop_hash_log.sh +0 -12
  22. package/src/tigerbeetle/scripts/fuzz_unique_errors.sh +0 -7
  23. package/src/tigerbeetle/scripts/install.bat +0 -7
  24. package/src/tigerbeetle/scripts/install.sh +0 -21
  25. package/src/tigerbeetle/scripts/install_zig.bat +0 -113
  26. package/src/tigerbeetle/scripts/install_zig.sh +0 -90
  27. package/src/tigerbeetle/scripts/lint.zig +0 -199
  28. package/src/tigerbeetle/scripts/pre-commit.sh +0 -9
  29. package/src/tigerbeetle/scripts/scripts/benchmark.bat +0 -55
  30. package/src/tigerbeetle/scripts/scripts/benchmark.sh +0 -66
  31. package/src/tigerbeetle/scripts/scripts/confirm_image.sh +0 -44
  32. package/src/tigerbeetle/scripts/scripts/fail_on_diff.sh +0 -9
  33. package/src/tigerbeetle/scripts/scripts/fuzz_loop.sh +0 -15
  34. package/src/tigerbeetle/scripts/scripts/fuzz_loop_hash_log.sh +0 -12
  35. package/src/tigerbeetle/scripts/scripts/fuzz_unique_errors.sh +0 -7
  36. package/src/tigerbeetle/scripts/scripts/install.bat +0 -7
  37. package/src/tigerbeetle/scripts/scripts/install.sh +0 -21
  38. package/src/tigerbeetle/scripts/scripts/install_zig.bat +0 -113
  39. package/src/tigerbeetle/scripts/scripts/install_zig.sh +0 -90
  40. package/src/tigerbeetle/scripts/scripts/lint.zig +0 -199
  41. package/src/tigerbeetle/scripts/scripts/pre-commit.sh +0 -9
  42. package/src/tigerbeetle/scripts/scripts/shellcheck.sh +0 -5
  43. package/src/tigerbeetle/scripts/scripts/tests_on_alpine.sh +0 -10
  44. package/src/tigerbeetle/scripts/scripts/tests_on_ubuntu.sh +0 -14
  45. package/src/tigerbeetle/scripts/scripts/upgrade_ubuntu_kernel.sh +0 -48
  46. package/src/tigerbeetle/scripts/scripts/validate_docs.sh +0 -23
  47. package/src/tigerbeetle/scripts/scripts/vr_state_enumerate +0 -46
  48. package/src/tigerbeetle/scripts/shellcheck.sh +0 -5
  49. package/src/tigerbeetle/scripts/tests_on_alpine.sh +0 -10
  50. package/src/tigerbeetle/scripts/tests_on_ubuntu.sh +0 -14
  51. package/src/tigerbeetle/scripts/upgrade_ubuntu_kernel.sh +0 -48
  52. package/src/tigerbeetle/scripts/validate_docs.sh +0 -23
  53. package/src/tigerbeetle/scripts/vr_state_enumerate +0 -46
  54. package/src/tigerbeetle/src/benchmark.zig +0 -336
  55. package/src/tigerbeetle/src/config.zig +0 -233
  56. package/src/tigerbeetle/src/constants.zig +0 -428
  57. package/src/tigerbeetle/src/ewah.zig +0 -286
  58. package/src/tigerbeetle/src/ewah_benchmark.zig +0 -120
  59. package/src/tigerbeetle/src/ewah_fuzz.zig +0 -130
  60. package/src/tigerbeetle/src/fifo.zig +0 -120
  61. package/src/tigerbeetle/src/io/benchmark.zig +0 -213
  62. package/src/tigerbeetle/src/io/darwin.zig +0 -814
  63. package/src/tigerbeetle/src/io/linux.zig +0 -1071
  64. package/src/tigerbeetle/src/io/test.zig +0 -643
  65. package/src/tigerbeetle/src/io/windows.zig +0 -1183
  66. package/src/tigerbeetle/src/io.zig +0 -34
  67. package/src/tigerbeetle/src/iops.zig +0 -107
  68. package/src/tigerbeetle/src/lsm/README.md +0 -308
  69. package/src/tigerbeetle/src/lsm/binary_search.zig +0 -341
  70. package/src/tigerbeetle/src/lsm/bloom_filter.zig +0 -125
  71. package/src/tigerbeetle/src/lsm/compaction.zig +0 -603
  72. package/src/tigerbeetle/src/lsm/composite_key.zig +0 -77
  73. package/src/tigerbeetle/src/lsm/direction.zig +0 -11
  74. package/src/tigerbeetle/src/lsm/eytzinger.zig +0 -587
  75. package/src/tigerbeetle/src/lsm/eytzinger_benchmark.zig +0 -330
  76. package/src/tigerbeetle/src/lsm/forest.zig +0 -205
  77. package/src/tigerbeetle/src/lsm/forest_fuzz.zig +0 -450
  78. package/src/tigerbeetle/src/lsm/grid.zig +0 -573
  79. package/src/tigerbeetle/src/lsm/groove.zig +0 -1036
  80. package/src/tigerbeetle/src/lsm/k_way_merge.zig +0 -474
  81. package/src/tigerbeetle/src/lsm/level_iterator.zig +0 -332
  82. package/src/tigerbeetle/src/lsm/manifest.zig +0 -617
  83. package/src/tigerbeetle/src/lsm/manifest_level.zig +0 -878
  84. package/src/tigerbeetle/src/lsm/manifest_log.zig +0 -789
  85. package/src/tigerbeetle/src/lsm/manifest_log_fuzz.zig +0 -691
  86. package/src/tigerbeetle/src/lsm/merge_iterator.zig +0 -106
  87. package/src/tigerbeetle/src/lsm/node_pool.zig +0 -235
  88. package/src/tigerbeetle/src/lsm/posted_groove.zig +0 -381
  89. package/src/tigerbeetle/src/lsm/segmented_array.zig +0 -1329
  90. package/src/tigerbeetle/src/lsm/segmented_array_benchmark.zig +0 -148
  91. package/src/tigerbeetle/src/lsm/segmented_array_fuzz.zig +0 -9
  92. package/src/tigerbeetle/src/lsm/set_associative_cache.zig +0 -850
  93. package/src/tigerbeetle/src/lsm/table.zig +0 -1009
  94. package/src/tigerbeetle/src/lsm/table_immutable.zig +0 -192
  95. package/src/tigerbeetle/src/lsm/table_iterator.zig +0 -340
  96. package/src/tigerbeetle/src/lsm/table_mutable.zig +0 -203
  97. package/src/tigerbeetle/src/lsm/test.zig +0 -439
  98. package/src/tigerbeetle/src/lsm/tree.zig +0 -1169
  99. package/src/tigerbeetle/src/lsm/tree_fuzz.zig +0 -479
  100. package/src/tigerbeetle/src/message_bus.zig +0 -1013
  101. package/src/tigerbeetle/src/message_pool.zig +0 -156
  102. package/src/tigerbeetle/src/ring_buffer.zig +0 -399
  103. package/src/tigerbeetle/src/simulator.zig +0 -580
  104. package/src/tigerbeetle/src/state_machine/auditor.zig +0 -578
  105. package/src/tigerbeetle/src/state_machine/workload.zig +0 -883
  106. package/src/tigerbeetle/src/state_machine.zig +0 -2099
  107. package/src/tigerbeetle/src/static_allocator.zig +0 -65
  108. package/src/tigerbeetle/src/stdx.zig +0 -171
  109. package/src/tigerbeetle/src/storage.zig +0 -393
  110. package/src/tigerbeetle/src/testing/cluster/message_bus.zig +0 -82
  111. package/src/tigerbeetle/src/testing/cluster/network.zig +0 -237
  112. package/src/tigerbeetle/src/testing/cluster/state_checker.zig +0 -169
  113. package/src/tigerbeetle/src/testing/cluster/storage_checker.zig +0 -202
  114. package/src/tigerbeetle/src/testing/cluster.zig +0 -444
  115. package/src/tigerbeetle/src/testing/fuzz.zig +0 -140
  116. package/src/tigerbeetle/src/testing/hash_log.zig +0 -66
  117. package/src/tigerbeetle/src/testing/id.zig +0 -99
  118. package/src/tigerbeetle/src/testing/packet_simulator.zig +0 -374
  119. package/src/tigerbeetle/src/testing/priority_queue.zig +0 -645
  120. package/src/tigerbeetle/src/testing/reply_sequence.zig +0 -139
  121. package/src/tigerbeetle/src/testing/state_machine.zig +0 -250
  122. package/src/tigerbeetle/src/testing/storage.zig +0 -757
  123. package/src/tigerbeetle/src/testing/table.zig +0 -247
  124. package/src/tigerbeetle/src/testing/time.zig +0 -84
  125. package/src/tigerbeetle/src/tigerbeetle.zig +0 -227
  126. package/src/tigerbeetle/src/time.zig +0 -112
  127. package/src/tigerbeetle/src/tracer.zig +0 -529
  128. package/src/tigerbeetle/src/unit_tests.zig +0 -40
  129. package/src/tigerbeetle/src/vopr.zig +0 -495
  130. package/src/tigerbeetle/src/vsr/README.md +0 -209
  131. package/src/tigerbeetle/src/vsr/client.zig +0 -544
  132. package/src/tigerbeetle/src/vsr/clock.zig +0 -855
  133. package/src/tigerbeetle/src/vsr/journal.zig +0 -2415
  134. package/src/tigerbeetle/src/vsr/journal_format_fuzz.zig +0 -111
  135. package/src/tigerbeetle/src/vsr/marzullo.zig +0 -309
  136. package/src/tigerbeetle/src/vsr/replica.zig +0 -6616
  137. package/src/tigerbeetle/src/vsr/replica_format.zig +0 -219
  138. package/src/tigerbeetle/src/vsr/superblock.zig +0 -1631
  139. package/src/tigerbeetle/src/vsr/superblock_client_table.zig +0 -256
  140. package/src/tigerbeetle/src/vsr/superblock_free_set.zig +0 -929
  141. package/src/tigerbeetle/src/vsr/superblock_free_set_fuzz.zig +0 -334
  142. package/src/tigerbeetle/src/vsr/superblock_fuzz.zig +0 -390
  143. package/src/tigerbeetle/src/vsr/superblock_manifest.zig +0 -615
  144. package/src/tigerbeetle/src/vsr/superblock_quorums.zig +0 -394
  145. package/src/tigerbeetle/src/vsr/superblock_quorums_fuzz.zig +0 -314
  146. package/src/tigerbeetle/src/vsr.zig +0 -1425
@@ -1,341 +0,0 @@
1
- const std = @import("std");
2
- const assert = std.debug.assert;
3
- const math = std.math;
4
-
5
- pub const Config = struct {
6
- verify: bool = false,
7
- };
8
-
9
- // TODO Add prefeching when @prefetch is available: https://github.com/ziglang/zig/issues/3600.
10
- //
11
- // TODO The Zig self hosted compiler will implement inlining itself before passing the IR to llvm,
12
- // which should eliminate the current poor codegen of key_from_value/compare_keys.
13
-
14
- /// Returns either the index of the first value equal to `key`,
15
- /// or if there is no such value then the index where `key` would be inserted.
16
- ///
17
- /// In other words, return `i` such that both:
18
- /// * key_from_value(values[i]) >= key or i == values.len
19
- /// * key_value_from(values[i-1]) < key or i == 0
20
- ///
21
- /// Doesn't perform the extra key comparison to determine if the match is exact.
22
- pub fn binary_search_values_raw(
23
- comptime Key: type,
24
- comptime Value: type,
25
- comptime key_from_value: fn (*const Value) callconv(.Inline) Key,
26
- comptime compare_keys: fn (Key, Key) callconv(.Inline) math.Order,
27
- values: []const Value,
28
- key: Key,
29
- comptime config: Config,
30
- ) u32 {
31
- if (values.len == 0) return 0;
32
-
33
- if (config.verify) {
34
- // Input must be sorted by key.
35
- for (values) |_, i| {
36
- assert(i == 0 or
37
- compare_keys(key_from_value(&values[i - 1]), key_from_value(&values[i])) != .gt);
38
- }
39
- }
40
-
41
- var offset: usize = 0;
42
- var length: usize = values.len;
43
- while (length > 1) {
44
- if (config.verify) {
45
- assert(offset == 0 or
46
- compare_keys(key_from_value(&values[offset - 1]), key) != .gt);
47
- assert(offset + length == values.len or
48
- compare_keys(key_from_value(&values[offset + length]), key) != .lt);
49
- }
50
-
51
- const half = length / 2;
52
- const mid = offset + half;
53
-
54
- // This trick seems to be what's needed to get llvm to emit branchless code for this,
55
- // a ternary-style if expression was generated as a jump here for whatever reason.
56
- const next_offsets = [_]usize{ offset, mid };
57
- offset = next_offsets[@boolToInt(compare_keys(key_from_value(&values[mid]), key) == .lt)];
58
-
59
- length -= half;
60
- }
61
-
62
- if (config.verify) {
63
- assert(length == 1);
64
- assert(offset == 0 or
65
- compare_keys(key_from_value(&values[offset - 1]), key) != .gt);
66
- assert(offset + length == values.len or
67
- compare_keys(key_from_value(&values[offset + length]), key) != .lt);
68
- }
69
-
70
- offset += @boolToInt(compare_keys(key_from_value(&values[offset]), key) == .lt);
71
-
72
- if (config.verify) {
73
- assert(offset == 0 or
74
- compare_keys(key_from_value(&values[offset - 1]), key) == .lt);
75
- assert(offset == values.len or
76
- compare_keys(key_from_value(&values[offset]), key) != .lt);
77
- }
78
-
79
- return @intCast(u32, offset);
80
- }
81
-
82
- pub inline fn binary_search_keys_raw(
83
- comptime Key: type,
84
- comptime compare_keys: fn (Key, Key) callconv(.Inline) math.Order,
85
- keys: []const Key,
86
- key: Key,
87
- comptime config: Config,
88
- ) u32 {
89
- return binary_search_values_raw(
90
- Key,
91
- Key,
92
- struct {
93
- inline fn key_from_key(k: *const Key) Key {
94
- return k.*;
95
- }
96
- }.key_from_key,
97
- compare_keys,
98
- keys,
99
- key,
100
- config,
101
- );
102
- }
103
-
104
- const BinarySearchResult = struct {
105
- index: u32,
106
- exact: bool,
107
- };
108
-
109
- pub inline fn binary_search_values(
110
- comptime Key: type,
111
- comptime Value: type,
112
- comptime key_from_value: fn (*const Value) callconv(.Inline) Key,
113
- comptime compare_keys: fn (Key, Key) callconv(.Inline) math.Order,
114
- values: []const Value,
115
- key: Key,
116
- comptime config: Config,
117
- ) BinarySearchResult {
118
- const index = binary_search_values_raw(Key, Value, key_from_value, compare_keys, values, key, config);
119
- return .{
120
- .index = index,
121
- .exact = index < values.len and compare_keys(key_from_value(&values[index]), key) == .eq,
122
- };
123
- }
124
-
125
- pub inline fn binary_search_keys(
126
- comptime Key: type,
127
- comptime compare_keys: fn (Key, Key) callconv(.Inline) math.Order,
128
- keys: []const Key,
129
- key: Key,
130
- comptime config: Config,
131
- ) BinarySearchResult {
132
- const index = binary_search_keys_raw(Key, compare_keys, keys, key, config);
133
- return .{
134
- .index = index,
135
- .exact = index < keys.len and compare_keys(keys[index], key) == .eq,
136
- };
137
- }
138
-
139
- const test_binary_search = struct {
140
- const fuzz = @import("../testing/fuzz.zig");
141
-
142
- const log = false;
143
-
144
- const gpa = std.testing.allocator;
145
-
146
- inline fn compare_keys(a: u32, b: u32) math.Order {
147
- return math.order(a, b);
148
- }
149
-
150
- fn less_than_key(_: void, a: u32, b: u32) bool {
151
- return a < b;
152
- }
153
-
154
- fn exhaustive_search(keys_count: u32) !void {
155
- const keys = try gpa.alloc(u32, keys_count);
156
- defer gpa.free(keys);
157
-
158
- for (keys) |*key, i| key.* = @intCast(u32, 7 * i + 3);
159
-
160
- var target_key: u32 = 0;
161
- while (target_key < keys_count + 13) : (target_key += 1) {
162
- var expect: BinarySearchResult = .{ .index = 0, .exact = false };
163
- for (keys) |key, i| {
164
- switch (compare_keys(key, target_key)) {
165
- .lt => expect.index = @intCast(u32, i) + 1,
166
- .eq => {
167
- expect.exact = true;
168
- break;
169
- },
170
- .gt => break,
171
- }
172
- }
173
-
174
- if (log) {
175
- std.debug.print("keys:", .{});
176
- for (keys) |k| std.debug.print("{},", .{k});
177
- std.debug.print("\n", .{});
178
- std.debug.print("target key: {}\n", .{target_key});
179
- }
180
-
181
- const actual = binary_search_keys(
182
- u32,
183
- compare_keys,
184
- keys,
185
- target_key,
186
- .{ .verify = true },
187
- );
188
-
189
- if (log) std.debug.print("expected: {}, actual: {}\n", .{ expect, actual });
190
- try std.testing.expectEqual(expect.index, actual.index);
191
- try std.testing.expectEqual(expect.exact, actual.exact);
192
- }
193
- }
194
-
195
- fn explicit_search(
196
- keys: []const u32,
197
- target_keys: []const u32,
198
- expected_results: []const BinarySearchResult,
199
- ) !void {
200
- assert(target_keys.len == expected_results.len);
201
-
202
- for (target_keys) |target_key, i| {
203
- if (log) {
204
- std.debug.print("keys:", .{});
205
- for (keys) |k| std.debug.print("{},", .{k});
206
- std.debug.print("\n", .{});
207
- std.debug.print("target key: {}\n", .{target_key});
208
- }
209
- const expect = expected_results[i];
210
- const actual = binary_search_keys(
211
- u32,
212
- compare_keys,
213
- keys,
214
- target_key,
215
- .{ .verify = true },
216
- );
217
- try std.testing.expectEqual(expect.index, actual.index);
218
- try std.testing.expectEqual(expect.exact, actual.exact);
219
- }
220
- }
221
-
222
- fn random_search(random: std.rand.Random, iter: usize) !void {
223
- const keys_count = @minimum(
224
- @as(usize, 1E6),
225
- fuzz.random_int_exponential(random, usize, iter),
226
- );
227
-
228
- const keys = try std.testing.allocator.alloc(u32, keys_count);
229
- defer std.testing.allocator.free(keys);
230
-
231
- for (keys) |*key| key.* = fuzz.random_int_exponential(random, u32, 100);
232
- std.sort.sort(u32, keys, {}, less_than_key);
233
- const target_key = fuzz.random_int_exponential(random, u32, 100);
234
-
235
- var expect: BinarySearchResult = .{ .index = 0, .exact = false };
236
- for (keys) |key, i| {
237
- switch (compare_keys(key, target_key)) {
238
- .lt => expect.index = @intCast(u32, i) + 1,
239
- .eq => {
240
- expect.exact = true;
241
- break;
242
- },
243
- .gt => break,
244
- }
245
- }
246
-
247
- const actual = binary_search_keys(
248
- u32,
249
- compare_keys,
250
- keys,
251
- target_key,
252
- .{ .verify = true },
253
- );
254
-
255
- if (log) std.debug.print("expected: {}, actual: {}\n", .{ expect, actual });
256
- try std.testing.expectEqual(expect.index, actual.index);
257
- try std.testing.expectEqual(expect.exact, actual.exact);
258
- }
259
- };
260
-
261
- // TODO test search on empty slice
262
- test "binary search: exhaustive" {
263
- if (test_binary_search.log) std.debug.print("\n", .{});
264
- var i: u32 = 1;
265
- while (i < 300) : (i += 1) {
266
- try test_binary_search.exhaustive_search(i);
267
- }
268
- }
269
-
270
- test "binary search: explicit" {
271
- if (test_binary_search.log) std.debug.print("\n", .{});
272
- try test_binary_search.explicit_search(
273
- &[_]u32{},
274
- &[_]u32{0},
275
- &[_]BinarySearchResult{
276
- .{ .index = 0, .exact = false },
277
- },
278
- );
279
- try test_binary_search.explicit_search(
280
- &[_]u32{1},
281
- &[_]u32{ 0, 1, 2 },
282
- &[_]BinarySearchResult{
283
- .{ .index = 0, .exact = false },
284
- .{ .index = 0, .exact = true },
285
- .{ .index = 1, .exact = false },
286
- },
287
- );
288
- try test_binary_search.explicit_search(
289
- &[_]u32{ 1, 3 },
290
- &[_]u32{ 0, 1, 2, 3, 4 },
291
- &[_]BinarySearchResult{
292
- .{ .index = 0, .exact = false },
293
- .{ .index = 0, .exact = true },
294
- .{ .index = 1, .exact = false },
295
- .{ .index = 1, .exact = true },
296
- .{ .index = 2, .exact = false },
297
- },
298
- );
299
- try test_binary_search.explicit_search(
300
- &[_]u32{ 1, 3, 5, 8, 9, 11 },
301
- &[_]u32{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 },
302
- &[_]BinarySearchResult{
303
- .{ .index = 0, .exact = false },
304
- .{ .index = 0, .exact = true },
305
- .{ .index = 1, .exact = false },
306
- .{ .index = 1, .exact = true },
307
- .{ .index = 2, .exact = false },
308
- .{ .index = 2, .exact = true },
309
- .{ .index = 3, .exact = false },
310
- .{ .index = 3, .exact = false },
311
- .{ .index = 3, .exact = true },
312
- .{ .index = 4, .exact = true },
313
- .{ .index = 5, .exact = false },
314
- .{ .index = 5, .exact = true },
315
- .{ .index = 6, .exact = false },
316
- .{ .index = 6, .exact = false },
317
- },
318
- );
319
- }
320
-
321
- test "binary search: duplicates" {
322
- if (test_binary_search.log) std.debug.print("\n", .{});
323
- try test_binary_search.explicit_search(
324
- &[_]u32{ 0, 0, 3, 3, 3, 5, 5, 5, 5 },
325
- &[_]u32{ 1, 2, 4, 6 },
326
- &[_]BinarySearchResult{
327
- .{ .index = 2, .exact = false },
328
- .{ .index = 2, .exact = false },
329
- .{ .index = 5, .exact = false },
330
- .{ .index = 9, .exact = false },
331
- },
332
- );
333
- }
334
-
335
- test "binary search: random" {
336
- var rng = std.rand.DefaultPrng.init(42);
337
- var i: usize = 0;
338
- while (i < 2048) : (i += 1) {
339
- try test_binary_search.random_search(rng.random(), i);
340
- }
341
- }
@@ -1,125 +0,0 @@
1
- //! Implementation of Split block Bloom filters: https://arxiv.org/pdf/2101.01719v4.pdf
2
-
3
- const std = @import("std");
4
- const assert = std.debug.assert;
5
- const mem = std.mem;
6
- const meta = std.meta;
7
-
8
- pub const Fingerprint = struct {
9
- /// Hash value used to map key to block.
10
- hash: u32,
11
- /// Mask of bits set in the block for the key.
12
- mask: meta.Vector(8, u32),
13
-
14
- pub fn create(key: []const u8) Fingerprint {
15
- const hash = std.hash.Wyhash.hash(0, key);
16
- const hash_lower = @truncate(u32, hash);
17
- const hash_upper = @intCast(u32, hash >> 32);
18
-
19
- // TODO These constants are from the paper and we understand them to be arbitrary odd
20
- // integers. Experimentally compare the performance of these with other randomly chosen
21
- // odd integers to verify/improve our understanding.
22
- const odd_integers: meta.Vector(8, u32) = [8]u32{
23
- 0x47b6137b,
24
- 0x44974d91,
25
- 0x8824ad5b,
26
- 0xa2b7289d,
27
- 0x705495c7,
28
- 0x2df1424b,
29
- 0x9efc4947,
30
- 0x5c6bfb31,
31
- };
32
-
33
- // Multiply-shift hashing. This produces 8 values in the range 0 to 31 (2^5 - 1).
34
- const bit_indexes = (odd_integers *% @splat(8, hash_lower)) >> @splat(8, @as(u5, 32 - 5));
35
-
36
- return .{
37
- .hash = hash_upper,
38
- .mask = @splat(8, @as(u32, 1)) << @intCast(meta.Vector(8, u5), bit_indexes),
39
- };
40
- }
41
- };
42
-
43
- /// Add the key with the given fingerprint to the filter.
44
- /// filter.len must be a multiple of 32.
45
- pub fn add(fingerprint: Fingerprint, filter: []u8) void {
46
- comptime assert(@sizeOf(meta.Vector(8, u32)) == 32);
47
-
48
- assert(filter.len > 0);
49
- assert(filter.len % @sizeOf(meta.Vector(8, u32)) == 0);
50
-
51
- const blocks = mem.bytesAsSlice([8]u32, filter);
52
- const index = block_index(fingerprint.hash, filter.len);
53
-
54
- const current: meta.Vector(8, u32) = blocks[index];
55
- blocks[index] = current | fingerprint.mask;
56
- }
57
-
58
- /// Check if the key with the given fingerprint may have been added to the filter.
59
- /// filter.len must be a multiple of 32.
60
- pub fn may_contain(fingerprint: Fingerprint, filter: []const u8) bool {
61
- comptime assert(@sizeOf(meta.Vector(8, u32)) == 32);
62
-
63
- assert(filter.len > 0);
64
- assert(filter.len % @sizeOf(meta.Vector(8, u32)) == 0);
65
-
66
- const blocks = mem.bytesAsSlice([8]u32, filter);
67
- const index = block_index(fingerprint.hash, filter.len);
68
-
69
- const current: meta.Vector(8, u32) = blocks[index];
70
- return @reduce(.Or, ~current & fingerprint.mask) == 0;
71
- }
72
-
73
- inline fn block_index(hash: u32, size: usize) u32 {
74
- assert(size > 0);
75
-
76
- const block_count = @divExact(size, @sizeOf(meta.Vector(8, u32)));
77
- return @intCast(u32, (@as(u64, hash) * block_count) >> 32);
78
- }
79
-
80
- test {
81
- _ = std.testing.refAllDecls(@This());
82
- }
83
-
84
- const test_bloom_filter = struct {
85
- const fuzz = @import("../testing/fuzz.zig");
86
- const block_size = @import("../constants.zig").block_size;
87
-
88
- fn random_keys(random: std.rand.Random, iter: usize) !void {
89
- const keys_count = @minimum(
90
- @as(usize, 1E6),
91
- fuzz.random_int_exponential(random, usize, iter),
92
- );
93
-
94
- const keys = try std.testing.allocator.alloc(u32, keys_count);
95
- defer std.testing.allocator.free(keys);
96
-
97
- for (keys) |*key| key.* = random.int(u32);
98
-
99
- // `block_size` is currently the only size bloom_filter that we use.
100
- const filter = try std.testing.allocator.alloc(u8, block_size);
101
- std.mem.set(u8, filter, 0);
102
- defer std.testing.allocator.free(filter);
103
-
104
- for (keys) |key| {
105
- add(Fingerprint.create(std.mem.asBytes(&key)), filter);
106
- }
107
- for (keys) |key| {
108
- try std.testing.expect(may_contain(Fingerprint.create(std.mem.asBytes(&key)), filter));
109
- }
110
-
111
- // TODO Test the false positive rate:
112
- // * Calculate the expected false positive rate
113
- // * Test with a large number of random keys.
114
- // * Use Chernoff bound or similar to determine a reasonable test cutoff.
115
- }
116
- };
117
-
118
- test "bloom filter: random" {
119
- var rng = std.rand.DefaultPrng.init(42);
120
- const iterations_max: usize = (1 << 12);
121
- var iterations: usize = 0;
122
- while (iterations < iterations_max) : (iterations += 1) {
123
- try test_bloom_filter.random_keys(rng.random(), iterations);
124
- }
125
- }