trace: measure where the time is spent in the index-heavy operations

All the known heavy code blocks are measured (except object database access). This should help identify if an optimization is effective or not. An unoptimized git-status would give something like below: 0.001791141 s: read cache ... 0.004011363 s: preload index 0.000516161 s: refresh index 0.003139257 s: git command: ... 'status' '--porcelain=2' 0.006788129 s: diff-files 0.002090267 s: diff-index 0.001885735 s: initialize name hash 0.032013138 s: read directory 0.051781209 s: git command: './git' 'status' Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Nguyễn Thái Ngọc Duy committed Jan 27, 2018 at 19:27 UTC ca54d9baa4a8e73141d4c963245ee6f09dcc994d
5 files changed +18
diff-lib.c
+4
@@ -92,6 +92,7 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
92 int diff_unmerged_stage = revs->max_count;
93 unsigned ce_option = ((option & DIFF_RACY_IS_MODIFIED)
94 ? CE_MATCH_RACY_IS_DIRTY : 0);
95 + uint64_t start = getnanotime();
96
97 diff_set_mnemonic_prefix(&revs->diffopt, "i/", "w/");
98
@@ -246,6 +247,7 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
247 }
248 diffcore_std(&revs->diffopt);
249 diff_flush(&revs->diffopt);
250 + trace_performance_since(start, "diff-files");
251 return 0;
252 }
253
@@ -512,6 +514,7 @@ static int diff_cache(struct rev_info *revs,
514 int run_diff_index(struct rev_info *revs, int cached)
515 {
516 struct object_array_entry *ent;
517 + uint64_t start = getnanotime();
518
519 ent = revs->pending.objects;
520 if (diff_cache(revs, &ent->item->oid, ent->name, cached))
@@ -521,6 +524,7 @@ int run_diff_index(struct rev_info *revs, int cached)
524 diffcore_fix_diff_index(&revs->diffopt);
525 diffcore_std(&revs->diffopt);
526 diff_flush(&revs->diffopt);
527 + trace_performance_since(start, "diff-index");
528 return 0;
529 }
530
dir.c
+2
@@ -2248,6 +2248,7 @@ int read_directory(struct dir_struct *dir, struct index_state *istate,
2248 const char *path, int len, const struct pathspec *pathspec)
2249 {
2250 struct untracked_cache_dir *untracked;
2251 + uint64_t start = getnanotime();
2252
2253 if (has_symlink_leading_path(path, len))
2254 return dir->nr;
@@ -2286,6 +2287,7 @@ int read_directory(struct dir_struct *dir, struct index_state *istate,
2287 dir->nr = i;
2288 }
2289
2290 + trace_performance_since(start, "read directory %.*s", len, path);
2291 if (dir->untracked) {
2292 static struct trace_key trace_untracked_stats = TRACE_KEY_INIT(UNTRACKED_STATS);
2293 trace_printf_key(&trace_untracked_stats,
name-hash.c
+3
@@ -578,6 +578,8 @@ static void threaded_lazy_init_name_hash(
578
579 static void lazy_init_name_hash(struct index_state *istate)
580 {
581 + uint64_t start = getnanotime();
582 +
583 if (istate->name_hash_initialized)
584 return;
585 hashmap_init(&istate->name_hash, cache_entry_cmp, NULL, istate->cache_nr);
@@ -600,6 +602,7 @@ static void lazy_init_name_hash(struct index_state *istate)
602 }
603
604 istate->name_hash_initialized = 1;
605 + trace_performance_since(start, "initialize name hash");
606 }
607
608 /*
preload-index.c
+2
@@ -78,6 +78,7 @@ static void preload_index(struct index_state *index,
78 {
79 int threads, i, work, offset;
80 struct thread_data data[MAX_PARALLEL];
81 + uint64_t start = getnanotime();
82
83 if (!core_preload_index)
84 return;
@@ -108,6 +109,7 @@ static void preload_index(struct index_state *index,
109 if (pthread_join(p->pthread, NULL))
110 die("unable to join threaded lstat");
111 }
112 + trace_performance_since(start, "preload index");
113 }
114 #endif
115
read-cache.c
+7
@@ -1372,6 +1372,7 @@ int refresh_index(struct index_state *istate, unsigned int flags,
1372 const char *typechange_fmt;
1373 const char *added_fmt;
1374 const char *unmerged_fmt;
1375 + uint64_t start = getnanotime();
1376
1377 modified_fmt = (in_porcelain ? "M\t%s\n" : "%s: needs update\n");
1378 deleted_fmt = (in_porcelain ? "D\t%s\n" : "%s: needs update\n");
@@ -1442,6 +1443,7 @@ int refresh_index(struct index_state *istate, unsigned int flags,
1443
1444 replace_index_entry(istate, i, new);
1445 }
1446 + trace_performance_since(start, "refresh index");
1447 return has_errors;
1448 }
1449
@@ -1873,6 +1875,7 @@ static void freshen_shared_index(char *base_sha1_hex, int warn)
1875
1876 int read_index_from(struct index_state *istate, const char *path)
1877 {
1878 + uint64_t start = getnanotime();
1879 struct split_index *split_index;
1880 int ret;
1881 char *base_sha1_hex;
@@ -1883,6 +1886,7 @@ int read_index_from(struct index_state *istate, const char *path)
1886 return istate->cache_nr;
1887
1888 ret = do_read_index(istate, path, 0);
1889 + trace_performance_since(start, "read cache %s", path);
1890
1891 split_index = istate->split_index;
1892 if (!split_index || is_null_sha1(split_index->base_sha1)) {
@@ -1906,6 +1910,7 @@ int read_index_from(struct index_state *istate, const char *path)
1910 freshen_shared_index(base_sha1_hex, 0);
1911 merge_base_index(istate);
1912 post_read_index_from(istate);
1913 + trace_performance_since(start, "read cache %s", base_path);
1914 return ret;
1915 }
1916
@@ -2234,6 +2239,7 @@ void update_index_if_able(struct index_state *istate, struct lock_file *lockfile
2239 static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
2240 int strip_extensions)
2241 {
2242 + uint64_t start = getnanotime();
2243 int newfd = tempfile->fd;
2244 git_SHA_CTX c;
2245 struct cache_header hdr;
@@ -2374,6 +2380,7 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
2380 return -1;
2381 istate->timestamp.sec = (unsigned int)st.st_mtime;
2382 istate->timestamp.nsec = ST_MTIME_NSEC(st);
2383 + trace_performance_since(start, "write index, changed mask = %x", istate->cache_changed);
2384 return 0;
2385 }
2386