Skip to content

Commit 7291699

Browse files
peffgitster
authored andcommitted
ref-filter: avoid extra copies of payload/signature
When we know we're going to show the subject or body of a tag or commit, we call find_subpos(), which returns pointers and lengths for the three parts: subject, body, signature. Oddly, the function finds the signature twice: once by calling parse_signature() at the start, which copies the signature into a separate strbuf, and then again by calling parse_signed_buffer() after we've parsed past the subject. This is due to 482c119 (gpg-interface: improve interface for parsing tags, 2021-02-11) and 88bce0e (ref-filter: hoist signature parsing, 2021-02-11). The idea is that in a multi-hash world, tag signatures may appear in the header, rather than at the end of the body, in which case we need to extract them into a separate buffer. But parse_signature() would never find such a buffer! It only looks for signature lines (like "-----BEGIN PGP") at the start of each line, without any header keyword. So this code will never find anything except the usual in-body signature. And the extra code has two downsides: 1. We spend time copying the payload and signature into strbufs. That might even be useful if we ended up with a NUL-terminated copy of the payload data, but we throw it away immediately. And the signature, since it comes at the end of the message, is already its own NUL-terminated buffer. The overhead isn't huge, but I measured a pretty consistent 1-2% speedup running "git for-each-ref --format='%(subject)'" with this patch on a clone of linux.git. 2. The output of find_subpos() is a set of three ptr/len combinations, but only two of them point into the original buffer. This makes the interface confusing: you can't do pointer comparisons between them, and you have to remember to free the signature buffer. Since there's only one caller, it's not too bad in practice, but it did bite me while working on the next patch (and simplifying it will pave the way for that). In the long run we might have to go back to something like this approach, if we do have multi-hash header signatures. But I would argue that the extra buffer should kick in only for a header signature, and be passed out of find_subpos() separately. Signed-off-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 87fbddd commit 7291699

File tree

1 file changed

+3
-8
lines changed

1 file changed

+3
-8
lines changed

ref-filter.c

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1833,16 +1833,10 @@ static void find_subpos(const char *buf,
18331833
size_t *nonsiglen,
18341834
const char **sig, size_t *siglen)
18351835
{
1836-
struct strbuf payload = STRBUF_INIT;
1837-
struct strbuf signature = STRBUF_INIT;
18381836
const char *eol;
18391837
const char *end = buf + strlen(buf);
18401838
const char *sigstart;
18411839

1842-
/* parse signature first; we might not even have a subject line */
1843-
parse_signature(buf, end - buf, &payload, &signature);
1844-
strbuf_release(&payload);
1845-
18461840
/* skip past header until we hit empty line */
18471841
while (*buf && *buf != '\n') {
18481842
eol = strchrnul(buf, '\n');
@@ -1853,8 +1847,10 @@ static void find_subpos(const char *buf,
18531847
/* skip any empty lines */
18541848
while (*buf == '\n')
18551849
buf++;
1856-
*sig = strbuf_detach(&signature, siglen);
1850+
/* parse signature first; we might not even have a subject line */
18571851
sigstart = buf + parse_signed_buffer(buf, strlen(buf));
1852+
*sig = sigstart;
1853+
*siglen = end - *sig;
18581854

18591855
/* subject is first non-empty line */
18601856
*sub = buf;
@@ -2021,7 +2017,6 @@ static void grab_sub_body_contents(struct atom_value *val, int deref, struct exp
20212017
v->s = xstrdup(subpos);
20222018

20232019
}
2024-
free((void *)sigpos);
20252020
}
20262021

20272022
/*

0 commit comments

Comments
 (0)