authorgravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2026-04-13 02:16:24 -07:00
committergravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2026-04-13 02:16:24 -07:00
log3c080a86f2a7cc235c0d64245399fcf306cde245
tree3d831d02a84c7b6e60b5761ed3f746f6d4a1b31a
parentc75a9bfb2d1523607ab3f3d676ce747a2f897a59
signaturebadge-check Signed by SSH key SHA256:4hHJbtBRU58AYXwjL7fkz2fnQHdiye8x1QpTCQ0sHNw

implement the oid .idx binary search


1 files changed, 41 insertions(+), 20 deletions(-)

git.zig+41-20
...@@ -986,10 +986,14 @@ pub const Repository = struct {...@@ -986,10 +986,14 @@ pub const Repository = struct {
986986
987 // read .idx987 // read .idx
988 if (r.idx_content.count() == 0) {988 if (r.idx_content.count() == 0) {
989 const t2 = tracer.trace(@src(), " read objects/pack", .{});
990 defer t2.end();
989 const packdir = try r.gitdir.openDir("objects/pack", .{});991 const packdir = try r.gitdir.openDir("objects/pack", .{});
990 defer packdir.close();992 defer packdir.close();
991 var iter = packdir.iterate();993 var iter = packdir.iterate();
992 while (try iter.next()) |entry| {994 while (try iter.next()) |entry| {
995 const t3 = tracer.trace(@src(), " {s}", .{entry.name});
996 defer t3.end();
993 if (entry.type != .REG) continue;997 if (entry.type != .REG) continue;
994 if (!std.mem.endsWith(u8, entry.name, ".idx")) continue;998 if (!std.mem.endsWith(u8, entry.name, ".idx")) continue;
995 // std.log.debug("packdir iterate: {s}", .{entry.name});999 // std.log.debug("packdir iterate: {s}", .{entry.name});
...@@ -1005,7 +1009,11 @@ pub const Repository = struct {...@@ -1005,7 +1009,11 @@ pub const Repository = struct {
1005 );1009 );
1006 }1010 }
1007 }1011 }
1012 const t4 = tracer.trace(@src(), " find pack_index/pack_offset", .{});
1013 errdefer t4.end();
1008 const pack_index, const pack_offset = blk: for (r.idx_content.keys(), r.idx_content.values()) |idx_path, idx_content| {1014 const pack_index, const pack_offset = blk: for (r.idx_content.keys(), r.idx_content.values()) |idx_path, idx_content| {
1015 const t5 = tracer.trace(@src(), " {s}", .{idx_path});
1016 defer t5.end();
1009 if (std.mem.startsWith(u8, idx_content, "\xfftOc")) {1017 if (std.mem.startsWith(u8, idx_content, "\xfftOc")) {
1010 std.debug.assert(std.mem.readInt(u32, idx_content[4..][0..4], .big) == 2);1018 std.debug.assert(std.mem.readInt(u32, idx_content[4..][0..4], .big) == 2);
1011 const flfo_table_bytes = idx_content[8..][0 .. 256 * 4];1019 const flfo_table_bytes = idx_content[8..][0 .. 256 * 4];
...@@ -1013,31 +1021,42 @@ pub const Repository = struct {...@@ -1013,31 +1021,42 @@ pub const Repository = struct {
1013 const name_bytes = idx_content[8..][1024..][0 .. object_count * 20];1021 const name_bytes = idx_content[8..][1024..][0 .. object_count * 20];
1014 const crc32_bytes = idx_content[8..][1024..][name_bytes.len..][0 .. object_count * 4];1022 const crc32_bytes = idx_content[8..][1024..][name_bytes.len..][0 .. object_count * 4];
1015 const offset_bytes = idx_content[8..][1024..][name_bytes.len..][crc32_bytes.len..][0 .. object_count * 4];1023 const offset_bytes = idx_content[8..][1024..][name_bytes.len..][crc32_bytes.len..][0 .. object_count * 4];
1016 for (0..object_count) |i| {1024 // std.sort.binarySearch;
1017 const object_id = &extras.to_hex(name_bytes[i * 20 ..][0..20].*);1025 const i = bll: {
1018 const pack_offset = std.mem.readInt(u32, offset_bytes[i * 4 ..][0..4], .big);1026 var low: usize = 0;
1019 if (std.mem.eql(u8, object_id, oid)) {1027 var high: usize = object_count;
1020 // std.log.debug("found {s} in {s} at offset {d}", .{ oid, idx_path, pack_offset });1028 while (low < high) {
1021 const pack_index = r.pack_content.getIndex(idx_path) orelse clk: {1029 const mid = low + (high - low) / 2;
1022 var pack_path: [128]u8 = @splat(0);1030 const object_id = &extras.to_hex(name_bytes[mid * 20 ..][0..20].*);
1023 @memcpy(pack_path[0..13], "objects/pack/");1031 switch (std.mem.order(u8, oid, object_id)) {
1024 @memcpy(pack_path[13..][0..idx_path.len], idx_path);1032 .eq => break :bll mid,
1025 @memcpy(pack_path[13..][idx_path.len - 4 ..][0..5], ".pack");1033 .gt => low = mid + 1,
1026 const pack_name_nidx = std.mem.indexOfScalar(u8, &pack_path, 0).?;1034 .lt => high = mid,
1027 const pack_file = try r.gitdir.openFile(pack_path[0..pack_name_nidx :0], .{});1035 }
1028 defer pack_file.close();
1029 const pack_content = try pack_file.mmap();
1030 errdefer nfs.munmap(pack_content);
1031 try r.pack_content.put(r.gpa, idx_path, pack_content);
1032 break :clk r.pack_content.count() - 1;
1033 };
1034 break :blk .{ pack_index, pack_offset };
1035 }1036 }
1036 }1037 continue;
1038 };
1039 const pack_offset = std.mem.readInt(u32, offset_bytes[i * 4 ..][0..4], .big);
1040 // std.log.debug("found {s} in {s} at offset {d}", .{ oid, idx_path, pack_offset });
1041 const pack_index = r.pack_content.getIndex(idx_path) orelse clk: {
1042 var pack_path: [128]u8 = @splat(0);
1043 @memcpy(pack_path[0..13], "objects/pack/");
1044 @memcpy(pack_path[13..][0..idx_path.len], idx_path);
1045 @memcpy(pack_path[13..][idx_path.len - 4 ..][0..5], ".pack");
1046 const pack_name_nidx = std.mem.indexOfScalar(u8, &pack_path, 0).?;
1047 const pack_file = try r.gitdir.openFile(pack_path[0..pack_name_nidx :0], .{});
1048 defer pack_file.close();
1049 const pack_content = try pack_file.mmap();
1050 errdefer nfs.munmap(pack_content);
1051 try r.pack_content.put(r.gpa, idx_path, pack_content);
1052 break :clk r.pack_content.count() - 1;
1053 };
1054 break :blk .{ pack_index, pack_offset };
1037 } else {1055 } else {
1038 return error.Version1Idx;1056 return error.Version1Idx;
1039 }1057 }
1040 } else return null;1058 } else return null;
1059 t4.end();
10411060
1042 // parse .pack1061 // parse .pack
1043 // std.log.debug("pack_index={d} pack_offset={d}", .{ pack_index, pack_offset });1062 // std.log.debug("pack_index={d} pack_offset={d}", .{ pack_index, pack_offset });
...@@ -1066,6 +1085,8 @@ pub const Repository = struct {...@@ -1066,6 +1085,8 @@ pub const Repository = struct {
1066 size += (c & 0x7f) << shift;1085 size += (c & 0x7f) << shift;
1067 shift += 7;1086 shift += 7;
1068 }1087 }
1088 const t2 = tracer.trace(@src(), " 2 {s} {d}", .{ @tagName(ty), size });
1089 defer t2.end();
1069 switch (ty) {1090 switch (ty) {
1070 .none => {1091 .none => {
1071 unreachable;1092 unreachable;