We do know the length of the path name of an tree entry from the tree
dictionary. On an unoptimized build, this cuts down "git rev-list
--objects v1.8.4"'s time from 6.2s to 5.8s. This difference is less on
optimized builds.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclo...@gmail.com>
---
 packv4-parse.c | 23 +++++++++++++++--------
 1 file changed, 15 insertions(+), 8 deletions(-)

diff --git a/packv4-parse.c b/packv4-parse.c
index c00a014..ae3e6a5 100644
--- a/packv4-parse.c
+++ b/packv4-parse.c
@@ -50,15 +50,17 @@ struct packv4_dict *pv4_create_dict(const unsigned char 
*data, int dict_size)
                return NULL;
        }
 
-       dict = xmalloc(sizeof(*dict) + nb_entries * sizeof(dict->offsets[0]));
+       dict = xmalloc(sizeof(*dict) +
+                      (nb_entries + 1) * sizeof(dict->offsets[0]));
        dict->data = data;
        dict->nb_entries = nb_entries;
 
+       dict->offsets[0] = 0;
        cp = data;
        for (i = 0; i < nb_entries; i++) {
-               dict->offsets[i] = cp - data;
                cp += 2;
                cp += strlen((const char *)cp) + 1;
+               dict->offsets[i + 1] = cp - data;
        }
 
        return dict;
@@ -163,7 +165,8 @@ static void load_path_dict(struct packed_git *p)
        p->path_dict = paths;
 }
 
-const unsigned char *get_pathref(struct packed_git *p, unsigned int index)
+const unsigned char *get_pathref(struct packed_git *p, unsigned int index,
+                                int *len)
 {
        if (!p->path_dict)
                load_path_dict(p);
@@ -172,6 +175,9 @@ const unsigned char *get_pathref(struct packed_git *p, 
unsigned int index)
                error("%s: index overflow", __func__);
                return NULL;
        }
+       if (len)
+               *len = p->path_dict->offsets[index + 1] -
+                       p->path_dict->offsets[index];
        return p->path_dict->data + p->path_dict->offsets[index];
 }
 
@@ -373,9 +379,9 @@ static int copy_canonical_tree_entries(struct packed_git 
*p, off_t offset,
 }
 
 static int tree_entry_prefix(unsigned char *buf, unsigned long size,
-                            const unsigned char *path, unsigned mode)
+                            const unsigned char *path, int path_len,
+                            unsigned mode)
 {
-       int path_len = strlen((const char *)path) + 1;
        int mode_len = 0;
        int len;
        unsigned char mode_buf[8];
@@ -463,14 +469,15 @@ static int decode_entries(struct packed_git *p, struct 
pack_window **w_curs,
                         */
                        const unsigned char *path, *sha1;
                        unsigned mode;
-                       int len;
+                       int len, pathlen;
 
-                       path = get_pathref(p, what >> 1);
+                       path = get_pathref(p, what >> 1, &pathlen);
                        sha1 = get_sha1ref(p, &scp);
                        if (!path || !sha1)
                                return -1;
                        mode = (path[0] << 8) | path[1];
-                       len = tree_entry_prefix(*dstp, *sizep, path + 2, mode);
+                       len = tree_entry_prefix(*dstp, *sizep,
+                                               path + 2, pathlen - 2, mode);
                        if (!len || len + 20 > *sizep)
                                return -1;
                        hashcpy(*dstp + len, sha1);
-- 
1.8.2.83.gc99314b

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to