Created
October 8, 2023 10:03
-
-
Save 18alantom/fac21902a1e7b295cac16f3772f42df3 to your computer and use it in GitHub Desktop.
Experiments
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// Run using | |
/// ```bash | |
/// zig run -O ReleaseFast fast_zeros.zig > /dev/null | |
/// ``` | |
/// This program writes 0s to std out using a buffer. | |
/// Time taken, buffer size and number of loops are | |
/// written to stderr. | |
/// | |
/// Purpose of this is to roughly check what size of | |
/// buffer allows for max throughput by measuring the | |
/// time taken to write zeros to stdout. | |
/// | |
/// `c.printf` is used cause it's much faster than zig's | |
/// `os.write` to fd 1. Why? I'm not really sure, but I think | |
/// it's cause of error handling condional checking between | |
/// the two functions. Will have to dive deeper. | |
/// | |
/// Insights from running the program: | |
/// - Power of 2 buffers take lesser time to fill (than pow 10). | |
/// - Until 1KB buffer big decrements in total time. | |
/// - After 1KB total roughly constant. | |
/// - Fastest run is with 4MB buffer (2**22). | |
/// - Commenting out the `std.c.printf` line shows that: | |
/// - `@memset` is constant until 512B (21ns). | |
/// - Doubles after that (linearly scales with input). | |
const temp = @import("./lib.zig").temp; | |
const std = @import("std"); | |
const print = std.debug.print; | |
const os = std.os; | |
const pow = std.math.pow; | |
pub fn main() !void { | |
// Powers of 10 | |
var ns1: [4]u32 = undefined; | |
for (0..ns1.len) |i| { | |
const exp: u32 = @intCast(i); | |
ns1[i] = pow(u32, 10, exp + 1); | |
} | |
// Powers of 2 | |
var ns2: [24]u32 = undefined; | |
for (0..ns2.len) |i| { | |
const exp: u32 = @intCast(i + 2); | |
ns2[i] = pow(u32, 2, exp); | |
} | |
var gpa = std.heap.GeneralPurposeAllocator(.{}){}; | |
const allocator = gpa.allocator(); | |
try outer_loop(&ns1, 10_000_000, &allocator); | |
try outer_loop(&ns2, pow(u32, 2, 30), &allocator); | |
} | |
pub fn outer_loop(buff_sizes: []const u32, size: u32, allocator: *const std.mem.Allocator) !void { | |
print("Looping: {d}\n{any}\n\n", .{ size, buff_sizes }); | |
for (buff_sizes) |buff_size| { | |
const buff = try allocator.allocSentinel(u8, buff_size, 0); | |
defer allocator.free(buff); | |
try loop(buff, size); | |
} | |
print("\n\n", .{}); | |
} | |
pub fn loop(buff: [:0]u8, size: u32) !void { | |
var timer = try std.time.Timer.start(); | |
var acc: u128 = 0; | |
const loops = size / buff.len; | |
for (0..loops) |_| { | |
@memset(buff, '0'); | |
_ = std.c.printf(buff); | |
acc += timer.lap(); | |
} | |
print( | |
\\{d} buff.len, {d} loops: | |
\\ avg: {d:10} | |
\\ total: {d:10} | |
\\ | |
\\ | |
, .{ buff.len, loops, acc / loops, acc }); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment