Message ID | 311ea4a5cd71c5dd2407348ad4608d2f7dd77ce5.1615302157.git.gitgitgadget@gmail.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | Simple IPC Mechanism | expand |
"Jeff Hostetler via GitGitGadget" <gitgitgadget@gmail.com> writes: > + /* > + * Write the header and the buffer in 2 parts so that we do not need > + * to allocate a buffer or rely on a static buffer. This avoids perf > + * and multi-threading issues. > + */ I understand "multi-threading issues" (i.e. let's not have too much stuff on the stack), but what issue around "perf" are we worried about? Even though we eliminate memcpy() from the original buffer to our temporary, this doubles the number of write(2) system calls used to write out packetised data, by the way. I do not know if this results in measurable performance degradation, but hopefully we can fix it locally if it turns out to be a real problem later. > + if (write_in_full(fd_out, header, 4) < 0 || > + write_in_full(fd_out, buf, size) < 0) > return error(_("packet write failed")); > return 0; > } > @@ -244,20 +252,23 @@ void packet_buf_write_len(struct strbuf *buf, const char *data, size_t len) > > int write_packetized_from_fd(int fd_in, int fd_out) > { > - static char buf[LARGE_PACKET_DATA_MAX]; > + char *buf = xmalloc(LARGE_PACKET_DATA_MAX); > int err = 0; > ssize_t bytes_to_write; > > while (!err) { > - bytes_to_write = xread(fd_in, buf, sizeof(buf)); > - if (bytes_to_write < 0) > + bytes_to_write = xread(fd_in, buf, LARGE_PACKET_DATA_MAX); > + if (bytes_to_write < 0) { > + free(buf); > return COPY_READ_ERROR; > + } > if (bytes_to_write == 0) > break; > err = packet_write_gently(fd_out, buf, bytes_to_write); > } > if (!err) > err = packet_flush_gently(fd_out); > + free(buf); > return err; > }
On Tue, Mar 09, 2021 at 03:48:40PM -0800, Junio C Hamano wrote: > "Jeff Hostetler via GitGitGadget" <gitgitgadget@gmail.com> writes: > > > + /* > > + * Write the header and the buffer in 2 parts so that we do not need > > + * to allocate a buffer or rely on a static buffer. This avoids perf > > + * and multi-threading issues. > > + */ > > I understand "multi-threading issues" (i.e. let's not have too much > stuff on the stack), but what issue around "perf" are we worried > about? > > Even though we eliminate memcpy() from the original buffer to our > temporary, this doubles the number of write(2) system calls used to > write out packetised data, by the way. I do not know if this results > in measurable performance degradation, but hopefully we can fix it > locally if it turns out to be a real problem later. Yeah, this came from my suggestion. My gut feeling is that it isn't likely to matter, but I'd much rather solve any performance problem we find using writev(), which would be pretty easy to emulate with a wrapper for systems that lack it. -Peff
Jeff King <peff@peff.net> writes: > On Tue, Mar 09, 2021 at 03:48:40PM -0800, Junio C Hamano wrote: > >> "Jeff Hostetler via GitGitGadget" <gitgitgadget@gmail.com> writes: >> >> > + /* >> > + * Write the header and the buffer in 2 parts so that we do not need >> > + * to allocate a buffer or rely on a static buffer. This avoids perf >> > + * and multi-threading issues. >> > + */ >> >> I understand "multi-threading issues" (i.e. let's not have too much >> stuff on the stack), but what issue around "perf" are we worried >> about? >> ... > Yeah, this came from my suggestion. My gut feeling is that it isn't > likely to matter, but I'd much rather solve any performance problem we > find using writev(), which would be pretty easy to emulate with a > wrapper for systems that lack it. I too had writev() in mind when I said "can fix it locally", so we are on the same page, which is good. So "this avoid multi-threading issues" without mentioning "perf and" would be more appropriate? Thanks.
On Thu, Mar 11, 2021 at 12:32:29PM -0800, Junio C Hamano wrote: > Jeff King <peff@peff.net> writes: > > > On Tue, Mar 09, 2021 at 03:48:40PM -0800, Junio C Hamano wrote: > > > >> "Jeff Hostetler via GitGitGadget" <gitgitgadget@gmail.com> writes: > >> > >> > + /* > >> > + * Write the header and the buffer in 2 parts so that we do not need > >> > + * to allocate a buffer or rely on a static buffer. This avoids perf > >> > + * and multi-threading issues. > >> > + */ > >> > >> I understand "multi-threading issues" (i.e. let's not have too much > >> stuff on the stack), but what issue around "perf" are we worried > >> about? > >> ... > > Yeah, this came from my suggestion. My gut feeling is that it isn't > > likely to matter, but I'd much rather solve any performance problem we > > find using writev(), which would be pretty easy to emulate with a > > wrapper for systems that lack it. > > I too had writev() in mind when I said "can fix it locally", so we > are on the same page, which is good. > > So "this avoid multi-threading issues" without mentioning "perf and" > would be more appropriate? IMHO yes. I think "avoid perf issues" is probably answering the "why not just heap-allocate the buffer" question. But that makes sense in the commit message, not in a comment. -Peff
diff --git a/pkt-line.c b/pkt-line.c index d633005ef746..8b3512190442 100644 --- a/pkt-line.c +++ b/pkt-line.c @@ -196,17 +196,25 @@ int packet_write_fmt_gently(int fd, const char *fmt, ...) static int packet_write_gently(const int fd_out, const char *buf, size_t size) { - static char packet_write_buffer[LARGE_PACKET_MAX]; + char header[4]; size_t packet_size; - if (size > sizeof(packet_write_buffer) - 4) + if (size > LARGE_PACKET_DATA_MAX) return error(_("packet write failed - data exceeds max packet size")); packet_trace(buf, size, 1); packet_size = size + 4; - set_packet_header(packet_write_buffer, packet_size); - memcpy(packet_write_buffer + 4, buf, size); - if (write_in_full(fd_out, packet_write_buffer, packet_size) < 0) + + set_packet_header(header, packet_size); + + /* + * Write the header and the buffer in 2 parts so that we do not need + * to allocate a buffer or rely on a static buffer. This avoids perf + * and multi-threading issues. + */ + + if (write_in_full(fd_out, header, 4) < 0 || + write_in_full(fd_out, buf, size) < 0) return error(_("packet write failed")); return 0; } @@ -244,20 +252,23 @@ void packet_buf_write_len(struct strbuf *buf, const char *data, size_t len) int write_packetized_from_fd(int fd_in, int fd_out) { - static char buf[LARGE_PACKET_DATA_MAX]; + char *buf = xmalloc(LARGE_PACKET_DATA_MAX); int err = 0; ssize_t bytes_to_write; while (!err) { - bytes_to_write = xread(fd_in, buf, sizeof(buf)); - if (bytes_to_write < 0) + bytes_to_write = xread(fd_in, buf, LARGE_PACKET_DATA_MAX); + if (bytes_to_write < 0) { + free(buf); return COPY_READ_ERROR; + } if (bytes_to_write == 0) break; err = packet_write_gently(fd_out, buf, bytes_to_write); } if (!err) err = packet_flush_gently(fd_out); + free(buf); return err; }