Thanks for using Compiler Explorer
Sponsors
Jakt
C++
Ada
Analysis
Android Java
Android Kotlin
Assembly
C
C3
Carbon
C++ (Circle)
CIRCT
Clean
CMake
CMakeScript
COBOL
C++ for OpenCL
MLIR
Cppx
Cppx-Blue
Cppx-Gold
Cpp2-cppfront
Crystal
C#
CUDA C++
D
Dart
Elixir
Erlang
Fortran
F#
GLSL
Go
Haskell
HLSL
Hook
Hylo
IL
ispc
Java
Julia
Kotlin
LLVM IR
LLVM MIR
Modula-2
Nim
Objective-C
Objective-C++
OCaml
OpenCL C
Pascal
Pony
Python
Racket
Ruby
Rust
Snowball
Scala
Solidity
Spice
SPIR-V
Swift
LLVM TableGen
Toit
TypeScript Native
V
Vala
Visual Basic
WASM
Zig
Javascript
GIMPLE
Ygen
zig source #1
Output
Compile to binary object
Link to binary
Execute the code
Intel asm syntax
Demangle identifiers
Verbose demangling
Filters
Unused labels
Library functions
Directives
Comments
Horizontal whitespace
Debug intrinsics
Compiler
zig 0.10.0
zig 0.11.0
zig 0.12.0
zig 0.12.1
zig 0.13.0
zig 0.2.0
zig 0.3.0
zig 0.4.0
zig 0.5.0
zig 0.6.0
zig 0.7.0
zig 0.7.1
zig 0.8.0
zig 0.9.0
zig trunk
Options
Source code
const std = @import("std"); const debug = std.debug; const mem = std.mem; const rand = std.rand; const sort = std.sort; const builtin = @import("builtin"); const io = std.io; const math = std.math; const meta = std.meta; const os = std.os; const time = os.time; const Def = builtin.TypeInfo.Definition; pub fn benchmark(comptime B: type) !void { const args = if (getDef(B, "args")) |_| B.args else []void{{}}; const iterations: u32 = if (getDef(B, "iterations")) |_| B.iterations else 100000; comptime var max_fn_name_len = 0; const functions = comptime blk: { var res: []const Def = []Def{}; for (meta.definitions(B)) |def| { if (def.data != builtin.TypeInfo.Definition.Data.Fn) continue; if (max_fn_name_len < def.name.len) max_fn_name_len = def.name.len; res = res ++ []Def{def}; } break :blk res; }; if (functions.len == 0) @compileError("No benchmarks to run."); const max_name_spaces = comptime math.max(max_fn_name_len + digits(u64, 10, args.len) + 1, "Benchmark".len); var timer = try time.Timer.start(); debug.warn("\n"); debug.warn("Benchmark"); nTimes(' ', (max_name_spaces - "Benchmark".len) + 1); nTimes(' ', digits(u64, 10, math.maxInt(u64)) - "Mean(ns)".len); debug.warn("Mean(ns)\n"); nTimes('-', max_name_spaces + digits(u64, 10, math.maxInt(u64)) + 1); debug.warn("\n"); inline for (functions) |def| { for (args) |arg, index| { var runtime_sum: u128 = 0; var i: usize = 0; while (i < iterations) : (i += 1) { timer.reset(); const res = switch (@typeOf(arg)) { void => @noInlineCall(@field(B, def.name)), else => @noInlineCall(@field(B, def.name), arg), }; const runtime = timer.read(); runtime_sum += runtime; doNotOptimize(res); } const runtime_mean = @intCast(u64, runtime_sum / iterations); debug.warn("{}.{}", def.name, index); nTimes(' ', (max_name_spaces - (def.name.len + digits(u64, 10, index) + 1)) + 1); nTimes(' ', digits(u64, 10, math.maxInt(u64)) - digits(u64, 10, runtime_mean)); debug.warn("{}\n", runtime_mean); } } } /// Pretend to use the value so the optimizer cant optimize it out. fn doNotOptimize(val: var) void { const T = @typeOf(val); var store: T = undefined; @ptrCast(*volatile T, &store).* = val; } fn digits(comptime N: type, comptime base: comptime_int, n: N) usize { comptime var res = 1; comptime var check = base; inline while (check <= math.maxInt(N)) : ({ check *= base; res += 1; }) { if (n < check) return res; } return res; } fn nTimes(c: u8, times: usize) void { var i: usize = 0; while (i < times) : (i += 1) debug.warn("{c}", c); } fn getDef(comptime T: type, name: []const u8) ?builtin.TypeInfo.Definition { for (@typeInfo(T).Struct.defs) |def| { if (mem.eql(u8, def.name, name)) return def; } return null; } pub fn StringSwitch(comptime strings: []const []const u8) type { for (strings[1..]) |_, i| { if (mem.lessThan(u8, strings[i], strings[i + 1])) continue; @compileError("Input not sorted (assert(\"" ++ strings[i] ++ "\" < \"" ++ strings[i + 1] ++ "\"))"); } return struct { pub fn match(str: []const u8) usize { var curr: usize = 0; next: for (strings) |s, i| { while (curr < s.len) : (curr += 1) { const a = str[curr]; const b = s[curr]; if (a != b) continue :next; } if (s.len == str.len) return i; } return strings.len; } pub fn case(comptime str: []const u8) usize { const i = match(str); debug.assert(i < strings.len); return i; } }; } test "match.StringSwitch" { @setEvalBranchQuota(1000000); const strings = [][]const u8{ "A", "AA", "AAA", "AAAA", "AAAAA", "AAAAAA", "AAAAAAA", "AAAAAAAA", }; const sw = comptime StringSwitch(strings); inline for (strings) |str| switch (sw.match(str)) { sw.case(str) => {}, else => unreachable, }; } export fn q() void { _ = benchmark(struct { const args = [][]const u8{ "A" ** 1, "A" ** 2, "A" ** 4, "A" ** 8, "A" ** 16, "A" ** 32, "A" ** 64, "A" ** 128, "A" ** 256, "A" ** 512, "A" ** 1024, "abcd" ** 8, "abcd" ** 16, "abcd" ** 32, "abcd" ** 64, "abcd" ** 128, "abcd" ** 256, "abcd" ** 512, "abcd" ** 1024, }; fn switch_StringSwitch(str: []const u8) usize { @setEvalBranchQuota(100000); const sw = StringSwitch(args); switch (sw.match(str)) { sw.case("A" ** 1) => return 21, sw.case("A" ** 2) => return 15, sw.case("A" ** 4) => return 31, sw.case("A" ** 8) => return 111, sw.case("A" ** 16) => return 400, sw.case("A" ** 32) => return 2, sw.case("A" ** 64) => return 100000, sw.case("A" ** 128) => return 12345, sw.case("A" ** 256) => return 1, sw.case("A" ** 512) => return 35, sw.case("A" ** 1024) => return 99999999, sw.case("abcd" ** 8) => return 4, sw.case("abcd" ** 16) => return 1512, sw.case("abcd" ** 32) => return 152222, sw.case("abcd" ** 64) => return 42566, sw.case("abcd" ** 128) => return 66477, sw.case("abcd" ** 256) => return 345377, sw.case("abcd" ** 512) => return 745745, sw.case("abcd" ** 1024) => return 3444, else => return 2241255, } } fn switch_hash_mem_eql(str: []const u8) usize { @setEvalBranchQuota(100000); const hash = mem.hash_slice_u8; const eql = mem.eql_slice_u8; switch (hash(str)) { hash("A" ** 1) => { if (!eql("A", str)) return 2241255; return 21; }, hash("A" ** 2) => { if (!eql("A", str)) return 2241255; return 15; }, hash("A" ** 4) => { if (!eql("A", str)) return 2241255; return 31; }, hash("A" ** 8) => { if (!eql("A", str)) return 2241255; return 111; }, hash("A" ** 16) => { if (!eql("A", str)) return 2241255; return 400; }, hash("A" ** 32) => { if (!eql("A", str)) return 2241255; return 2; }, hash("A" ** 64) => { if (!eql("A", str)) return 2241255; return 100000; }, hash("A" ** 128) => { if (!eql("A", str)) return 2241255; return 12345; }, hash("A" ** 256) => { if (!eql("A", str)) return 2241255; return 1; }, hash("A" ** 512) => { if (!eql("A", str)) return 2241255; return 35; }, hash("A" ** 1024) => { if (!eql("A", str)) return 2241255; return 99999999; }, hash("abcd" ** 8) => { if (!eql("abcd", str)) return 2241255; return 4; }, hash("abcd" ** 16) => { if (!eql("abcd", str)) return 2241255; return 1512; }, hash("abcd" ** 32) => { if (!eql("abcd", str)) return 2241255; return 152222; }, hash("abcd" ** 64) => { if (!eql("abcd", str)) return 2241255; return 42566; }, hash("abcd" ** 128) => { if (!eql("abcd", str)) return 2241255; return 66477; }, hash("abcd" ** 256) => { if (!eql("abcd", str)) return 2241255; return 345377; }, hash("abcd" ** 512) => { if (!eql("abcd", str)) return 2241255; return 745745; }, hash("abcd" ** 1024) => { if (!eql("abcd", str)) return 2241255; return 3444; }, else => return 2241255, } } fn switch_mem_eql(str: []const u8) usize { if (mem.eql(u8, "A" ** 1, str)) { return 21; } else if (mem.eql(u8, "A" ** 2, str)) { return 15; } else if (mem.eql(u8, "A" ** 4, str)) { return 31; } else if (mem.eql(u8, "A" ** 8, str)) { return 111; } else if (mem.eql(u8, "A" ** 16, str)) { return 400; } else if (mem.eql(u8, "A" ** 32, str)) { return 2; } else if (mem.eql(u8, "A" ** 64, str)) { return 100000; } else if (mem.eql(u8, "A" ** 128, str)) { return 12345; } else if (mem.eql(u8, "A" ** 256, str)) { return 1; } else if (mem.eql(u8, "A" ** 512, str)) { return 35; } else if (mem.eql(u8, "A" ** 1024, str)) { return 99999999; } else if (mem.eql(u8, "abcd" ** 8, str)) { return 4; } else if (mem.eql(u8, "abcd" ** 16, str)) { return 1512; } else if (mem.eql(u8, "abcd" ** 32, str)) { return 152222; } else if (mem.eql(u8, "abcd" ** 64, str)) { return 42566; } else if (mem.eql(u8, "abcd" ** 128, str)) { return 66477; } else if (mem.eql(u8, "abcd" ** 256, str)) { return 345377; } else if (mem.eql(u8, "abcd" ** 512, str)) { return 745745; } else if (mem.eql(u8, "abcd" ** 1024, str)) { return 3444; } else { return 2241255; } } }); }
Become a Patron
Sponsor on GitHub
Donate via PayPal
Source on GitHub
Mailing list
Installed libraries
Wiki
Report an issue
How it works
Contact the author
CE on Mastodon
About the author
Statistics
Changelog
Version tree