aboutsummaryrefslogtreecommitdiff
path: root/strbuf.c
diff options
context:
space:
mode:
authorJeff King <peff@peff.net>2015-04-16 04:49:06 -0400
committerJunio C Hamano <gitster@pobox.com>2015-04-16 08:15:04 -0700
commit82912d1de86ae3d7f247bc3b16a81afd01aa31c7 (patch)
treec6aade69d71d0f60f98d7049befb48712d29cf71 /strbuf.c
parentf43cce23adde58d44081e46279c7fd655d4246ec (diff)
downloadgit-82912d1de86ae3d7f247bc3b16a81afd01aa31c7.tar.gz
git-82912d1de86ae3d7f247bc3b16a81afd01aa31c7.tar.xz
strbuf_getwholeline: use getc_unlocked
strbuf_getwholeline calls getc in a tight loop. On modern libc implementations, the stdio code locks the handle for every operation, which means we are paying a significant overhead. We can get around this by locking the handle for the whole loop and using the unlocked variant. Running "git rev-parse refs/heads/does-not-exist" on a repo with an extremely large (1.6GB) packed-refs file went from: real 0m18.900s user 0m18.472s sys 0m0.448s to: real 0m10.953s user 0m10.384s sys 0m0.580s for a wall-clock speedup of 42%. All times are best-of-3, and done on a glibc 2.19 system. Note that we call into strbuf_grow while holding the lock. It's possible for that function to call other stdio functions (e.g., printing to stderr when dying due to malloc error); however, the POSIX.1-2001 definition of flockfile makes it clear that the locks are per-handle, so we are fine unless somebody else tries to read from our same handle. This doesn't ever happen in the current code, and is unlikely to be added in the future (we would have to do something exotic like add a die_routine that tried to read from stdin). Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'strbuf.c')
-rw-r--r--strbuf.c4
1 files changed, 3 insertions, 1 deletions
diff --git a/strbuf.c b/strbuf.c
index 14f337db1..af2bad4b5 100644
--- a/strbuf.c
+++ b/strbuf.c
@@ -443,12 +443,14 @@ int strbuf_getwholeline(struct strbuf *sb, FILE *fp, int term)
return EOF;
strbuf_reset(sb);
- while ((ch = getc(fp)) != EOF) {
+ flockfile(fp);
+ while ((ch = getc_unlocked(fp)) != EOF) {
strbuf_grow(sb, 1);
sb->buf[sb->len++] = ch;
if (ch == term)
break;
}
+ funlockfile(fp);
if (ch == EOF && sb->len == 0)
return EOF;