Should we expect zig 0.13 binaries to be slower than 0.11? (at least those that use random number generators)

I have been benchmarking this program

const std = @import("std");
const boolGenerate = @import("bool_generate.zig").boolGenerate;
const ourRng = @import("utils.zig").ourRng;

pub fn main() !void {
    const allocator = std.heap.page_allocator;
    var prng: std.rand.DefaultPrng = try ourRng();
    const rndGen = prng.random();
    var argsIterator = try std.process.argsWithAllocator(allocator);
    defer argsIterator.deinit();

    _ = argsIterator.next(); // First argument is the program name

    const stringLenArg = argsIterator.next() orelse "512";

    const stringLength = try std.fmt.parseInt(u16, stringLenArg, 10);

    const numStrings = 40000;

    const output = try boolGenerate(allocator, rndGen, stringLength, numStrings);
    std.debug.print("Generated {} strings of length {}\n", .{ numStrings, stringLength });
    defer {
        for (output) |str| allocator.free(str);
        allocator.free(output);
    }
    const stdout = std.io.getStdOut().writer();
    try stdout.print("{} \n", .{output.len});
}

Don’t include the whole thing, essentially boolGenerate uses the random generator to flip a random number of bits in the chromosome of length stringLength. The thing is that I have noticed a 20% performance hit all across the lengths that I had been measuring.
A previous version of this code used std.random.crypto so I thought the change in performance was due to that; but actually when I changed to std.posix.getRandom as opposed to std.rand.getRandom I got a huge performance penalty too.
The main bottleneck should be the random number generator here. Maybe the default RNG has changed, and this one is better, but slower?

Right, this commit changes Xoroshiro128 to Xoshiro256, which I guess should be a bit slower.

This should be expected. std.posix.getRandom is a syscall for system entropy, using it as a source for random numbers would be very slow.

std.crypto.random is a CSPRNG: a Cryptographically-Secure Pseudo-Random Number Generator. This will also be slow, and you shouldn’t use it unless you need the cryptographic security (and from what you describe, you do not).

It’s not clear from your code where either of those get used, however, but you really just want to make a syscall to seed a PRNG and then use that.

std.Random has a number of generators, Xoroshiro256++ is very high-quality randomness (for a PRNG) but it isn’t the very fastest. There’s always a tradeoff between speed and quality in PRNGs (although some are off the Pareto frontier there and should simply not be used). Your best bet is to benchmark several and see which works best for your application: from what I know about PRNGs (something, but I’m not an expert / implementer) all of the ones in std are non-deprecated choices.

3 Likes