macos: increase child process stdio buffer size

On macOS, when calling `spawn`, the child process's stdio buffer
size is 8192 bytes. This is due to the AF_UNIX socket buffer size
being 8192 bytes in the XNU kernel.

When large amounts of data are transferred through the child
process's stdio, this buffer size can cause performance issues.
To mitigate this, the buffer size has been increased to 65536
bytes, aligning it with the behavior on Linux.
This commit is contained in:
verycosy 2025-02-08 20:30:45 +09:00 committed by Colin Ihrig
parent abe59d6319
commit 6889c552e5
3 changed files with 40 additions and 2 deletions

View File

@ -509,4 +509,6 @@ typedef struct {
#define UV_FS_O_SEQUENTIAL 0
#define UV_FS_O_TEMPORARY 0
#define UV_SPAWN_BUFFER_SIZE (64 * 1024)
#endif /* UV_UNIX_H */

View File

@ -188,6 +188,7 @@ void uv__wait_children(uv_loop_t* loop) {
static int uv__process_init_stdio(uv_stdio_container_t* container, int fds[2]) {
int mask;
int fd;
int ret;
mask = UV_IGNORE | UV_CREATE_PIPE | UV_INHERIT_FD | UV_INHERIT_STREAM;
@ -199,8 +200,27 @@ static int uv__process_init_stdio(uv_stdio_container_t* container, int fds[2]) {
assert(container->data.stream != NULL);
if (container->data.stream->type != UV_NAMED_PIPE)
return UV_EINVAL;
else
return uv_socketpair(SOCK_STREAM, 0, fds, 0, 0);
else {
ret = uv_socketpair(SOCK_STREAM, 0, fds, 0, 0);
#ifdef __APPLE__
if(ret == 0) {
int size = UV_SPAWN_BUFFER_SIZE;
int options[] = {SO_RCVBUF, SO_SNDBUF};
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
ret = setsockopt(fds[i], SOL_SOCKET, options[j], &size, sizeof(size));
if (ret != 0)
return ret;
}
}
}
#endif
return ret;
}
case UV_INHERIT_FD:
case UV_INHERIT_STREAM:

View File

@ -603,6 +603,22 @@ TEST_IMPL(spawn_stdin) {
r = uv_spawn(uv_default_loop(), &process, &options);
ASSERT_OK(r);
#ifdef __APPLE__
int recv_buf;
int recv_fd;
int send_buf;
int send_fd;
socklen_t optlen = sizeof(int);
ASSERT_OK(uv_fileno((uv_handle_t*) options.stdio[0].data.stream, &recv_fd));
ASSERT_OK(getsockopt(recv_fd, SOL_SOCKET, SO_RCVBUF, &recv_buf, &optlen));
ASSERT_EQ(recv_buf, UV_SPAWN_BUFFER_SIZE);
ASSERT_OK(uv_fileno((uv_handle_t*) options.stdio[1].data.stream, &send_fd));
ASSERT_OK(getsockopt(send_fd, SOL_SOCKET, SO_SNDBUF, &send_buf, &optlen));
ASSERT_EQ(send_buf, UV_SPAWN_BUFFER_SIZE);
#endif
buf.base = buffer;
buf.len = sizeof(buffer);
r = uv_write(&write_req, (uv_stream_t*) &in, &buf, 1, write_cb);