about summary refs log tree commit diff
path: root/overlays
diff options
context:
space:
mode:
authorAlyssa Ross <hi@alyssa.is>2021-08-08 17:28:53 +0000
committerAlyssa Ross <hi@alyssa.is>2021-08-08 17:30:27 +0000
commit511f215488d597b04b7c1b5fe72eb2dc8c34f15f (patch)
tree3b53013971e9608c82775be2914e58843660b410 /overlays
parent7562409d98eb08b06cae0c5c6d5478507cefc8e0 (diff)
downloadnixlib-511f215488d597b04b7c1b5fe72eb2dc8c34f15f.tar
nixlib-511f215488d597b04b7c1b5fe72eb2dc8c34f15f.tar.gz
nixlib-511f215488d597b04b7c1b5fe72eb2dc8c34f15f.tar.bz2
nixlib-511f215488d597b04b7c1b5fe72eb2dc8c34f15f.tar.lz
nixlib-511f215488d597b04b7c1b5fe72eb2dc8c34f15f.tar.xz
nixlib-511f215488d597b04b7c1b5fe72eb2dc8c34f15f.tar.zst
nixlib-511f215488d597b04b7c1b5fe72eb2dc8c34f15f.zip
patches/cgit: use buffered stdio
Diffstat (limited to 'overlays')
-rw-r--r--overlays/patches/cgit/default.nix1
-rw-r--r--overlays/patches/cgit/use-buffered-stdio.patch161
2 files changed, 162 insertions, 0 deletions
diff --git a/overlays/patches/cgit/default.nix b/overlays/patches/cgit/default.nix
index 7d90da12d125..201fc79c78fc 100644
--- a/overlays/patches/cgit/default.nix
+++ b/overlays/patches/cgit/default.nix
@@ -31,5 +31,6 @@ cgit.overrideAttrs ({ patches ? [], ... }: {
       url = "https://git.causal.agency/cgit/patch/?id=e65d3eb446294520e2aee50966e5070661d09671";
       sha256 = "0wvckndjmxar3vgqdc3jdnpzy0xgrdlqgfaasixl3x87sdnf4kg7";
     })
+    ./use-buffered-stdio.patch
   ];
 })
diff --git a/overlays/patches/cgit/use-buffered-stdio.patch b/overlays/patches/cgit/use-buffered-stdio.patch
new file mode 100644
index 000000000000..4fa5db70edd9
--- /dev/null
+++ b/overlays/patches/cgit/use-buffered-stdio.patch
@@ -0,0 +1,161 @@
+From 98237819a417bf81a393b893e84c76ddb6dd36f5 Mon Sep 17 00:00:00 2001
+From: Eric Wong <e@80x24.org>
+Date: Fri, 19 Mar 2021 20:38:22 +0000
+Subject: [PATCH] use buffered stdio
+
+Our generation of HTML triggers many small write(2) syscalls
+which is inefficient.
+
+Time output on a horrible query against my git.git mirror
+shows significant performance improvement:
+
+QUERY_STRING='id=2b93bfac0f5bcabbf60f174f4e7bfa9e318e64d5&id2=d6da71a9d16b8cf27f9d8f90692d3625c849cbc8'
+PATH_INFO=/mirrors/git.git/diff
+export QUERY_STRING PATH_INFO
+time ./cgit >/dev/null
+
+Before:
+real    0m1.585s
+user    0m0.904s
+sys     0m0.658s
+
+After:
+real    0m0.750s
+user    0m0.666s
+sys     0m0.076s
+
+Signed-off-by: Eric Wong <e@80x24.org>
+Message-Id: <20210319203822.GA30217@dcvr>
+---
+ cache.c       |  7 +++++++
+ cgit.c        |  2 +-
+ filter.c      | 22 +++++++++++++++++++++-
+ html.c        |  2 +-
+ ui-snapshot.c |  3 +++
+ 5 files changed, 33 insertions(+), 3 deletions(-)
+
+diff --git a/cache.c b/cache.c
+index 2c70be78..580c0e80 100644
+--- a/cache.c
++++ b/cache.c
+@@ -265,6 +265,13 @@ static int process_slot(struct cache_slot *slot)
+ {
+ 	int err;
+ 
++	/*
++	 * Make sure any buffered data is flushed before we redirect,
++	 * do sendfile(2) or write(2)
++	 */
++	if (fflush(stdout))
++		return errno;
++
+ 	err = open_slot(slot);
+ 	if (!err && slot->match) {
+ 		if (is_expired(slot)) {
+diff --git a/cgit.c b/cgit.c
+index c4320f04..d8ea2212 100644
+--- a/cgit.c
++++ b/cgit.c
+@@ -674,7 +674,7 @@ static inline void authenticate_post(void)
+ 		len = MAX_AUTHENTICATION_POST_BYTES;
+ 	if ((len = read(STDIN_FILENO, buffer, len)) < 0)
+ 		die_errno("Could not read POST from stdin");
+-	if (write(STDOUT_FILENO, buffer, len) < 0)
++	if (fwrite(buffer, 1, len, stdout) < len)
+ 		die_errno("Could not write POST to stdout");
+ 	cgit_close_filter(ctx.cfg.auth_filter);
+ 	exit(0);
+diff --git a/filter.c b/filter.c
+index 70f5b749..fba26aa0 100644
+--- a/filter.c
++++ b/filter.c
+@@ -48,6 +48,7 @@ static int open_exec_filter(struct cgit_filter *base, va_list ap)
+ 	for (i = 0; i < filter->base.argument_count; i++)
+ 		filter->argv[i + 1] = va_arg(ap, char *);
+ 
++	chk_zero(fflush(stdout), "unable to flush STDOUT");
+ 	filter->old_stdout = chk_positive(dup(STDOUT_FILENO),
+ 		"Unable to duplicate STDOUT");
+ 	chk_zero(pipe(pipe_fh), "Unable to create pipe to subprocess");
+@@ -71,6 +72,7 @@ static int close_exec_filter(struct cgit_filter *base)
+ 	struct cgit_exec_filter *filter = (struct cgit_exec_filter *)base;
+ 	int i, exit_status = 0;
+ 
++	chk_zero(fflush(stdout), "unable to flush STDOUT");
+ 	chk_non_negative(dup2(filter->old_stdout, STDOUT_FILENO),
+ 		"Unable to restore STDOUT");
+ 	close(filter->old_stdout);
+@@ -143,17 +145,32 @@ void cgit_init_filters(void)
+ #endif
+ 
+ #ifndef NO_LUA
+-static ssize_t (*libc_write)(int fd, const void *buf, size_t count);
++static size_t (*libc_fwrite)(const void *buf, size_t size, size_t n, FILE *);
++static ssize_t (*libc_write)(int fd, const void *buf, size_t size);
+ static ssize_t (*filter_write)(struct cgit_filter *base, const void *buf, size_t count) = NULL;
+ static struct cgit_filter *current_write_filter = NULL;
+ 
+ void cgit_init_filters(void)
+ {
++	/*
++	 * we need to wrap both functions since the Lua filter may
++	 * have code which calls write(2) directly, bypassing fwrite(3)
++	 */
++	libc_fwrite = dlsym(RTLD_NEXT, "fwrite");
++	if (!libc_fwrite)
++		die("Could not locate libc's write function");
+ 	libc_write = dlsym(RTLD_NEXT, "write");
+ 	if (!libc_write)
+ 		die("Could not locate libc's write function");
+ }
+ 
++size_t fwrite(const void *buf, size_t size, size_t n, FILE *f)
++{
++	if (f != stdout || !filter_write)
++		return libc_fwrite(buf, size, n, f);
++	return filter_write(current_write_filter, buf, size * n);
++}
++
+ ssize_t write(int fd, const void *buf, size_t count)
+ {
+ 	if (fd != STDOUT_FILENO || !filter_write)
+@@ -305,6 +322,9 @@ static int open_lua_filter(struct cgit_filter *base, va_list ap)
+ 	struct lua_filter *filter = (struct lua_filter *)base;
+ 	int i;
+ 
++	if (fflush(stdout))
++		return 1;
++
+ 	if (init_lua_filter(filter))
+ 		return 1;
+ 
+diff --git a/html.c b/html.c
+index 138c649e..ca9db91d 100644
+--- a/html.c
++++ b/html.c
+@@ -80,7 +80,7 @@ char *fmtalloc(const char *format, ...)
+ 
+ void html_raw(const char *data, size_t size)
+ {
+-	if (write(STDOUT_FILENO, data, size) != size)
++	if (fwrite(data, 1, size, stdout) != size)
+ 		die_errno("write error on html output");
+ }
+ 
+diff --git a/ui-snapshot.c b/ui-snapshot.c
+index 556d3ed4..8b81e374 100644
+--- a/ui-snapshot.c
++++ b/ui-snapshot.c
+@@ -37,6 +37,9 @@ static int write_archive_type(const char *format, const char *hex, const char *p
+ 	/* argv_array guarantees a trailing NULL entry. */
+ 	memcpy(nargv, argv.argv, sizeof(char *) * (argv.argc + 1));
+ 
++	if (fflush(stdout))
++		return errno;
++
+ 	result = write_archive(argv.argc, nargv, NULL, the_repository, NULL, 0);
+ 	argv_array_clear(&argv);
+ 	free(nargv);
+-- 
+2.32.0
+