[PATCH v2 00/10] upload-pack: reduce lock contention when writing packfile data
- From
Patrick Steinhardt <ps@pks.im>
- Date
- Mar 3, 2026, 15:00 UTC
- Message-ID
- <20260303-pks-upload-pack-write-contention-v2-0-7321830f08fe@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 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.imThanks!
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: reduce lock contention when writing packfile data
git-compat-util: introduce `cast_size_t_to_ssize_t()`
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 dataMakefile | 4 ++++ builtin/pack-objects.c | 23 +++++++++++++++---- compat/posix.h | 14 ++++++++++++ compat/writev.c | 29 ++++++++++++++++++++++++ config.mak.uname | 2 ++ csum-file.c | 28 +++++++---------------- csum-file.h | 16 ++++++++++++-- git-compat-util.h | 8 +++++++ meson.build | 1 + sideband.c | 14 +++++++++--- upload-pack.c | 60 ++++++++++++++++++++++++++++++++++++++++---------- wrapper.c | 41 ++++++++++++++++++++++++++++++++++ wrapper.h | 9 ++++++++ write-or-die.c | 8 +++++++ write-or-die.h | 1 + 15 files changed, 217 insertions(+), 41 deletions(-)
Range-diff versus v1:
1: 368a984880 = 1: 81c00e3b52 upload-pack: fix debug statement when flushing packfile data
-: ---------- > 2: 01c86a9573 upload-pack: adapt keepalives based on buffering
2: f014e8005a ! 3: 16bc5661d4 upload-pack: reduce lock contention when writing packfile data
@@ Commit message
write(3p) syscalls from 130,000 to 100,000. So overall this doesn't seem
worth it.
+ Note that the issue could also be fixed by adapting the write buffer
+ that we use in the downstream git-pack-objects(1) command, and such a
+ change would have roughly the same result. But the command that
+ generates the packfile data may not always be git-pack-objects(1) as it
+ can be changed via "uploadpack.packObjectsHook", so such a fix would
+ only help in _some_ cases. Regardless of that, we'll also adapt the
+ write buffer size of git-pack-objects(1) in a subsequent commit.
+
Helped-by: Matt Smiley <msmiley@gitlab.com>
Signed-off-by: Patrick Steinhardt <ps@pks.im>
@@ upload-pack.c: static int relay_pack_data(int pack_objects_out, struct output_st
+ * Make sure that we buffer some data before sending it to the client.
+ * This significantly reduces the number of write(3p) syscalls.
+ */
-+ if (readsz && os->used < (LARGE_PACKET_DATA_MAX * 2 / 3))
++ if (readsz && os->used < (sizeof(os->buffer) * 2 / 3))
+ return readsz;
+
if (os->used > 1) {
-: ---------- > 4: f42a8a0558 git-compat-util: introduce `cast_size_t_to_ssize_t()`
-: ---------- > 5: 830c72f588 compat/posix: introduce writev(3p) wrapper
-: ---------- > 6: 733ef129f1 wrapper: introduce writev(3p) wrappers
-: ---------- > 7: 18f7429e14 sideband: use writev(3p) to send pktlines
-: ---------- > 8: 8eb2aee74d csum-file: introduce `hashfd_ext()`
-: ---------- > 9: a634506b81 csum-file: drop `hashfd_throughput()`
-: ---------- > 10: ca6d52b012 builtin/pack-objects: reduce lock contention when writing packfile data--- base-commit: 7b2bccb0d58d4f24705bf985de1f4612e4cf06e5 change-id: 20260227-pks-upload-pack-write-contention-435ce01f5fe9