Skip to content

Commit 4651ece

Browse files
torvaldsJunio C Hamano
authored andcommitted
Switch over tree descriptors to contain a pre-parsed entry
This makes the tree descriptor contain a "struct name_entry" as part of it, and it gets filled in so that it always contains a valid entry. On some benchmarks, it improves performance by up to 15%. That makes tree entry "extract" trivial, and means that we only actually need to decode each tree entry just once: we decode the first one when we initialize the tree descriptor, and each subsequent one when doing "update_tree_entry()". In particular, this means that we don't need to do strlen() both at extract time _and_ at update time. Finally, it also allows more sharing of code (entry_extract(), that wanted a "struct name_entry", just got totally trivial, along with the "tree_entry()" function). Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Junio C Hamano <junkio@cox.net>
1 parent 6fda5e5 commit 4651ece

File tree

2 files changed

+57
-62
lines changed

2 files changed

+57
-62
lines changed

tree-walk.c

Lines changed: 44 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,42 @@
22
#include "tree-walk.h"
33
#include "tree.h"
44

5+
static const char *get_mode(const char *str, unsigned int *modep)
6+
{
7+
unsigned char c;
8+
unsigned int mode = 0;
9+
10+
while ((c = *str++) != ' ') {
11+
if (c < '0' || c > '7')
12+
return NULL;
13+
mode = (mode << 3) + (c - '0');
14+
}
15+
*modep = mode;
16+
return str;
17+
}
18+
19+
static void decode_tree_entry(struct tree_desc *desc, const void *buf, unsigned long size)
20+
{
21+
const char *path;
22+
unsigned int mode, len;
23+
24+
path = get_mode(buf, &mode);
25+
if (!path)
26+
die("corrupt tree file");
27+
len = strlen(path) + 1;
28+
29+
/* Initialize the descriptor entry */
30+
desc->entry.path = path;
31+
desc->entry.mode = mode;
32+
desc->entry.sha1 = (const unsigned char *)(path + len);
33+
}
34+
535
void init_tree_desc(struct tree_desc *desc, const void *buffer, unsigned long size)
636
{
737
desc->buffer = buffer;
838
desc->size = size;
39+
if (size)
40+
decode_tree_entry(desc, buffer, size);
941
}
1042

1143
void *fill_tree_descriptor(struct tree_desc *desc, const unsigned char *sha1)
@@ -36,78 +68,33 @@ static void entry_clear(struct name_entry *a)
3668

3769
static void entry_extract(struct tree_desc *t, struct name_entry *a)
3870
{
39-
a->sha1 = tree_entry_extract(t, &a->path, &a->mode);
71+
*a = t->entry;
4072
}
4173

4274
void update_tree_entry(struct tree_desc *desc)
4375
{
4476
const void *buf = desc->buffer;
77+
const unsigned char *end = desc->entry.sha1 + 20;
4578
unsigned long size = desc->size;
46-
int len = strlen(buf) + 1 + 20;
79+
unsigned long len = end - (const unsigned char *)buf;
4780

4881
if (size < len)
4982
die("corrupt tree file");
50-
desc->buffer = (char *) buf + len;
51-
desc->size = size - len;
52-
}
53-
54-
static const char *get_mode(const char *str, unsigned int *modep)
55-
{
56-
unsigned char c;
57-
unsigned int mode = 0;
58-
59-
while ((c = *str++) != ' ') {
60-
if (c < '0' || c > '7')
61-
return NULL;
62-
mode = (mode << 3) + (c - '0');
63-
}
64-
*modep = mode;
65-
return str;
66-
}
67-
68-
const unsigned char *tree_entry_extract(struct tree_desc *desc, const char **pathp, unsigned int *modep)
69-
{
70-
const void *tree = desc->buffer;
71-
unsigned long size = desc->size;
72-
int len = strlen(tree)+1;
73-
const unsigned char *sha1 = (unsigned char *) tree + len;
74-
const char *path;
75-
unsigned int mode;
76-
77-
path = get_mode(tree, &mode);
78-
if (!path || size < len + 20)
79-
die("corrupt tree file");
80-
*pathp = path;
81-
*modep = canon_mode(mode);
82-
return sha1;
83+
buf = end;
84+
size -= len;
85+
desc->buffer = buf;
86+
desc->size = size;
87+
if (size)
88+
decode_tree_entry(desc, buf, size);
8389
}
8490

8591
int tree_entry(struct tree_desc *desc, struct name_entry *entry)
8692
{
87-
const void *tree = desc->buffer;
88-
const char *path;
89-
unsigned long len, size = desc->size;
90-
91-
if (!size)
93+
if (!desc->size)
9294
return 0;
9395

94-
path = get_mode(tree, &entry->mode);
95-
if (!path)
96-
die("corrupt tree file");
97-
98-
entry->path = path;
99-
len = strlen(path);
100-
101-
path += len + 1;
102-
entry->sha1 = (const unsigned char *) path;
103-
104-
path += 20;
105-
len = path - (char *) tree;
106-
if (len > size)
107-
die("corrupt tree file");
108-
109-
desc->buffer = path;
110-
desc->size = size - len;
96+
*entry = desc->entry;
97+
update_tree_entry(desc);
11198
return 1;
11299
}
113100

tree-walk.h

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,25 @@
11
#ifndef TREE_WALK_H
22
#define TREE_WALK_H
33

4-
struct tree_desc {
5-
const void *buffer;
6-
unsigned int size;
7-
};
8-
94
struct name_entry {
105
const unsigned char *sha1;
116
const char *path;
127
unsigned int mode;
138
};
149

10+
struct tree_desc {
11+
const void *buffer;
12+
struct name_entry entry;
13+
unsigned int size;
14+
};
15+
16+
static inline const unsigned char *tree_entry_extract(struct tree_desc *desc, const char **pathp, unsigned int *modep)
17+
{
18+
*pathp = desc->entry.path;
19+
*modep = canon_mode(desc->entry.mode);
20+
return desc->entry.sha1;
21+
}
22+
1523
static inline int tree_entry_len(const char *name, const unsigned char *sha1)
1624
{
1725
return (char *)sha1 - (char *)name - 1;

0 commit comments

Comments
 (0)