Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- const std = @import("std");
- const builtin = @import("builtin");
- pub fn main() !void {
- if (std.os.argv.len < 2)
- return error.NeedsIterationArgument;
- const FIB = 35;
- const RESOLUTION = Timer.Resolution.Millisecond;
- const ITERATIONS = try std.fmt.parseInt(usize, std.mem.toSlice(u8, std.os.argv[1]), 10);
- Timer.Time("fib-zig", ITERATIONS, RESOLUTION, struct { fn run() usize {
- return fib_zig(FIB);
- }});
- Timer.Time("fib-asm", ITERATIONS, RESOLUTION, struct { fn run() usize {
- return fib_asm(FIB);
- }});
- }
- // LLVM version
- pub export fn fib_zig(n: usize) usize {
- if (n <= 1) return 1;
- return fib_zig(n - 1) + fib_zig(n - 2);
- }
- // Custom SystemV version
- extern fn fib_asm(n: usize) usize;
- comptime { asm (
- \\ .intel_syntax noprefix
- \\ .global fib_asm
- \\ .type fib_asm, @function
- \\
- \\ fib_asm:
- \\ mov rax, 1
- \\ cmp rdi, rax
- \\ jle done
- \\ dec rdi
- \\ push rdi
- \\ call fib_asm
- \\ pop rdi
- \\ push rax
- \\ dec rdi
- \\ call fib_asm
- \\ pop rcx
- \\ add rax, rcx
- \\ done:
- \\ ret
- );}
- pub const Timer = struct {
- pub const Resolution = enum {
- Second,
- Millisecond,
- Microsecond,
- Nanosecond,
- pub fn toUnit(self: Resolution) []const u8 {
- return switch (self) {
- .Second => "s",
- .Millisecond => "ms",
- .Microsecond => "μs",
- .Nanosecond => "ns",
- };
- }
- pub fn toSecondMultiple(self: Resolution) u64 {
- return switch (self) {
- .Second => u64(1),
- .Millisecond => u64(1000),
- .Microsecond => u64(1000 * 1000),
- .Nanosecond => u64(1000 * 1000 * 1000),
- };
- }
- };
- pub fn Time(
- comptime name: []const u8,
- iterations: usize,
- resolution: Resolution,
- comptime action: type,
- ) void {
- var it = u64(0);
- var average: u64 = 0;
- while (it < iterations) : (it += 1) {
- const start = Timer.Get(resolution);
- const result = action.run();
- const end = Timer.Get(resolution);
- average = ((average * it) + (end - start)) / (it + 1);
- _ = Timer.BlackBox(result);
- }
- const unit = resolution.toUnit();
- std.debug.warn("{} takes {}{} on average(runs: {})\n", name, average, unit, iterations);
- }
- pub usingnamespace switch (builtin.os) {
- .windows => struct {
- var freq: u64 = 0;
- extern "kernel32" stdcallcc fn QueryPerformanceCounter(x: *u64) usize;
- extern "kernel32" stdcallcc fn QueryPerformanceFrequency(x: *u64) usize;
- pub fn BlackBox(result: u64) usize {
- return QueryPerformanceCounter(@intToPtr(*u64, @intCast(usize, result)));
- }
- pub fn Get(resolution: Resolution) u64 {
- var time: u64 = undefined;
- if (freq == 0)
- _ = QueryPerformanceFrequency(&freq);
- _ = QueryPerformanceCounter(&time);
- return time / (freq / resolution.toSecondMultiple());
- }
- },
- .linux => struct {
- const linux = std.os.linux;
- pub fn BlackBox(result: u64) usize {
- return linux.syscall2(linux.SYS_clock_gettime, linux.CLOCK_REALTIME, @intCast(usize, result));
- }
- pub fn Get(resolution: Resolution) u64 {
- var tp: linux.timespec = undefined;
- const ns = Resolution.Nanosecond.toSecondMultiple();
- _ = linux.syscall2(linux.SYS_clock_gettime, linux.CLOCK_REALTIME, @ptrToInt(&tp));
- const time = @intCast(u64, tp.tv_sec) * ns + @intCast(u64, tp.tv_nsec);
- return time / (ns / resolution.toSecondMultiple());
- }
- },
- else => @compileError("OS not supported"),
- };
- };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement