summaryrefslogtreecommitdiff
path: root/tag.c
diff options
context:
space:
mode:
authorNicolas Pitre <nico@cam.org>2005-05-06 17:48:34 (GMT)
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-05-06 18:02:01 (GMT)
commitbd2c39f58f915af532b488c5bda753314f0db603 (patch)
tree8c1e85a4af5d77cff94fc2703c271bbfc512778e /tag.c
parentf4f21ce367a5119be1c4396d01271ece6e40ff70 (diff)
downloadgit-bd2c39f58f915af532b488c5bda753314f0db603.zip
git-bd2c39f58f915af532b488c5bda753314f0db603.tar.gz
git-bd2c39f58f915af532b488c5bda753314f0db603.tar.bz2
[PATCH] don't load and decompress objects twice with parse_object()
It turns out that parse_object() is loading and decompressing given object to free it just before calling the specific object parsing function which does mmap and decompress the same object again. This patch introduces the ability to parse specific objects directly from a memory buffer. Without this patch, running git-fsck-cache on the kernel repositorytake: real 0m13.006s user 0m11.421s sys 0m1.218s With this patch applied: real 0m8.060s user 0m7.071s sys 0m0.710s The performance increase is significant, and this is kind of a prerequisite for sane delta object support with fsck. Signed-off-by: Nicolas Pitre <nico@cam.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'tag.c')
-rw-r--r--tag.c50
1 files changed, 28 insertions, 22 deletions
diff --git a/tag.c b/tag.c
index 3a71dd4..22deb24 100644
--- a/tag.c
+++ b/tag.c
@@ -21,11 +21,8 @@ struct tag *lookup_tag(unsigned char *sha1)
return (struct tag *) obj;
}
-int parse_tag(struct tag *item)
+int parse_tag_buffer(struct tag *item, void *data, unsigned long size)
{
- char type[20];
- void *data, *bufptr;
- unsigned long size;
int typelen, taglen;
unsigned char object[20];
const char *type_line, *tag_line, *sig_line;
@@ -33,20 +30,11 @@ int parse_tag(struct tag *item)
if (item->object.parsed)
return 0;
item->object.parsed = 1;
- data = bufptr = read_sha1_file(item->object.sha1, type, &size);
- if (!data)
- return error("Could not read %s",
- sha1_to_hex(item->object.sha1));
- if (strcmp(type, tag_type)) {
- free(data);
- return error("Object %s not a tag",
- sha1_to_hex(item->object.sha1));
- }
if (size < 64)
- goto err;
+ return -1;
if (memcmp("object ", data, 7) || get_sha1_hex(data + 7, object))
- goto err;
+ return -1;
item->tagged = parse_object(object);
if (item->tagged)
@@ -54,29 +42,47 @@ int parse_tag(struct tag *item)
type_line = data + 48;
if (memcmp("\ntype ", type_line-1, 6))
- goto err;
+ return -1;
tag_line = strchr(type_line, '\n');
if (!tag_line || memcmp("tag ", ++tag_line, 4))
- goto err;
+ return -1;
sig_line = strchr(tag_line, '\n');
if (!sig_line)
- goto err;
+ return -1;
sig_line++;
typelen = tag_line - type_line - strlen("type \n");
if (typelen >= 20)
- goto err;
+ return -1;
taglen = sig_line - tag_line - strlen("tag \n");
item->tag = xmalloc(taglen + 1);
memcpy(item->tag, tag_line + 4, taglen);
item->tag[taglen] = '\0';
- free(data);
return 0;
+}
-err:
+int parse_tag(struct tag *item)
+{
+ char type[20];
+ void *data;
+ unsigned long size;
+ int ret;
+
+ if (item->object.parsed)
+ return 0;
+ data = read_sha1_file(item->object.sha1, type, &size);
+ if (!data)
+ return error("Could not read %s",
+ sha1_to_hex(item->object.sha1));
+ if (strcmp(type, tag_type)) {
+ free(data);
+ return error("Object %s not a tag",
+ sha1_to_hex(item->object.sha1));
+ }
+ ret = parse_tag_buffer(item, data, size);
free(data);
- return -1;
+ return ret;
}