From: Patrick Steinhardt Date: Tue, 10 Mar 2026 13:24:56 GMT Subject: [PATCH v3 00/10] upload-pack: reduce lock contention when writing packfile data Message-ID: <20260310-pks-upload-pack-write-contention-v3-0-8bc97aa3e267@pks.im> In-Reply-To: <20260227-pks-upload-pack-write-contention-v1-0-7166fe255704@pks.im> Hi, this small patch series fixes some heavy lock contention when writing data from git-upload-pack(1) into pipes. This lock contention can be observed when having hundreds of git-upload-pack(1) processes active at the same time that write data into pipes at dozens of gigabits per second. I have uploaded the flame graph that clearly shows the lock contention at [1]. Changes in v3: - Fix handling of `iov_len` overflows in writev(3p) wrapper. - Add another patch that causes us to flush out data instead of sending a 0005 keepalive packet. - Link to v2: https://lore.kernel.org/r/20260303-pks-upload-pack-write-contention-v2-0-7321830f08fe@pks.im Changes in v2: - Change the buffer size in git-pack-objects(1) to also reduce the number of write syscalls over there. - Introduce writev to half the number of syscalls when writing pktlines. - Use `sizeof(os->buffer)` instead of open-coding its size. - Improve keepalive logic in git-upload-pack(1) to account for buffering. - Link to v1: https://lore.kernel.org/r/20260227-pks-upload-pack-write-contention-v1-0-7166fe255704@pks.im Thanks! Patrick [1]: https://gitlab.com/gitlab-org/git/-/work_items/675 --- Patrick Steinhardt (10): upload-pack: fix debug statement when flushing packfile data upload-pack: adapt keepalives based on buffering upload-pack: prefer flushing data over sending keepalive upload-pack: reduce lock contention when writing packfile data compat/posix: introduce writev(3p) wrapper wrapper: introduce writev(3p) wrappers sideband: use writev(3p) to send pktlines csum-file: introduce `hashfd_ext()` csum-file: drop `hashfd_throughput()` builtin/pack-objects: reduce lock contention when writing packfile data Makefile | 4 +++ builtin/pack-objects.c | 23 +++++++++++--- compat/posix.h | 14 +++++++++ compat/writev.c | 44 +++++++++++++++++++++++++++ config.mak.uname | 2 ++ csum-file.c | 28 +++++------------ csum-file.h | 16 ++++++++-- meson.build | 1 + sideband.c | 14 +++++++-- upload-pack.c | 81 +++++++++++++++++++++++++++++++++++++++----------- wrapper.c | 41 +++++++++++++++++++++++++ wrapper.h | 9 ++++++ write-or-die.c | 8 +++++ write-or-die.h | 1 + 14 files changed, 239 insertions(+), 47 deletions(-) Range-diff versus v2: 1: ef3244ffcc = 1: 540b577540 upload-pack: fix debug statement when flushing packfile data 2: 3297edd609 = 2: 253d119b10 upload-pack: adapt keepalives based on buffering -: ---------- > 3: 960c650063 upload-pack: prefer flushing data over sending keepalive 3: 84671fb222 = 4: 0e147c41cf upload-pack: reduce lock contention when writing packfile data 4: bd1f070cb4 < -: ---------- git-compat-util: introduce `cast_size_t_to_ssize_t()` 5: d5acbd1584 ! 5: b6fbd89b8e compat/posix: introduce writev(3p) wrapper @@ compat/writev.c (new) +ssize_t git_writev(int fd, const struct iovec *iov, int iovcnt) +{ + size_t total_written = 0; ++ size_t sum = 0; ++ ++ /* ++ * According to writev(3p), the syscall shall error with EINVAL in case ++ * the sum of `iov_len` overflows `ssize_t`. ++ */ ++ for (int i = 0; i < iovcnt; i++) { ++ if (iov[i].iov_len > maximum_signed_value_of_type(ssize_t) || ++ iov[i].iov_len + sum > maximum_signed_value_of_type(ssize_t)) { ++ errno = EINVAL; ++ return -1; ++ } ++ ++ sum += iov[i].iov_len; ++ } + + for (int i = 0; i < iovcnt; i++) { + const char *bytes = iov[i].iov_base; @@ compat/writev.c (new) + } + +out: -+ return cast_size_t_to_ssize_t(total_written); ++ return (ssize_t) total_written; +} ## config.mak.uname ## 6: e3525cd25e = 6: 0a90ab2f62 wrapper: introduce writev(3p) wrappers 7: fe07f2d331 = 7: 5e29cfbf10 sideband: use writev(3p) to send pktlines 8: 4563ad923f = 8: 32b59d5f29 csum-file: introduce `hashfd_ext()` 9: 549b3dbefc = 9: a5b0eb3627 csum-file: drop `hashfd_throughput()` 10: 155f79b128 = 10: a82959772e builtin/pack-objects: reduce lock contention when writing packfile data --- base-commit: fb1b83bcddff60463f6e86bb021784c88d0b748c change-id: 20260227-pks-upload-pack-write-contention-435ce01f5fe9