marlersoft / zigwin32gen

Generates Complete Zig bindings for Win32. See https://github.com/marlersoft/zigwin32 for the bindings themselves.
108 stars 17 forks source link

Feature/std os windows guid #12

Open arBmind opened 2 years ago

marler8997 commented 2 years ago

Your branch made me realize that I should have been importing Guid instead of referencing its fully-qualified name each time. I pushed a commit that fixed that here: 449b7cd15244b6c652287e5321529fbbeb8b65d1

I rebased your commits and added an additional one that removes Guid completely from zig.zig and updates all references to use the one from std directly.

For some reason this this is causing zig test zigwin32\win32.zig to take forever for me...

arBmind commented 2 years ago

@marler8997 Thank you for considering my PR.

My first commit made it work, without any changes. My second commit requires this PR https://github.com/marlersoft/win32jsongen/pull/4 for win32jsongen to work properly. This adds curly braces to the GUIDs in the JSON files.

marler8997 commented 2 years ago

Ok, well the commit I added should also work, it just adds the curly braces when generating the code. However it's still making my zig test zigwin32\win32.zig take much longer but I'm not sure why (like 100 times longer, around 45 seconds compared to it's still running after 20 minutes or so). I created a small test app to see if std GUID was slower at comptime but I didn't see much difference. Will have to investigate more.

Here's the perf test app for reference:

const builtin = @import("builtin");
const std = @import("std");

pub fn main() void {
    comptime {
        const count = 1000000;
        @setEvalBranchQuota(count * 3);
        var i: usize = 0;
        while (i < count) : (i += 1) {
            //_ = std.os.windows.GUID.parse("{aa7a8931-80e4-4fec-8f3b-553f87b4966e}");
            _ = Guid.parse("aa7a8931-80e4-4fec-8f3b-553f87b4966e");
        }
    }
}

// TODO: this should probably be in the standard lib somewhere?
pub const Guid = extern union {
    Ints: extern struct {
        a: u32,
        b: u16,
        c: u16,
        d: [8]u8,
    },
    Bytes: [16]u8,

    const big_endian_hex_offsets = [16] u6 {0, 2, 4, 6, 9, 11, 14, 16, 19, 21, 24, 26, 28, 30, 32, 34};
    const little_endian_hex_offsets = [16] u6 {
        6, 4, 2, 0,
        11, 9,
        16, 14,
        19, 21, 24, 26, 28, 30, 32, 34};
    const hex_offsets = switch (builtin.target.cpu.arch.endian()) {
        .Big => big_endian_hex_offsets,
        .Little => little_endian_hex_offsets,
    };

    pub fn parse(s: []const u8) Guid {
        var guid = Guid { .Bytes = undefined };
        for (hex_offsets) |hex_offset, i| {
            //guid.Bytes[i] = decodeHexByte(s[offset..offset+2]);
            guid.Bytes[i] = decodeHexByte([2]u8 { s[hex_offset], s[hex_offset+1] });
        }
        return guid;
    }
};
comptime { std.debug.assert(@sizeOf(Guid) == 16); }

// TODO: is this in the standard lib somewhere?
fn hexVal(c: u8) u4 {
    if (c <= '9') return @intCast(u4, c - '0');
    if (c >= 'a') return @intCast(u4, c + 10 - 'a');
    return @intCast(u4, c + 10 - 'A');
}

// TODO: is this in the standard lib somewhere?
fn decodeHexByte(hex: [2]u8) u8 {
    return @intCast(u8, hexVal(hex[0])) << 4 | hexVal(hex[1]);
}
marler8997 commented 2 years ago

Ok I've grepped all of zigwin32 for all the Guids and put them into a single file to test performance (see https://gist.github.com/marler8997/2ab2fc12190792308d233efcafe89ac3). My custom Guid takes about 12 seconds to run zig test guids.zig, the one from std.os.windows takes about 6 minutes! To see for yourself, change the variable use_std_guid in the gist above to test the performance of each one.

marler8997 commented 2 years ago

I've submitted a PR to create a benchmark for GUID.parse here: https://github.com/ziglang/gotta-go-fast/pull/21

Once that's in I'll see about replacing the implementation in std with the one here, then we could switch to it.