From 10048b0d31d0db923ae39c6bbd67139ed6252f6f Mon Sep 17 00:00:00 2001 From: Sam Atman Date: Wed, 30 Apr 2025 20:30:39 -0400 Subject: Allocation Failure Tests These turned up an excessive amount of allocations in CanonData and CompatData, which have been reduced to two through the somewhat squirrely use of 'magic numbers'. There are now allocation tests for every allocated structure in the library, and they run to completion in a reasonable amount of time. So, that's nice. --- src/CanonData.zig | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) (limited to 'src/CanonData.zig') diff --git a/src/CanonData.zig b/src/CanonData.zig index d95a5be..5d2332a 100644 --- a/src/CanonData.zig +++ b/src/CanonData.zig @@ -2,6 +2,7 @@ nfc: std.AutoHashMapUnmanaged([2]u21, u21), nfd: [][]u21 = undefined, +cps: []u21 = undefined, const CanonData = @This(); @@ -17,23 +18,29 @@ pub fn init(allocator: mem.Allocator) !CanonData { .nfc = .empty, .nfd = try allocator.alloc([]u21, 0x110000), }; - var _cp: u24 = undefined; + { + errdefer allocator.free(cdata.nfd); + cdata.cps = try allocator.alloc(u21, magic.canon_size); + } + + var total_cp: u24 = undefined; errdefer { cdata.nfc.deinit(allocator); - for (cdata.nfd[0.._cp]) |slice| allocator.free(slice); + allocator.free(cdata.cps); allocator.free(cdata.nfd); } @memset(cdata.nfd, &.{}); + var total_len: usize = 0; + while (true) { const len: u8 = try reader.readInt(u8, endian); if (len == 0) break; const cp = try reader.readInt(u24, endian); - _cp = cp; - const nfd_cp = try allocator.alloc(u21, len - 1); - errdefer allocator.free(nfd_cp); + total_cp = cp; + const nfd_cp = cdata.cps[total_len..][0 .. len - 1]; for (0..len - 1) |i| { nfd_cp[i] = @intCast(try reader.readInt(u24, endian)); } @@ -41,14 +48,17 @@ pub fn init(allocator: mem.Allocator) !CanonData { try cdata.nfc.put(allocator, nfd_cp[0..2].*, @intCast(cp)); } cdata.nfd[cp] = nfd_cp; + total_len += len - 1; } + if (comptime magic.print) std.debug.print("CanonData magic number: {d}\n", .{total_len}); + return cdata; } pub fn deinit(cdata: *CanonData, allocator: mem.Allocator) void { cdata.nfc.deinit(allocator); - for (cdata.nfd) |slice| allocator.free(slice); + allocator.free(cdata.cps); allocator.free(cdata.nfd); } @@ -66,3 +76,5 @@ const std = @import("std"); const builtin = @import("builtin"); const compress = std.compress; const mem = std.mem; +const magic = @import("magic"); +const options = @import("options"); -- cgit v1.2.3