mirror of
https://github.com/ziglang/zig.git
synced 2024-11-15 00:26:57 +00:00
std.Progress: smaller type for parents and robustify
Switch Node.Parent, Node.Index, and Node.OptionalIndex to be backed by u8 rather than u16. This works fine since we use 200 as the preallocated node buffer. This has the nice property that scanning the entire parents array for allocated nodes fits in 4 cache lines, even if we bumped the 200 up to 254 (leaving room for the two special states). The thread that reads progress updates from the pipe now handles short reads by ignoring messages that are sent in multiple reads. When checking the terminal size, if there is a failure, fall back to a conservative guess of 80x25 rather than panicking. A debug message is also emitted which would be displayed only in a debug build.
This commit is contained in:
parent
11f894702b
commit
ea7d8ec147
@ -104,11 +104,11 @@ pub const Node = struct {
|
||||
}
|
||||
};
|
||||
|
||||
const Parent = enum(u16) {
|
||||
const Parent = enum(u8) {
|
||||
/// Unallocated storage.
|
||||
unused = std.math.maxInt(u16) - 1,
|
||||
unused = std.math.maxInt(u8) - 1,
|
||||
/// Indicates root node.
|
||||
none = std.math.maxInt(u16),
|
||||
none = std.math.maxInt(u8),
|
||||
/// Index into `node_storage`.
|
||||
_,
|
||||
|
||||
@ -120,8 +120,8 @@ pub const Node = struct {
|
||||
}
|
||||
};
|
||||
|
||||
const OptionalIndex = enum(u16) {
|
||||
none = std.math.maxInt(u16),
|
||||
const OptionalIndex = enum(u8) {
|
||||
none = std.math.maxInt(u8),
|
||||
/// Index into `node_storage`.
|
||||
_,
|
||||
|
||||
@ -137,7 +137,7 @@ pub const Node = struct {
|
||||
};
|
||||
|
||||
/// Index into `node_storage`.
|
||||
const Index = enum(u16) {
|
||||
const Index = enum(u8) {
|
||||
_,
|
||||
|
||||
fn toParent(i: @This()) Parent {
|
||||
@ -589,8 +589,6 @@ fn serialize(serialized_buffer: *Serialized.Buffer) Serialized {
|
||||
};
|
||||
}
|
||||
|
||||
var ipc_metadata_len: u16 = 0;
|
||||
|
||||
const SavedMetadata = struct {
|
||||
ipc_fd: u16,
|
||||
main_index: u8,
|
||||
@ -612,6 +610,9 @@ const SavedMetadata = struct {
|
||||
}
|
||||
};
|
||||
|
||||
var ipc_metadata_len: u8 = 0;
|
||||
var remaining_read_trash_bytes: usize = 0;
|
||||
|
||||
fn serializeIpc(start_serialized_len: usize, serialized_buffer: *Serialized.Buffer) usize {
|
||||
const ipc_metadata_copy = &serialized_buffer.ipc_metadata_copy;
|
||||
const ipc_metadata = &serialized_buffer.ipc_metadata;
|
||||
@ -641,36 +642,43 @@ fn serializeIpc(start_serialized_len: usize, serialized_buffer: *Serialized.Buff
|
||||
},
|
||||
};
|
||||
if (n == 0) break;
|
||||
if (remaining_read_trash_bytes > 0) {
|
||||
assert(bytes_read == 0);
|
||||
if (remaining_read_trash_bytes >= n) {
|
||||
remaining_read_trash_bytes -= n;
|
||||
continue;
|
||||
}
|
||||
const src = pipe_buf[remaining_read_trash_bytes..n];
|
||||
std.mem.copyForwards(u8, &pipe_buf, src);
|
||||
remaining_read_trash_bytes = 0;
|
||||
bytes_read = src.len;
|
||||
continue;
|
||||
}
|
||||
bytes_read += n;
|
||||
}
|
||||
// Ignore all but the last message on the pipe.
|
||||
var input: []align(2) u8 = pipe_buf[0..bytes_read];
|
||||
var input: []u8 = pipe_buf[0..bytes_read];
|
||||
if (input.len == 0) {
|
||||
serialized_len = useSavedIpcData(serialized_len, serialized_buffer, main_storage, main_index, old_ipc_metadata);
|
||||
continue;
|
||||
}
|
||||
|
||||
const storage, const parents = while (true) {
|
||||
if (input.len < 4) {
|
||||
std.log.warn("short read: {d} out of 4 header bytes", .{input.len});
|
||||
// TODO keep track of the short read to trash odd bytes with the next read
|
||||
serialized_len = useSavedIpcData(serialized_len, serialized_buffer, main_storage, main_index, old_ipc_metadata);
|
||||
continue :main_loop;
|
||||
}
|
||||
const subtree_len = std.mem.readInt(u32, input[0..4], .little);
|
||||
const expected_bytes = 4 + subtree_len * (@sizeOf(Node.Storage) + @sizeOf(Node.Parent));
|
||||
const subtree_len: usize = input[0];
|
||||
const expected_bytes = 1 + subtree_len * (@sizeOf(Node.Storage) + @sizeOf(Node.Parent));
|
||||
if (input.len < expected_bytes) {
|
||||
std.log.warn("short read: {d} out of {d} ({d} nodes)", .{ input.len, expected_bytes, subtree_len });
|
||||
// TODO keep track of the short read to trash odd bytes with the next read
|
||||
// Ignore short reads. We'll handle the next full message when it comes instead.
|
||||
assert(remaining_read_trash_bytes == 0);
|
||||
remaining_read_trash_bytes = expected_bytes - input.len;
|
||||
serialized_len = useSavedIpcData(serialized_len, serialized_buffer, main_storage, main_index, old_ipc_metadata);
|
||||
continue :main_loop;
|
||||
}
|
||||
if (input.len > expected_bytes) {
|
||||
input = @alignCast(input[expected_bytes..]);
|
||||
input = input[expected_bytes..];
|
||||
continue;
|
||||
}
|
||||
const storage_bytes = input[4..][0 .. subtree_len * @sizeOf(Node.Storage)];
|
||||
const parents_bytes = input[4 + storage_bytes.len ..][0 .. subtree_len * @sizeOf(Node.Parent)];
|
||||
const storage_bytes = input[1..][0 .. subtree_len * @sizeOf(Node.Storage)];
|
||||
const parents_bytes = input[1 + storage_bytes.len ..][0 .. subtree_len * @sizeOf(Node.Parent)];
|
||||
break .{
|
||||
std.mem.bytesAsSlice(Node.Storage, storage_bytes),
|
||||
std.mem.bytesAsSlice(Node.Parent, parents_bytes),
|
||||
@ -722,7 +730,7 @@ fn serializeIpc(start_serialized_len: usize, serialized_buffer: *Serialized.Buff
|
||||
return serialized_len;
|
||||
}
|
||||
|
||||
fn copyRoot(dest: *Node.Storage, src: *align(2) Node.Storage) void {
|
||||
fn copyRoot(dest: *Node.Storage, src: *align(1) Node.Storage) void {
|
||||
dest.* = .{
|
||||
.completed_count = src.completed_count,
|
||||
.estimated_total_count = src.estimated_total_count,
|
||||
@ -937,7 +945,7 @@ fn write(buf: []const u8) void {
|
||||
|
||||
fn writeIpc(fd: posix.fd_t, serialized: Serialized) error{BrokenPipe}!void {
|
||||
assert(serialized.parents.len == serialized.storage.len);
|
||||
const serialized_len: u32 = @intCast(serialized.parents.len);
|
||||
const serialized_len: u8 = @intCast(serialized.parents.len);
|
||||
const header = std.mem.asBytes(&serialized_len);
|
||||
const storage = std.mem.sliceAsBytes(serialized.storage);
|
||||
const parents = std.mem.sliceAsBytes(serialized.parents);
|
||||
@ -977,7 +985,9 @@ fn maybeUpdateSize(resize_flag: bool) void {
|
||||
var info: windows.CONSOLE_SCREEN_BUFFER_INFO = undefined;
|
||||
|
||||
if (windows.kernel32.GetConsoleScreenBufferInfo(fd, &info) == windows.FALSE) {
|
||||
@panic("TODO: handle this failure");
|
||||
std.log.debug("failed to determine terminal size; using conservative guess 80x25", .{});
|
||||
global_progress.rows = 25;
|
||||
global_progress.cols = 80;
|
||||
}
|
||||
|
||||
global_progress.rows = @intCast(info.dwSize.Y);
|
||||
@ -995,7 +1005,9 @@ fn maybeUpdateSize(resize_flag: bool) void {
|
||||
global_progress.rows = winsize.ws_row;
|
||||
global_progress.cols = winsize.ws_col;
|
||||
} else {
|
||||
@panic("TODO: handle this failure");
|
||||
std.log.debug("failed to determine terminal size; using conservative guess 80x25", .{});
|
||||
global_progress.rows = 25;
|
||||
global_progress.cols = 80;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user