From 05bcfac85f4beb6c06a22d155372a1d9e6de86ad Mon Sep 17 00:00:00 2001 From: jinzhongjia Date: Sun, 3 May 2026 20:07:17 +0800 Subject: [PATCH 1/3] fix: add compatibility for Zig 0.16 ArrayList and timer changes - Replace legacy ArrayList initializers with `initCapacity()` in relevant places to support Zig 0.16, preserving compatibility with older releases. - Update benchmarks to use platform time routines when std.time.Timer is removed in Zig 0.16, and switch to page_allocator where GeneralPurposeAllocator is no longer available. - Expand workflow support to include Zig 0.16.0. - Clarify version support and adaptation details in documentation. --- .github/workflows/benchmark.yml | 2 +- .github/workflows/format-check.yml | 2 +- .github/workflows/test.yml | 2 +- CLAUDE.md | 7 +++-- src/bench.zig | 48 ++++++++++++++++++++++++++---- src/msgpack.zig | 4 +-- src/test.zig | 42 +++++++++++++------------- 7 files changed, 73 insertions(+), 34 deletions(-) diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index 44c6e2a..f975140 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -28,7 +28,7 @@ jobs: - name: Setup Zig uses: goto-bus-stop/setup-zig@v2 with: - version: 0.15.1 + version: 0.16.0 - name: Display platform information shell: bash diff --git a/.github/workflows/format-check.yml b/.github/workflows/format-check.yml index 6a53bb6..480bb06 100644 --- a/.github/workflows/format-check.yml +++ b/.github/workflows/format-check.yml @@ -19,7 +19,7 @@ jobs: - name: Setup Zig uses: goto-bus-stop/setup-zig@v2 with: - version: 0.15.1 + version: 0.16.0 - name: Check code formatting run: zig fmt --check . diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a6a16a1..162b804 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -25,7 +25,7 @@ jobs: # 架构配置标识符 arch_config: [linux-x86_64, linux-aarch64, macos-arm64, windows-x86_64] # 定时任务只测试 master 版本,其他情况测试所有版本 - version: ${{ github.event_name == 'schedule' && fromJSON('["master"]') || fromJSON('["0.14.1", "0.15.1", "master"]') }} + version: ${{ github.event_name == 'schedule' && fromJSON('["master"]') || fromJSON('["0.14.1", "0.15.1", "0.16.0", "master"]') }} include: # Linux x86_64 - arch_config: linux-x86_64 diff --git a/CLAUDE.md b/CLAUDE.md index bf04d40..c0b1379 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -21,13 +21,16 @@ zig build docs ``` ### Zig Version Compatibility -- **Currently supports**: Zig 0.14.0 and 0.15.x -- **Partial support**: Zig 0.16 (nightly) - may have compatibility issues +- **Currently supports**: Zig 0.14.0, 0.15.x, and 0.16.0 - **Legacy support**: Zig 0.11-0.13 (use library version 0.0.6 for Zig 0.13 and older) - Code uses version detection (`builtin.zig_version.minor`) to handle API differences: - Endianness enum changes (`.Big`/`.Little` vs `.big`/`.little`) - ArrayList API changes in Zig 0.15+ (allocator parameter required for methods) + - ArrayList initialization changes in Zig 0.16 (`std.ArrayList(T){}` removed, use `initCapacity`) - Build system API differences between versions + - `std.time.Timer` removed in 0.16 (replaced with platform-specific timing in benchmarks) + - `std.heap.GeneralPurposeAllocator` removed in 0.16 (replaced with `page_allocator`) + - `std.io.fixedBufferStream` removed in 0.16 (compat layer provides `BufferStream`) ## Architecture diff --git a/src/bench.zig b/src/bench.zig index 06df513..84c9e01 100644 --- a/src/bench.zig +++ b/src/bench.zig @@ -16,6 +16,27 @@ const pack = msgpack.Pack( bufferType.read, ); +const is_zig_16 = builtin.zig_version.minor >= 16; + +/// Get monotonic time in nanoseconds (cross-platform) +fn getTimeNs() u64 { + if (builtin.os.tag == .windows) { + const w = std.os.windows; + var counter: w.LARGE_INTEGER = undefined; + _ = w.ntdll.RtlQueryPerformanceCounter(&counter); + var freq: w.LARGE_INTEGER = undefined; + _ = w.ntdll.RtlQueryPerformanceFrequency(&freq); + const ns = std.time.ns_per_s; + const c: u64 = @bitCast(counter); + const f: u64 = @bitCast(freq); + return @intCast(@divTrunc(@as(u128, c) * ns, @as(u128, f))); + } else if (builtin.os.tag != .windows) { + var ts: std.c.timespec = undefined; + _ = std.c.clock_gettime(std.c.CLOCK.MONOTONIC, &ts); + return @as(u64, @intCast(ts.tv_sec)) * std.time.ns_per_s + @as(u64, @intCast(ts.tv_nsec)); + } else @compileError("unsupported OS for benchmark"); +} + /// Benchmark timer helper /// Run a benchmark and print results fn benchmark( @@ -23,9 +44,7 @@ fn benchmark( comptime iterations: usize, comptime func: fn (allocator: std.mem.Allocator) anyerror!void, ) !void { - var gpa = std.heap.GeneralPurposeAllocator(.{}){}; - defer _ = gpa.deinit(); - const allocator = gpa.allocator(); + const allocator = std.heap.page_allocator; // Warmup for (0..10) |_| { @@ -33,11 +52,15 @@ fn benchmark( } // Actual benchmark - var timer = try std.time.Timer.start(); + var legacy_timer: if (is_zig_16) void else std.time.Timer = if (is_zig_16) {} else undefined; + if (!is_zig_16) legacy_timer = try std.time.Timer.start(); + const start_ns = if (is_zig_16) getTimeNs() else 0; + for (0..iterations) |_| { try func(allocator); } - const elapsed_ns = timer.read(); + + const elapsed_ns = if (is_zig_16) getTimeNs() - start_ns else legacy_timer.read(); const avg_ns = elapsed_ns / iterations; const ops_per_sec = if (avg_ns > 0) (1_000_000_000 / avg_ns) else 0; @@ -850,7 +873,7 @@ fn benchMixedTypesRead(allocator: std.mem.Allocator) !void { // Main Benchmark Runner // ============================================================================ -pub fn main() !void { +fn runBenchmarks() !void { std.debug.print("\n", .{}); std.debug.print("=" ** 80 ++ "\n", .{}); std.debug.print("MessagePack Benchmark Suite\n", .{}); @@ -936,3 +959,16 @@ pub fn main() !void { std.debug.print("Benchmark Complete\n", .{}); std.debug.print("=" ** 80 ++ "\n", .{}); } + +const BenchEntry = if (is_zig_16) struct { + pub fn main(init: std.process.Init) !void { + _ = &init; + try runBenchmarks(); + } +} else struct { + pub fn main() !void { + try runBenchmarks(); + } +}; + +pub const main = BenchEntry.main; diff --git a/src/msgpack.zig b/src/msgpack.zig index 7327751..6ae2d0e 100644 --- a/src/msgpack.zig +++ b/src/msgpack.zig @@ -1316,7 +1316,7 @@ pub const Payload = union(enum) { var new_heap = if (current_zig.minor == 14) std.ArrayList(Payload).init(alloc) else - std.ArrayList(Payload){}; + std.ArrayList(Payload).initCapacity(alloc, 0) catch unreachable; // Copy existing items from stack buffer to heap for (buffer[0..len.*]) |item| { @@ -2857,7 +2857,7 @@ pub fn PackWithLimits( var parse_stack = if (current_zig.minor == 14) std.ArrayList(ParseState).init(allocator) else - std.ArrayList(ParseState){}; + try std.ArrayList(ParseState).initCapacity(allocator, 0); defer if (current_zig.minor == 14) parse_stack.deinit() else parse_stack.deinit(allocator); errdefer cleanupParseStack(&parse_stack, allocator); diff --git a/src/test.zig b/src/test.zig index 19e5637..1e6806e 100644 --- a/src/test.zig +++ b/src/test.zig @@ -6,6 +6,8 @@ const allocator = std.testing.allocator; const expect = std.testing.expect; const Payload = msgpack.Payload; +const has_new_io = builtin.zig_version.minor >= 15; + fn u8eql(a: []const u8, b: []const u8) bool { return std.mem.eql(u8, a, b); } @@ -76,7 +78,7 @@ test "PackerIO: corrupted length field" { var input = if (builtin.zig_version.minor == 14) std.ArrayList(u8).init(allocator) else - std.ArrayList(u8){}; + std.ArrayList(u8).initCapacity(allocator, 0) catch unreachable; defer if (builtin.zig_version.minor == 14) input.deinit() else input.deinit(allocator); // str32 claiming 1MB but only providing a few bytes @@ -134,7 +136,7 @@ test "PackerIO: truncated array cleanup" { var input = if (builtin.zig_version.minor == 14) std.ArrayList(u8).init(allocator) else - std.ArrayList(u8){}; + std.ArrayList(u8).initCapacity(allocator, 0) catch unreachable; defer if (builtin.zig_version.minor == 14) input.deinit() else input.deinit(allocator); // Create array header for 3 elements (0x93) @@ -1424,7 +1426,7 @@ test "large maps" { var keys = if (builtin.zig_version.minor == 14) std.ArrayList([]u8).init(allocator) else - std.ArrayList([]u8){}; + std.ArrayList([]u8).initCapacity(allocator, 0) catch unreachable; defer { for (keys.items) |key| { allocator.free(key); @@ -1852,7 +1854,7 @@ test "actual map32 format" { var keys = if (builtin.zig_version.minor == 14) std.ArrayList([]u8).init(allocator) else - std.ArrayList([]u8){}; + std.ArrayList([]u8).initCapacity(allocator, 0) catch unreachable; defer { for (keys.items) |key| { allocator.free(key); @@ -2058,7 +2060,7 @@ test "format markers verification" { var test_keys = if (builtin.zig_version.minor == 14) std.ArrayList([]u8).init(allocator) else - std.ArrayList([]u8){}; + std.ArrayList([]u8).initCapacity(allocator, 0) catch unreachable; defer { for (test_keys.items) |key| { allocator.free(key); @@ -3413,7 +3415,7 @@ test "fuzz: mixed payload sequence" { var payloads = if (builtin.zig_version.minor == 14) std.ArrayList(Payload).init(allocator) else - std.ArrayList(Payload){}; + std.ArrayList(Payload).initCapacity(allocator, 0) catch unreachable; defer { for (payloads.items) |payload| { payload.free(allocator); @@ -3453,7 +3455,7 @@ test "iterative parser: normal nested depth (100 layers)" { var input = if (builtin.zig_version.minor == 14) std.ArrayList(u8).init(allocator) else - std.ArrayList(u8){}; + std.ArrayList(u8).initCapacity(allocator, 0) catch unreachable; defer if (builtin.zig_version.minor == 14) input.deinit() else input.deinit(allocator); const depth = 100; @@ -3502,7 +3504,7 @@ test "iterative parser: max depth exceeded" { var input = if (builtin.zig_version.minor == 14) std.ArrayList(u8).init(allocator) else - std.ArrayList(u8){}; + std.ArrayList(u8).initCapacity(allocator, 0) catch unreachable; defer if (builtin.zig_version.minor == 14) input.deinit() else input.deinit(allocator); const depth = 100; @@ -3548,7 +3550,7 @@ test "iterative parser: array too large" { var input = if (builtin.zig_version.minor == 14) std.ArrayList(u8).init(allocator) else - std.ArrayList(u8){}; + std.ArrayList(u8).initCapacity(allocator, 0) catch unreachable; defer if (builtin.zig_version.minor == 14) input.deinit() else input.deinit(allocator); // array16 marker + length @@ -3580,7 +3582,7 @@ test "iterative parser: deep nested maps" { var input = if (builtin.zig_version.minor == 14) std.ArrayList(u8).init(allocator) else - std.ArrayList(u8){}; + std.ArrayList(u8).initCapacity(allocator, 0) catch unreachable; defer if (builtin.zig_version.minor == 14) input.deinit() else input.deinit(allocator); const depth = 50; @@ -3775,7 +3777,7 @@ test "fuzz: deep mixed nesting" { var input = if (builtin.zig_version.minor == 14) std.ArrayList(u8).init(allocator) else - std.ArrayList(u8){}; + std.ArrayList(u8).initCapacity(allocator, 0) catch unreachable; defer if (builtin.zig_version.minor == 14) input.deinit() else input.deinit(allocator); for (0..depth) |_| { @@ -3823,7 +3825,7 @@ test "malicious: array32 claims 4 billion elements" { var input = if (builtin.zig_version.minor == 14) std.ArrayList(u8).init(allocator) else - std.ArrayList(u8){}; + std.ArrayList(u8).initCapacity(allocator, 0) catch unreachable; defer if (builtin.zig_version.minor == 14) input.deinit() else input.deinit(allocator); // array32 claiming 0xFFFFFFFF (4 billion) elements @@ -3858,7 +3860,7 @@ test "malicious: map32 claims 4 billion pairs" { var input = if (builtin.zig_version.minor == 14) std.ArrayList(u8).init(allocator) else - std.ArrayList(u8){}; + std.ArrayList(u8).initCapacity(allocator, 0) catch unreachable; defer if (builtin.zig_version.minor == 14) input.deinit() else input.deinit(allocator); // map32 claiming 0xFFFFFFFF pairs @@ -3903,7 +3905,7 @@ test "malicious: extremely deep nesting (2000 layers)" { var input = if (builtin.zig_version.minor == 14) std.ArrayList(u8).init(allocator) else - std.ArrayList(u8){}; + std.ArrayList(u8).initCapacity(allocator, 0) catch unreachable; defer if (builtin.zig_version.minor == 14) input.deinit() else input.deinit(allocator); // 2000 layers of nesting (far exceeds limit of 100) @@ -3939,7 +3941,7 @@ test "corrupted: truncated array data" { var input = if (builtin.zig_version.minor == 14) std.ArrayList(u8).init(allocator) else - std.ArrayList(u8){}; + std.ArrayList(u8).initCapacity(allocator, 0) catch unreachable; defer if (builtin.zig_version.minor == 14) input.deinit() else input.deinit(allocator); // array claiming 10 elements but data is incomplete @@ -3971,7 +3973,7 @@ test "map with non-string key (integer key)" { var input = if (builtin.zig_version.minor == 14) std.ArrayList(u8).init(allocator) else - std.ArrayList(u8){}; + std.ArrayList(u8).initCapacity(allocator, 0) catch unreachable; defer if (builtin.zig_version.minor == 14) input.deinit() else input.deinit(allocator); // map with integer key (now valid - keys can be any Payload type) @@ -4023,7 +4025,7 @@ test "malicious: mixed depth and breadth attack" { var input = if (builtin.zig_version.minor == 14) std.ArrayList(u8).init(allocator) else - std.ArrayList(u8){}; + std.ArrayList(u8).initCapacity(allocator, 0) catch unreachable; defer if (builtin.zig_version.minor == 14) input.deinit() else input.deinit(allocator); // Build: [ [100 items], [100 items], ... ] nested 60 levels deep @@ -4059,7 +4061,7 @@ test "edge case: empty containers at various depths" { var input = if (builtin.zig_version.minor == 14) std.ArrayList(u8).init(allocator) else - std.ArrayList(u8){}; + std.ArrayList(u8).initCapacity(allocator, 0) catch unreachable; defer if (builtin.zig_version.minor == 14) input.deinit() else input.deinit(allocator); const depths = [_]usize{ 0, 1, 5, 10, 20 }; @@ -4133,7 +4135,7 @@ test "corrupted: nested arrays with mismatched counts" { var input = if (builtin.zig_version.minor == 14) std.ArrayList(u8).init(allocator) else - std.ArrayList(u8){}; + std.ArrayList(u8).initCapacity(allocator, 0) catch unreachable; defer if (builtin.zig_version.minor == 14) input.deinit() else input.deinit(allocator); // Outer array claims 3 elements, but we provide different structure @@ -5004,8 +5006,6 @@ test "memory alignment: large integer array serialization" { // std.io.Reader and std.io.Writer Tests (Zig 0.15+) // ============================================================================ -const has_new_io = builtin.zig_version.minor >= 15; - test "PackerIO: basic write and read with fixed Reader/Writer" { if (!has_new_io) return error.SkipZigTest; From b1ba240180d1942d6297b3d5f703f8b4ac4f5e65 Mon Sep 17 00:00:00 2001 From: jinzhongjia Date: Sun, 3 May 2026 21:48:48 +0800 Subject: [PATCH 2/3] =?UTF-8?q?chore(ci):=20=E7=BB=9F=E4=B8=80=E4=BD=BF?= =?UTF-8?q?=E7=94=A8=20mlugg/setup-zig@v2=20=E6=9B=BF=E4=BB=A3=E5=B7=B2?= =?UTF-8?q?=E5=BA=9F=E5=BC=83=20action?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - goto-bus-stop/setup-zig 仓库已归档,后续不再维护 - 替换为 mlugg/setup-zig 保证后续兼容和安全 - 避免旧 action 可能引起的集成失效或安全风险 --- .github/workflows/benchmark.yml | 2 +- .github/workflows/deploy_docs.yml | 2 +- .github/workflows/format-check.yml | 2 +- .github/workflows/test.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index f975140..e25af6d 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -26,7 +26,7 @@ jobs: uses: actions/checkout@v4 - name: Setup Zig - uses: goto-bus-stop/setup-zig@v2 + uses: mlugg/setup-zig@v2 with: version: 0.16.0 diff --git a/.github/workflows/deploy_docs.yml b/.github/workflows/deploy_docs.yml index 20c7dac..48c92d7 100644 --- a/.github/workflows/deploy_docs.yml +++ b/.github/workflows/deploy_docs.yml @@ -45,7 +45,7 @@ jobs: uses: actions/checkout@v3 with: fetch-depth: 0 # Not needed if lastUpdated is not enabled - - uses: goto-bus-stop/setup-zig@v2 + - uses: mlugg/setup-zig@v2 with: cache: false - name: Generate Docs diff --git a/.github/workflows/format-check.yml b/.github/workflows/format-check.yml index 480bb06..4797c44 100644 --- a/.github/workflows/format-check.yml +++ b/.github/workflows/format-check.yml @@ -17,7 +17,7 @@ jobs: uses: actions/checkout@v4 - name: Setup Zig - uses: goto-bus-stop/setup-zig@v2 + uses: mlugg/setup-zig@v2 with: version: 0.16.0 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 162b804..c12028d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -56,7 +56,7 @@ jobs: fetch-depth: 0 - name: Setup Zig - uses: goto-bus-stop/setup-zig@v2 + uses: mlugg/setup-zig@v2 with: version: ${{ matrix.version }} From 6f5e9e161e5e0e1f021ad7dadb1f2623e6381a87 Mon Sep 17 00:00:00 2001 From: jinzhongjia Date: Thu, 7 May 2026 00:43:54 +0800 Subject: [PATCH 3/3] docs: update Zig 0.16.0 as stable and fix benchmark timing --- AGENT.md | 3 +-- CLAUDE.md | 4 ++-- README.md | 4 ++-- README_CN.md | 4 ++-- src/bench.zig | 28 +++++++++++----------------- 5 files changed, 18 insertions(+), 25 deletions(-) diff --git a/AGENT.md b/AGENT.md index 2d58d04..4b35fe4 100644 --- a/AGENT.md +++ b/AGENT.md @@ -230,8 +230,7 @@ defer result.free(allocator); // 释放内存 ### 5.1 支持的 Zig 版本 -- ✅ **完全支持**:Zig 0.14.x, 0.15.x -- ⚠️ **部分支持**:Zig 0.16 (nightly) +- ✅ **完全支持**:Zig 0.14.x, 0.15.x, 0.16.0 ### 5.2 关键差异点 diff --git a/CLAUDE.md b/CLAUDE.md index c0b1379..2bf90f1 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -28,7 +28,7 @@ zig build docs - ArrayList API changes in Zig 0.15+ (allocator parameter required for methods) - ArrayList initialization changes in Zig 0.16 (`std.ArrayList(T){}` removed, use `initCapacity`) - Build system API differences between versions - - `std.time.Timer` removed in 0.16 (replaced with platform-specific timing in benchmarks) + - `std.time.Timer` removed in 0.16 (benchmarks use `std.Io.Clock.awake` instead) - `std.heap.GeneralPurposeAllocator` removed in 0.16 (replaced with `page_allocator`) - `std.io.fixedBufferStream` removed in 0.16 (compat layer provides `BufferStream`) @@ -82,4 +82,4 @@ Tests use Zig's built-in testing framework. The test suite in `src/test.zig` cov ## CI/CD -GitHub Actions workflow tests against multiple Zig versions (0.14.0, 0.15.1, nightly) to ensure compatibility. \ No newline at end of file +GitHub Actions workflow tests against multiple Zig versions (0.14.1, 0.15.1, 0.16.0, and master) to ensure compatibility. diff --git a/README.md b/README.md index 48df6f3..39eed3a 100644 --- a/README.md +++ b/README.md @@ -47,12 +47,12 @@ This library is tested and optimized for all major platforms and architectures: | 0.13 and older | 0.0.6 | Legacy support | | 0.14.0 | Current | ✅ Fully supported | | 0.15.x | Current | ✅ Fully supported | -| 0.16.0-dev (nightly) | Current | ✅ Supported with compatibility layer | +| 0.16.0 | Current | ✅ Supported with compatibility layer | > **Note:** For Zig 0.13 and older versions, please use version `0.0.6` of this library. > **Note:** Zig 0.16+ removes `std.io.FixedBufferStream`, but this library provides a compatibility layer to maintain the same API across all supported versions. -For Zig `0.14.0`, `0.15.x`, and `0.16.0-dev`, follow these steps: +For Zig `0.14.0`, `0.15.x`, and `0.16.0`, follow these steps: 1. **Add as a dependency:** Add the library to your `build.zig.zon` file. You can fetch a specific commit or branch. diff --git a/README_CN.md b/README_CN.md index 090ac58..4472507 100644 --- a/README_CN.md +++ b/README_CN.md @@ -47,12 +47,12 @@ Zig 编程语言的 MessagePack 实现。此库提供了一种简单高效的方 | 0.13 及更早版本 | 0.0.6 | 旧版支持 | | 0.14.0 | 当前版本 | ✅ 完全支持 | | 0.15.x | 当前版本 | ✅ 完全支持 | -| 0.16.0-dev (nightly) | 当前版本 | ✅ 通过兼容层支持 | +| 0.16.0 | 当前版本 | ✅ 通过兼容层支持 | > **注意**: 对于 Zig 0.13 及更早版本,请使用本库的 `0.0.6` 版本。 > **注意**: Zig 0.16+ 移除了 `std.io.FixedBufferStream`,但本库提供了兼容层以在所有支持的版本中维持相同的 API。 -对于 Zig `0.14.0`、`0.15.x` 和 `0.16.0-dev` 版本,请按以下步骤操作: +对于 Zig `0.14.0`、`0.15.x` 和 `0.16.0` 版本,请按以下步骤操作: 1. **添加为依赖项**: 将库添加到您的 `build.zig.zon` 文件中。您可以获取特定的提交或分支。 diff --git a/src/bench.zig b/src/bench.zig index 84c9e01..59996f9 100644 --- a/src/bench.zig +++ b/src/bench.zig @@ -17,24 +17,18 @@ const pack = msgpack.Pack( ); const is_zig_16 = builtin.zig_version.minor >= 16; +const BenchRuntime = if (is_zig_16) struct { + var io: ?std.Io = null; +} else struct {}; -/// Get monotonic time in nanoseconds (cross-platform) +/// Get monotonic time in nanoseconds on Zig 0.16+. fn getTimeNs() u64 { - if (builtin.os.tag == .windows) { - const w = std.os.windows; - var counter: w.LARGE_INTEGER = undefined; - _ = w.ntdll.RtlQueryPerformanceCounter(&counter); - var freq: w.LARGE_INTEGER = undefined; - _ = w.ntdll.RtlQueryPerformanceFrequency(&freq); - const ns = std.time.ns_per_s; - const c: u64 = @bitCast(counter); - const f: u64 = @bitCast(freq); - return @intCast(@divTrunc(@as(u128, c) * ns, @as(u128, f))); - } else if (builtin.os.tag != .windows) { - var ts: std.c.timespec = undefined; - _ = std.c.clock_gettime(std.c.CLOCK.MONOTONIC, &ts); - return @as(u64, @intCast(ts.tv_sec)) * std.time.ns_per_s + @as(u64, @intCast(ts.tv_nsec)); - } else @compileError("unsupported OS for benchmark"); + if (is_zig_16) { + const io = BenchRuntime.io orelse @panic("benchmark runtime io is not initialized"); + return @intCast(std.Io.Clock.awake.now(io).nanoseconds); + } + + unreachable; } /// Benchmark timer helper @@ -962,7 +956,7 @@ fn runBenchmarks() !void { const BenchEntry = if (is_zig_16) struct { pub fn main(init: std.process.Init) !void { - _ = &init; + BenchRuntime.io = init.io; try runBenchmarks(); } } else struct {