We have to call strbuf_grow anytime we are going to add data to a strbuf. In most cases, it's a noop (since we grow the buffer aggressively), and the cost of the function call and size check is dwarfed by the actual buffer operation. For a tight loop of single-character additions, though, this overhead is noticeable. Furthermore, the single-character case is much easier to check; since the "extra" parameter is 1, we can do it without worrying about overflow. This patch adds a simple inline function for checking single-character growth. For the growth case, it just calls into the regular strbuf_grow(). This is redundant, as strbuf_grow will check again whether we need to grow. But it keeps our inline code simple, and most calls will not need to grow, so it's OK to treat this as a rare "slow path". We apply the new function to strbuf_getwholeline. Running "git rev-parse refs/heads/does-not-exist" on a repo with an extremely large (1.6GB) packed-refs file went from (best-of-3): real 0m10.953s user 0m10.384s sys 0m0.580s to: real 0m8.910s user 0m8.452s sys 0m0.468s for a wall-clock speedup of 18%. Signed-off-by: Jeff King <peff@xxxxxxxx> --- strbuf.c | 2 +- strbuf.h | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/strbuf.c b/strbuf.c index af2bad4..2facd5f 100644 --- a/strbuf.c +++ b/strbuf.c @@ -445,7 +445,7 @@ int strbuf_getwholeline(struct strbuf *sb, FILE *fp, int term) strbuf_reset(sb); flockfile(fp); while ((ch = getc_unlocked(fp)) != EOF) { - strbuf_grow(sb, 1); + strbuf_grow_ch(sb); sb->buf[sb->len++] = ch; if (ch == term) break; diff --git a/strbuf.h b/strbuf.h index 1883494..ef41151 100644 --- a/strbuf.h +++ b/strbuf.h @@ -137,6 +137,15 @@ static inline size_t strbuf_avail(const struct strbuf *sb) */ extern void strbuf_grow(struct strbuf *, size_t); +/* + * An optimized version of strbuf_grow() for a single character. + */ +static inline void strbuf_grow_ch(struct strbuf *sb) +{ + if (!sb->alloc || sb->alloc - 1 <= sb->len) + strbuf_grow(sb, 1); +} + /** * Set the length of the buffer to a given value. This function does *not* * allocate new memory, so you should not perform a `strbuf_setlen()` to a -- 2.4.0.rc0.363.gf9f328b -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html