Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade to Version 0.12 #37

Merged
merged 12 commits into from
Apr 22, 2024
4 changes: 2 additions & 2 deletions .github/workflows/zig.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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
Expand Down
125 changes: 66 additions & 59 deletions README.md
Original file line number Diff line number Diff line change
@@ -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)
Expand All @@ -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/<COMMIT>.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/<COMMIT>.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/<COMMIT>.tar.gz",
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
note: expected .hash = "<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/<COMMIT>.tar.gz",
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
note: expected .hash = "<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/<COMMIT>.tar.gz",
+ .hash = "<HASH>",
},
},
}
```
```diff
.{
.name = "my-project",
.version = "1.0.0",
.paths = .{""},
.dependencies = .{
.zbench = .{
.url = "https://github.com/hendriknielaender/zbench/archive/<COMMIT>.tar.gz",
+ .hash = "<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
Expand All @@ -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 {
Expand Down Expand Up @@ -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

Expand All @@ -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

Expand Down
18 changes: 7 additions & 11 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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" },
Expand All @@ -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" },
Expand All @@ -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",
Expand All @@ -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,
Expand Down
4 changes: 2 additions & 2 deletions docs/advanced.md
Original file line number Diff line number Diff line change
@@ -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:

Expand Down
1 change: 0 additions & 1 deletion docs/intro.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

2 changes: 0 additions & 2 deletions docs/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,3 @@ test "bench test" {
try zbench.run(myBenchmark, &bench, &benchmarkResults);
}
```


2 changes: 1 addition & 1 deletion util/os/osx.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
2 changes: 1 addition & 1 deletion util/os/windows.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
Loading