diff --git a/.github/workflows/zig.yml b/.github/workflows/zig.yml index 2ebee28..89b73e9 100644 --- a/.github/workflows/zig.yml +++ b/.github/workflows/zig.yml @@ -18,7 +18,7 @@ jobs: - uses: actions/checkout@v2 - uses: goto-bus-stop/setup-zig@v2 with: - version: 0.11.0 + version: 0.12.0 - run: zig build test build-examples: strategy: @@ -29,7 +29,7 @@ jobs: - uses: actions/checkout@v2 - uses: goto-bus-stop/setup-zig@v2 with: - version: 0.11.0 + version: 0.12.0 - run: zig build test_examples lint: runs-on: ubuntu-latest diff --git a/README.md b/README.md index f81aa83..331d022 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ # ⚡ zBench - A Simple Zig Benchmarking Library + [![MIT license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/hendriknielaender/zbench/blob/HEAD/LICENSE) ![GitHub code size in bytes](https://img.shields.io/github/languages/code-size/hendriknielaender/zbench) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/hendriknielaender/zbench/blob/HEAD/CONTRIBUTING.md) @@ -8,81 +9,85 @@ zBench is a simple benchmarking library for the Zig programming language. It is ## Install Option 1 (build.zig.zon) -1. Declare zbench as a dependency in `build.zig.zon`: - - ```diff - .{ - .name = "my-project", - .version = "1.0.0", - .paths = .{""}, - .dependencies = .{ - + .zbench = .{ - + .url = "https://github.com/hendriknielaender/zbench/archive/.tar.gz", - + }, - }, - } - ``` +1. Declare zBench as a dependency in `build.zig.zon`: + + ```diff + .{ + .name = "my-project", + .version = "1.0.0", + .paths = .{""}, + .dependencies = .{ + + .zbench = .{ + + .url = "https://github.com/hendriknielaender/zbench/archive/.tar.gz", + + }, + }, + } + ``` 2. Add the module in `build.zig`: - ```diff - const std = @import("std"); + ```diff + const std = @import("std"); - pub fn build(b: *std.Build) void { - const target = b.standardTargetOptions(.{}); - const optimize = b.standardOptimizeOption(.{}); + pub fn build(b: *std.Build) void { + const target = b.standardTargetOptions(.{}); + const optimize = b.standardOptimizeOption(.{}); - + const opts = .{ .target = target, .optimize = optimize }; - + const zbench_module = b.dependency("zbench", opts).module("zbench"); + + const opts = .{ .target = target, .optimize = optimize }; + + const zbench_module = b.dependency("zbench", opts).module("zbench"); - const exe = b.addExecutable(.{ - .name = "test", - .root_source_file = .{ .path = "src/main.zig" }, - .target = target, - .optimize = optimize, - }); - + exe.addModule("zbench", zbench_module); - exe.install(); + const exe = b.addExecutable(.{ + .name = "test", + .root_source_file = .{ .path = "src/main.zig" }, + .target = target, + .optimize = optimize, + }); + + exe.addModule("zbench", zbench_module); + exe.install(); - ... - } - ``` + ... + } + ``` 3. Get the package hash: - ``` - $ zig build - my-project/build.zig.zon:6:20: error: url field is missing corresponding hash field - .url = "https://github.com/hendriknielaender/zbench/archive/.tar.gz", - ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - note: expected .hash = "", - ``` + ```shell + $ zig build + my-project/build.zig.zon:6:20: error: url field is missing corresponding hash field + .url = "https://github.com/hendriknielaender/zbench/archive/.tar.gz", + ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + note: expected .hash = "", + ``` 4. Update `build.zig.zon` package hash value: - ```diff - .{ - .name = "my-project", - .version = "1.0.0", - .paths = .{""}, - .dependencies = .{ - .zbench = .{ - .url = "https://github.com/hendriknielaender/zbench/archive/.tar.gz", - + .hash = "", - }, - }, - } - ``` + ```diff + .{ + .name = "my-project", + .version = "1.0.0", + .paths = .{""}, + .dependencies = .{ + .zbench = .{ + .url = "https://github.com/hendriknielaender/zbench/archive/.tar.gz", + + .hash = "", + }, + }, + } + ``` ## Install Option 2 (git submodule) + On your project root directory make a directory name libs. + - Run `git submodule add https://github.com/hendriknielaender/zBench libs/zbench` - Then add the module into your `build.zig` + ```zig exe.addAnonymousModule("zbench", .{ .source_file = .{ .path = "libs/zbench/zbench.zig" }, }); ``` + Now you can import like this: ```zig @@ -91,7 +96,7 @@ const zbench = @import("zbench"); ## Usage -Create a new benchmark function in your Zig code. This function should take a single argument of type std.mem.Allocator. The function would run the code you wish to benchmark. +Create a new benchmark function in your Zig code. This function should take a single argument of type `std.mem.Allocator`. The function would run the code you wish to benchmark. ```zig fn benchmarkMyFunction(allocator: std.mem.Allocator) void { @@ -132,7 +137,7 @@ pub const Config = struct { Zig is in active development and the APIs can change frequently, making it challenging to support every dev build. This project currently aims to be compatible with stable, non-development builds to provide a consistent experience for the users. -***Supported Version***: As of now, zBench is tested and supported on Zig version ***0.11.0***. +**_Supported Version_**: As of now, zBench is tested and supported on Zig version **_0.12.0_**. ### Benchmark Functions @@ -148,29 +153,31 @@ The function body contains the code you wish to benchmark. zBench provides a comprehensive report for each benchmark run. It includes the total operations performed, the average, min, and max durations of operations, and the percentile distribution (p75, p99, p995) of operation durations. -``` +```shell benchmark runs time (avg ± σ) (min ... max) p75 p99 p995 --------------------------------------------------------------------------------------------------------------- benchmarkMyFunction 1000 1200ms ± 10ms (100ms ... 2000ms) 1100ms 1900ms 1950ms ``` -This example report indicates that the benchmark "benchmarkMyFunction" was run with an average of 1200 ms per operation with a 10ms standard deviation. -The minimum and maximum operation times were 100 ms and 2000 ms, respectively. The 75th, 99th, and 99.5th percentiles of operation durations were 1100 ms, 1900 ms, and 1950 ms, respectively. +This example report indicates that the benchmark "benchmarkMyFunction" ran with an average of 1200 ms per execution and a standard deviation of 10 ms. +The minimum and maximum execution times were 100 ms and 2000 ms, respectively. The 75th, 99th and 99.5th percentiles of execution times were 1100 ms, 1900 ms, and 1950 ms, respectively. ### Running zBench Examples You can run all example tests with the following command: -```bash + +```shell zig build test_examples ``` ### Troubleshooting + - If Zig doesn't detect changes in a dependency, clear the project's `zig-cache` folder and `~/.cache/zig`. - [Non-ASCII characters not printed correctly on Windows](docs/advanced.md) ## Contributing -The main purpose of this repository is to continue to evolve zBench, making it faster and more efficient. We are grateful to the community for contributing bugfixes and improvements. Read below to learn how you can take part in improving zBench. +The main purpose of this repository is to continue to evolve zBench, making it faster and more efficient. We are grateful to the community for contributing bugfixes and improvements. Read below to learn how you help improve zBench. ### Contributing Guide diff --git a/build.zig b/build.zig index d94d1f4..2b43d4d 100644 --- a/build.zig +++ b/build.zig @@ -20,7 +20,7 @@ pub fn build(b: *std.Build) void { setupDocumentation(b, lib); } -fn setupLibrary(b: *std.Build, target: std.zig.CrossTarget, optimize: std.builtin.OptimizeMode) *std.Build.LibExeObjStep { +fn setupLibrary(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode) *std.Build.Step.Compile { const lib = b.addStaticLibrary(.{ .name = "zbench", .root_source_file = .{ .path = "zbench.zig" }, @@ -34,7 +34,7 @@ fn setupLibrary(b: *std.Build, target: std.zig.CrossTarget, optimize: std.builti return lib; } -fn setupTesting(b: *std.Build, target: std.zig.CrossTarget, optimize: std.builtin.OptimizeMode) void { +fn setupTesting(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode) void { const test_files = [_]struct { name: []const u8, path: []const u8 }{ .{ .name = "optional", .path = "util/optional.zig" }, .{ .name = "platform", .path = "util/platform.zig" }, @@ -56,7 +56,7 @@ fn setupTesting(b: *std.Build, target: std.zig.CrossTarget, optimize: std.builti } } -fn setupExamples(b: *std.Build, target: std.zig.CrossTarget, optimize: std.builtin.OptimizeMode) void { +fn setupExamples(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode) void { const example_step = b.step("test_examples", "Build examples"); const example_names = [_][]const u8{ "basic", @@ -73,25 +73,21 @@ fn setupExamples(b: *std.Build, target: std.zig.CrossTarget, optimize: std.built for (example_names) |example_name| { const example = b.addTest(.{ .name = example_name, - .root_source_file = .{ - .path = b.fmt("examples/{s}.zig", .{example_name}), - }, + .root_source_file = .{ .path = b.fmt("examples/{s}.zig", .{example_name}) }, .target = target, .optimize = optimize, }); const install_example = b.addInstallArtifact(example, .{}); const zbench_mod = b.addModule("zbench", .{ - .source_file = .{ - .path = "zbench.zig", - }, + .root_source_file = .{ .path = "zbench.zig" }, }); - example.addModule("zbench", zbench_mod); + example.root_module.addImport("zbench", zbench_mod); example_step.dependOn(&example.step); example_step.dependOn(&install_example.step); } } -fn setupDocumentation(b: *std.Build, lib: *std.Build.LibExeObjStep) void { +fn setupDocumentation(b: *std.Build, lib: *std.Build.Step.Compile) void { const install_docs = b.addInstallDirectory(.{ .source_dir = lib.getEmittedDocs(), .install_dir = .prefix, diff --git a/docs/advanced.md b/docs/advanced.md index babe370..0e669f5 100644 --- a/docs/advanced.md +++ b/docs/advanced.md @@ -1,6 +1,6 @@ -## Advanced +# Advanced -### Note for Windows Users +## Note for Windows Users If you encounter issues with character encoding, such as misrepresentation of "plusminus" (±) or "sigma" (σ) symbols in the benchmark results, it's likely due to Windows using UTF-16 LE encoding by default. To ensure characters are displayed correctly, you can switch your system to use UTF-8 encoding by following these steps: diff --git a/docs/intro.md b/docs/intro.md index 1388b16..3d4667d 100644 --- a/docs/intro.md +++ b/docs/intro.md @@ -11,4 +11,3 @@ Welcome to zBench, a streamlined benchmarking library for the Zig programming la ## Why zBench? zBench is built with the philosophy of simplicity and effectiveness. Whether you're a beginner in Zig or an experienced developer, zBench offers the tools to perform reliable and insightful performance evaluations of your code. - diff --git a/docs/quickstart.md b/docs/quickstart.md index 0b1fd28..dfa36f5 100644 --- a/docs/quickstart.md +++ b/docs/quickstart.md @@ -35,5 +35,3 @@ test "bench test" { try zbench.run(myBenchmark, &bench, &benchmarkResults); } ``` - - diff --git a/util/os/osx.zig b/util/os/osx.zig index 7eea2e2..978a67b 100644 --- a/util/os/osx.zig +++ b/util/os/osx.zig @@ -22,7 +22,7 @@ pub fn getTotalMemory(allocator: std.mem.Allocator) !u64 { } fn exec(allocator: std.mem.Allocator, args: []const []const u8) ![]const u8 { - const stdout = (try std.process.Child.exec(.{ .allocator = allocator, .argv = args })).stdout; + const stdout = (try std.process.Child.run(.{ .allocator = allocator, .argv = args })).stdout; if (stdout.len == 0) return error.EmptyOutput; diff --git a/util/os/windows.zig b/util/os/windows.zig index b339580..ea1b90c 100644 --- a/util/os/windows.zig +++ b/util/os/windows.zig @@ -52,7 +52,7 @@ pub fn getTotalMemory(allocator: std.mem.Allocator) !u64 { } fn exec(allocator: std.mem.Allocator, args: []const []const u8) ![]const u8 { - const stdout = (try std.ChildProcess.exec(.{ .allocator = allocator, .argv = args })).stdout; + const stdout = (try std.ChildProcess.run(.{ .allocator = allocator, .argv = args })).stdout; if (stdout.len == 0) return error.EmptyOutput;