@@ -324,7 +324,7 @@ var global_progress: Progress = .{
324
324
.node_end_index = 0 ,
325
325
};
326
326
327
- const node_storage_buffer_len = 200 ;
327
+ const node_storage_buffer_len = 83 ;
328
328
var node_parents_buffer : [node_storage_buffer_len ]Node.Parent = undefined ;
329
329
var node_storage_buffer : [node_storage_buffer_len ]Node.Storage = undefined ;
330
330
var node_freelist_buffer : [node_storage_buffer_len ]Node.OptionalIndex = undefined ;
@@ -755,8 +755,10 @@ const Serialized = struct {
755
755
756
756
parents_copy : [node_storage_buffer_len ]Node.Parent ,
757
757
storage_copy : [node_storage_buffer_len ]Node.Storage ,
758
+ ipc_metadata_fds_copy : [node_storage_buffer_len ]Fd ,
758
759
ipc_metadata_copy : [node_storage_buffer_len ]SavedMetadata ,
759
760
761
+ ipc_metadata_fds : [node_storage_buffer_len ]Fd ,
760
762
ipc_metadata : [node_storage_buffer_len ]SavedMetadata ,
761
763
};
762
764
};
@@ -810,36 +812,39 @@ fn serialize(serialized_buffer: *Serialized.Buffer) Serialized {
810
812
}
811
813
812
814
const SavedMetadata = struct {
813
- ipc_fd : u16 ,
815
+ remaining_read_trash_bytes : u16 ,
814
816
main_index : u8 ,
815
817
start_index : u8 ,
816
818
nodes_len : u8 ,
819
+ };
817
820
818
- fn getIpcFd ( metadata : SavedMetadata ) posix.fd_t {
819
- return if ( is_windows )
820
- @ptrFromInt ( @as ( usize , metadata . ipc_fd ) << 2 )
821
- else
822
- metadata . ipc_fd ;
821
+ const Fd = enum ( i32 ) {
822
+ _ ,
823
+
824
+ fn init ( fd : posix.fd_t ) Fd {
825
+ return @enumFromInt ( if ( is_windows ) @as ( isize , @bitCast ( @intFromPtr ( fd ))) else fd ) ;
823
826
}
824
827
825
- fn setIpcFd (fd : posix.fd_t ) u16 {
826
- return @intCast ( if (is_windows )
827
- @shrExact ( @intFromPtr ( fd ), 2 )
828
+ fn get (fd : Fd ) posix.fd_t {
829
+ return if (is_windows )
830
+ @ptrFromInt ( @as ( usize , @bitCast ( @as ( isize , @intFromEnum ( fd )))) )
828
831
else
829
- fd );
832
+ @intFromEnum ( fd );
830
833
}
831
834
};
832
835
833
836
var ipc_metadata_len : u8 = 0 ;
834
- var remaining_read_trash_bytes : usize = 0 ;
835
837
836
838
fn serializeIpc (start_serialized_len : usize , serialized_buffer : * Serialized.Buffer ) usize {
839
+ const ipc_metadata_fds_copy = & serialized_buffer .ipc_metadata_fds_copy ;
837
840
const ipc_metadata_copy = & serialized_buffer .ipc_metadata_copy ;
841
+ const ipc_metadata_fds = & serialized_buffer .ipc_metadata_fds ;
838
842
const ipc_metadata = & serialized_buffer .ipc_metadata ;
839
843
840
844
var serialized_len = start_serialized_len ;
841
- var pipe_buf : [2 * 4096 ]u8 align ( 4 ) = undefined ;
845
+ var pipe_buf : [2 * 4096 ]u8 = undefined ;
842
846
847
+ const old_ipc_metadata_fds = ipc_metadata_fds_copy [0.. ipc_metadata_len ];
843
848
const old_ipc_metadata = ipc_metadata_copy [0.. ipc_metadata_len ];
844
849
ipc_metadata_len = 0 ;
845
850
@@ -850,6 +855,7 @@ fn serializeIpc(start_serialized_len: usize, serialized_buffer: *Serialized.Buff
850
855
) | main_parent , * main_storage , main_index | {
851
856
if (main_parent == .unused ) continue ;
852
857
const fd = main_storage .getIpcFd () orelse continue ;
858
+ const opt_saved_metadata = findOld (fd , old_ipc_metadata_fds , old_ipc_metadata );
853
859
var bytes_read : usize = 0 ;
854
860
while (true ) {
855
861
const n = posix .read (fd , pipe_buf [bytes_read .. ]) catch | err | switch (err ) {
@@ -862,24 +868,26 @@ fn serializeIpc(start_serialized_len: usize, serialized_buffer: *Serialized.Buff
862
868
},
863
869
};
864
870
if (n == 0 ) break ;
865
- if (remaining_read_trash_bytes > 0 ) {
866
- assert (bytes_read == 0 );
867
- if (remaining_read_trash_bytes >= n ) {
868
- remaining_read_trash_bytes -= n ;
871
+ if (opt_saved_metadata ) | m | {
872
+ if (m .remaining_read_trash_bytes > 0 ) {
873
+ assert (bytes_read == 0 );
874
+ if (m .remaining_read_trash_bytes >= n ) {
875
+ m .remaining_read_trash_bytes = @intCast (m .remaining_read_trash_bytes - n );
876
+ continue ;
877
+ }
878
+ const src = pipe_buf [m .remaining_read_trash_bytes .. n ];
879
+ std .mem .copyForwards (u8 , & pipe_buf , src );
880
+ m .remaining_read_trash_bytes = 0 ;
881
+ bytes_read = src .len ;
869
882
continue ;
870
883
}
871
- const src = pipe_buf [remaining_read_trash_bytes .. n ];
872
- std .mem .copyForwards (u8 , & pipe_buf , src );
873
- remaining_read_trash_bytes = 0 ;
874
- bytes_read = src .len ;
875
- continue ;
876
884
}
877
885
bytes_read += n ;
878
886
}
879
887
// Ignore all but the last message on the pipe.
880
888
var input : []u8 = pipe_buf [0.. bytes_read ];
881
889
if (input .len == 0 ) {
882
- serialized_len = useSavedIpcData (serialized_len , serialized_buffer , main_storage , main_index , old_ipc_metadata );
890
+ serialized_len = useSavedIpcData (serialized_len , serialized_buffer , main_storage , main_index , opt_saved_metadata , 0 , fd );
883
891
continue ;
884
892
}
885
893
@@ -888,9 +896,8 @@ fn serializeIpc(start_serialized_len: usize, serialized_buffer: *Serialized.Buff
888
896
const expected_bytes = 1 + subtree_len * (@sizeOf (Node .Storage ) + @sizeOf (Node .Parent ));
889
897
if (input .len < expected_bytes ) {
890
898
// Ignore short reads. We'll handle the next full message when it comes instead.
891
- assert (remaining_read_trash_bytes == 0 );
892
- remaining_read_trash_bytes = expected_bytes - input .len ;
893
- serialized_len = useSavedIpcData (serialized_len , serialized_buffer , main_storage , main_index , old_ipc_metadata );
899
+ const remaining_read_trash_bytes : u16 = @intCast (expected_bytes - input .len );
900
+ serialized_len = useSavedIpcData (serialized_len , serialized_buffer , main_storage , main_index , opt_saved_metadata , remaining_read_trash_bytes , fd );
894
901
continue :main_loop ;
895
902
}
896
903
if (input .len > expected_bytes ) {
@@ -908,8 +915,9 @@ fn serializeIpc(start_serialized_len: usize, serialized_buffer: *Serialized.Buff
908
915
const nodes_len : u8 = @intCast (@min (parents .len - 1 , serialized_buffer .storage .len - serialized_len ));
909
916
910
917
// Remember in case the pipe is empty on next update.
918
+ ipc_metadata_fds [ipc_metadata_len ] = Fd .init (fd );
911
919
ipc_metadata [ipc_metadata_len ] = .{
912
- .ipc_fd = SavedMetadata . setIpcFd ( fd ) ,
920
+ .remaining_read_trash_bytes = 0 ,
913
921
.start_index = @intCast (serialized_len ),
914
922
.nodes_len = nodes_len ,
915
923
.main_index = @intCast (main_index ),
@@ -950,6 +958,7 @@ fn serializeIpc(start_serialized_len: usize, serialized_buffer: *Serialized.Buff
950
958
// Save a copy in case any pipes are empty on the next update.
951
959
@memcpy (serialized_buffer .parents_copy [0.. serialized_len ], serialized_buffer .parents [0.. serialized_len ]);
952
960
@memcpy (serialized_buffer .storage_copy [0.. serialized_len ], serialized_buffer .storage [0.. serialized_len ]);
961
+ @memcpy (ipc_metadata_fds_copy [0.. ipc_metadata_len ], ipc_metadata_fds [0.. ipc_metadata_len ]);
953
962
@memcpy (ipc_metadata_copy [0.. ipc_metadata_len ], ipc_metadata [0.. ipc_metadata_len ]);
954
963
955
964
return serialized_len ;
@@ -963,9 +972,13 @@ fn copyRoot(dest: *Node.Storage, src: *align(1) Node.Storage) void {
963
972
};
964
973
}
965
974
966
- fn findOld (ipc_fd : posix.fd_t , old_metadata : []const SavedMetadata ) ? * const SavedMetadata {
967
- for (old_metadata ) | * m | {
968
- if (m .getIpcFd () == ipc_fd )
975
+ fn findOld (
976
+ ipc_fd : posix.fd_t ,
977
+ old_metadata_fds : []Fd ,
978
+ old_metadata : []SavedMetadata ,
979
+ ) ? * SavedMetadata {
980
+ for (old_metadata_fds , old_metadata ) | fd , * m | {
981
+ if (fd .get () == ipc_fd )
969
982
return m ;
970
983
}
971
984
return null ;
@@ -976,25 +989,38 @@ fn useSavedIpcData(
976
989
serialized_buffer : * Serialized.Buffer ,
977
990
main_storage : * Node.Storage ,
978
991
main_index : usize ,
979
- old_metadata : []const SavedMetadata ,
992
+ opt_saved_metadata : ? * SavedMetadata ,
993
+ remaining_read_trash_bytes : u16 ,
994
+ fd : posix.fd_t ,
980
995
) usize {
981
996
const parents_copy = & serialized_buffer .parents_copy ;
982
997
const storage_copy = & serialized_buffer .storage_copy ;
998
+ const ipc_metadata_fds = & serialized_buffer .ipc_metadata_fds ;
983
999
const ipc_metadata = & serialized_buffer .ipc_metadata ;
984
1000
985
- const ipc_fd = main_storage .getIpcFd ().? ;
986
- const saved_metadata = findOld (ipc_fd , old_metadata ) orelse {
1001
+ const saved_metadata = opt_saved_metadata orelse {
987
1002
main_storage .completed_count = 0 ;
988
1003
main_storage .estimated_total_count = 0 ;
1004
+ if (remaining_read_trash_bytes > 0 ) {
1005
+ ipc_metadata_fds [ipc_metadata_len ] = Fd .init (fd );
1006
+ ipc_metadata [ipc_metadata_len ] = .{
1007
+ .remaining_read_trash_bytes = remaining_read_trash_bytes ,
1008
+ .start_index = @intCast (start_serialized_len ),
1009
+ .nodes_len = 0 ,
1010
+ .main_index = @intCast (main_index ),
1011
+ };
1012
+ ipc_metadata_len += 1 ;
1013
+ }
989
1014
return start_serialized_len ;
990
1015
};
991
1016
992
1017
const start_index = saved_metadata .start_index ;
993
1018
const nodes_len = @min (saved_metadata .nodes_len , serialized_buffer .storage .len - start_serialized_len );
994
1019
const old_main_index = saved_metadata .main_index ;
995
1020
1021
+ ipc_metadata_fds [ipc_metadata_len ] = Fd .init (fd );
996
1022
ipc_metadata [ipc_metadata_len ] = .{
997
- .ipc_fd = SavedMetadata . setIpcFd ( ipc_fd ) ,
1023
+ .remaining_read_trash_bytes = remaining_read_trash_bytes ,
998
1024
.start_index = @intCast (start_serialized_len ),
999
1025
.nodes_len = nodes_len ,
1000
1026
.main_index = @intCast (main_index ),
@@ -1209,6 +1235,11 @@ fn writeIpc(fd: posix.fd_t, serialized: Serialized) error{BrokenPipe}!void {
1209
1235
.{ .base = parents .ptr , .len = parents .len },
1210
1236
};
1211
1237
1238
+ // Ensures the packet can fit in the pipe buffer.
1239
+ const upper_bound_msg_len = 1 + node_storage_buffer_len * @sizeOf (Node .Storage ) +
1240
+ node_storage_buffer_len * @sizeOf (Node .OptionalIndex );
1241
+ comptime assert (upper_bound_msg_len <= 4096 );
1242
+
1212
1243
while (remaining_write_trash_bytes > 0 ) {
1213
1244
// We do this in a separate write call to give a better chance for the
1214
1245
// writev below to be in a single packet.
@@ -1228,7 +1259,7 @@ fn writeIpc(fd: posix.fd_t, serialized: Serialized) error{BrokenPipe}!void {
1228
1259
1229
1260
// If this write would block we do not want to keep trying, but we need to
1230
1261
// know if a partial message was written.
1231
- if (posix . writev (fd , & vecs )) | written | {
1262
+ if (writevNonblock (fd , & vecs )) | written | {
1232
1263
const total = header .len + storage .len + parents .len ;
1233
1264
if (written < total ) {
1234
1265
remaining_write_trash_bytes = total - written ;
@@ -1243,6 +1274,23 @@ fn writeIpc(fd: posix.fd_t, serialized: Serialized) error{BrokenPipe}!void {
1243
1274
}
1244
1275
}
1245
1276
1277
+ fn writevNonblock (fd : posix.fd_t , iov : []posix.iovec_const ) posix.WriteError ! usize {
1278
+ var iov_index : usize = 0 ;
1279
+ var written : usize = 0 ;
1280
+ var total_written : usize = 0 ;
1281
+ while (true ) {
1282
+ while (if (iov_index < iov .len )
1283
+ written >= iov [iov_index ].len
1284
+ else
1285
+ return total_written ) : (iov_index += 1 ) written -= iov [iov_index ].len ;
1286
+ iov [iov_index ].base += written ;
1287
+ iov [iov_index ].len -= written ;
1288
+ written = try posix .writev (fd , iov [iov_index .. ]);
1289
+ if (written == 0 ) return total_written ;
1290
+ total_written += written ;
1291
+ }
1292
+ }
1293
+
1246
1294
fn maybeUpdateSize (resize_flag : bool ) void {
1247
1295
if (! resize_flag ) return ;
1248
1296
0 commit comments