Skip to content

std.io.AnyWriter has very high overhead #21566

@silversquirl

Description

@silversquirl

std.io.AnyWriter (and hence std.io.GenericWriter, since that uses AnyWriter internally) has a large amount of overhead in tight loops, as it hampers inlining.

The following code snippet demonstrates an extreme case of the issue, but it comes up a lot in practice too:

pub fn main() !void {
    const devnull = try std.fs.openFileAbsolute("/dev/null", .{ .mode = .write_only });
    var timer = try std.time.Timer.start();
    {
        // Write 1MiB to /dev/null, one byte at a time, using std.io.BufferedWriter
        var bufw = std.io.bufferedWriter(devnull.writer());
        const w = bufw.writer();
        for (0..1 << 20) |i| {
            try w.writeByte(@truncate(i));
        }
        try bufw.flush();

        std.debug.print("BufferedWriter: {}\n", .{std.fmt.fmtDuration(timer.read())});
    }

    {
        timer.reset();
        // Write 1MiB to /dev/null, one byte at a time, using a custom buffering solution
        var buf: [4096]u8 = undefined;
        var idx: usize = 0;
        const w = devnull.writer();
        for (0..1 << 20) |i| {
            buf[idx] = @truncate(i);
            idx += 1;

            if (idx >= buf.len) {
                try w.writeAll(&buf);
                idx = 0;
            }
        }
        try w.writeAll(buf[0..idx]);

        std.debug.print("Custom buffering: {}\n", .{std.fmt.fmtDuration(timer.read())});
    }
}

const std = @import("std");

EDIT (by @mlugg): the original numbers here were incorrect, since OP accidentally used -Doptimize with zig run. Accurate numbers from running this on my system are as follows:

[mlugg@nebula test]$ zig run repro.zig -OReleaseFast
BufferedWriter: 488.15us
Custom buffering: 272.103us

Using a custom buffering solution rather than std.io.BufferedWriter results in an approximately 2x speedup, simply by avoiding the overhead of std.io.AnyWriter.

This pretty much defeats the whole point of having BufferedWriter in the first place, since AnyWriter destroys the good write performance it would otherwise provide. (EDIT @mlugg: this sentence was written based on incorrect performance numbers, which showed a wrongly exaggerated result.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementSolving this issue will likely involve adding new logic or components to the codebase.optimizationstandard libraryThis issue involves writing Zig code for the standard library.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions