Skip to content

Commit c46c406

Browse files
pcloudsgitster
authored andcommitted
trace.h: support nested performance tracing
Performance measurements are listed right now as a flat list, which is fine when we measure big blocks. But when we start adding more and more measurements, some of them could be just part of a bigger measurement and a flat list gives a wrong impression that they are executed at the same level instead of nested. Add trace_performance_enter() and trace_performance_leave() to allow indent these nested measurements. For now it does not help much because the only nested thing is (lazy) name hash initialization (e.g. called in diff-index from "git status"). This will help more because I'm going to add some more tracing that's actually nested. Signed-off-by: Nguyễn Thái Ngọc Duy <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent fa03cdc commit c46c406

File tree

7 files changed

+96
-20
lines changed

7 files changed

+96
-20
lines changed

diff-lib.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -518,11 +518,11 @@ static int diff_cache(struct rev_info *revs,
518518
int run_diff_index(struct rev_info *revs, int cached)
519519
{
520520
struct object_array_entry *ent;
521-
uint64_t start = getnanotime();
522521

523522
if (revs->pending.nr != 1)
524523
BUG("run_diff_index must be passed exactly one tree");
525524

525+
trace_performance_enter();
526526
ent = revs->pending.objects;
527527
if (diff_cache(revs, &ent->item->oid, ent->name, cached))
528528
exit(128);
@@ -531,7 +531,7 @@ int run_diff_index(struct rev_info *revs, int cached)
531531
diffcore_fix_diff_index(&revs->diffopt);
532532
diffcore_std(&revs->diffopt);
533533
diff_flush(&revs->diffopt);
534-
trace_performance_since(start, "diff-index");
534+
trace_performance_leave("diff-index");
535535
return 0;
536536
}
537537

dir.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2263,10 +2263,13 @@ int read_directory(struct dir_struct *dir, struct index_state *istate,
22632263
const char *path, int len, const struct pathspec *pathspec)
22642264
{
22652265
struct untracked_cache_dir *untracked;
2266-
uint64_t start = getnanotime();
22672266

2268-
if (has_symlink_leading_path(path, len))
2267+
trace_performance_enter();
2268+
2269+
if (has_symlink_leading_path(path, len)) {
2270+
trace_performance_leave("read directory %.*s", len, path);
22692271
return dir->nr;
2272+
}
22702273

22712274
untracked = validate_untracked_cache(dir, len, pathspec);
22722275
if (!untracked)
@@ -2302,7 +2305,7 @@ int read_directory(struct dir_struct *dir, struct index_state *istate,
23022305
dir->nr = i;
23032306
}
23042307

2305-
trace_performance_since(start, "read directory %.*s", len, path);
2308+
trace_performance_leave("read directory %.*s", len, path);
23062309
if (dir->untracked) {
23072310
static int force_untracked_cache = -1;
23082311
static struct trace_key trace_untracked_stats = TRACE_KEY_INIT(UNTRACKED_STATS);

name-hash.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -578,10 +578,10 @@ static void threaded_lazy_init_name_hash(
578578

579579
static void lazy_init_name_hash(struct index_state *istate)
580580
{
581-
uint64_t start = getnanotime();
582581

583582
if (istate->name_hash_initialized)
584583
return;
584+
trace_performance_enter();
585585
hashmap_init(&istate->name_hash, cache_entry_cmp, NULL, istate->cache_nr);
586586
hashmap_init(&istate->dir_hash, dir_entry_cmp, NULL, istate->cache_nr);
587587

@@ -602,7 +602,7 @@ static void lazy_init_name_hash(struct index_state *istate)
602602
}
603603

604604
istate->name_hash_initialized = 1;
605-
trace_performance_since(start, "initialize name hash");
605+
trace_performance_leave("initialize name hash");
606606
}
607607

608608
/*

preload-index.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,6 @@ static void preload_index(struct index_state *index,
7878
{
7979
int threads, i, work, offset;
8080
struct thread_data data[MAX_PARALLEL];
81-
uint64_t start = getnanotime();
8281

8382
if (!core_preload_index)
8483
return;
@@ -88,6 +87,7 @@ static void preload_index(struct index_state *index,
8887
threads = 2;
8988
if (threads < 2)
9089
return;
90+
trace_performance_enter();
9191
if (threads > MAX_PARALLEL)
9292
threads = MAX_PARALLEL;
9393
offset = 0;
@@ -109,7 +109,7 @@ static void preload_index(struct index_state *index,
109109
if (pthread_join(p->pthread, NULL))
110110
die("unable to join threaded lstat");
111111
}
112-
trace_performance_since(start, "preload index");
112+
trace_performance_leave("preload index");
113113
}
114114
#endif
115115

read-cache.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1476,8 +1476,8 @@ int refresh_index(struct index_state *istate, unsigned int flags,
14761476
const char *typechange_fmt;
14771477
const char *added_fmt;
14781478
const char *unmerged_fmt;
1479-
uint64_t start = getnanotime();
14801479

1480+
trace_performance_enter();
14811481
modified_fmt = (in_porcelain ? "M\t%s\n" : "%s: needs update\n");
14821482
deleted_fmt = (in_porcelain ? "D\t%s\n" : "%s: needs update\n");
14831483
typechange_fmt = (in_porcelain ? "T\t%s\n" : "%s needs update\n");
@@ -1547,7 +1547,7 @@ int refresh_index(struct index_state *istate, unsigned int flags,
15471547

15481548
replace_index_entry(istate, i, new_entry);
15491549
}
1550-
trace_performance_since(start, "refresh index");
1550+
trace_performance_leave("refresh index");
15511551
return has_errors;
15521552
}
15531553

@@ -2002,7 +2002,6 @@ static void freshen_shared_index(const char *shared_index, int warn)
20022002
int read_index_from(struct index_state *istate, const char *path,
20032003
const char *gitdir)
20042004
{
2005-
uint64_t start = getnanotime();
20062005
struct split_index *split_index;
20072006
int ret;
20082007
char *base_oid_hex;
@@ -2012,15 +2011,17 @@ int read_index_from(struct index_state *istate, const char *path,
20122011
if (istate->initialized)
20132012
return istate->cache_nr;
20142013

2014+
trace_performance_enter();
20152015
ret = do_read_index(istate, path, 0);
2016-
trace_performance_since(start, "read cache %s", path);
2016+
trace_performance_leave("read cache %s", path);
20172017

20182018
split_index = istate->split_index;
20192019
if (!split_index || is_null_oid(&split_index->base_oid)) {
20202020
post_read_index_from(istate);
20212021
return ret;
20222022
}
20232023

2024+
trace_performance_enter();
20242025
if (split_index->base)
20252026
discard_index(split_index->base);
20262027
else
@@ -2037,8 +2038,8 @@ int read_index_from(struct index_state *istate, const char *path,
20372038
freshen_shared_index(base_path, 0);
20382039
merge_base_index(istate);
20392040
post_read_index_from(istate);
2040-
trace_performance_since(start, "read cache %s", base_path);
20412041
free(base_path);
2042+
trace_performance_leave("read cache %s", base_path);
20422043
return ret;
20432044
}
20442045

trace.c

Lines changed: 63 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -176,10 +176,30 @@ void trace_strbuf_fl(const char *file, int line, struct trace_key *key,
176176
strbuf_release(&buf);
177177
}
178178

179+
static uint64_t perf_start_times[10];
180+
static int perf_indent;
181+
182+
uint64_t trace_performance_enter(void)
183+
{
184+
uint64_t now;
185+
186+
if (!trace_want(&trace_perf_key))
187+
return 0;
188+
189+
now = getnanotime();
190+
perf_start_times[perf_indent] = now;
191+
if (perf_indent + 1 < ARRAY_SIZE(perf_start_times))
192+
perf_indent++;
193+
else
194+
BUG("Too deep indentation");
195+
return now;
196+
}
197+
179198
static void trace_performance_vprintf_fl(const char *file, int line,
180199
uint64_t nanos, const char *format,
181200
va_list ap)
182201
{
202+
static const char space[] = " ";
183203
struct strbuf buf = STRBUF_INIT;
184204

185205
if (!prepare_trace_line(file, line, &trace_perf_key, &buf))
@@ -188,7 +208,10 @@ static void trace_performance_vprintf_fl(const char *file, int line,
188208
strbuf_addf(&buf, "performance: %.9f s", (double) nanos / 1000000000);
189209

190210
if (format && *format) {
191-
strbuf_addstr(&buf, ": ");
211+
if (perf_indent >= strlen(space))
212+
BUG("Too deep indentation");
213+
214+
strbuf_addf(&buf, ":%.*s ", perf_indent, space);
192215
strbuf_vaddf(&buf, format, ap);
193216
}
194217

@@ -244,6 +267,24 @@ void trace_performance_since(uint64_t start, const char *format, ...)
244267
va_end(ap);
245268
}
246269

270+
void trace_performance_leave(const char *format, ...)
271+
{
272+
va_list ap;
273+
uint64_t since;
274+
275+
if (perf_indent)
276+
perf_indent--;
277+
278+
if (!format) /* Allow callers to leave without tracing anything */
279+
return;
280+
281+
since = perf_start_times[perf_indent];
282+
va_start(ap, format);
283+
trace_performance_vprintf_fl(NULL, 0, getnanotime() - since,
284+
format, ap);
285+
va_end(ap);
286+
}
287+
247288
#else
248289

249290
void trace_printf_key_fl(const char *file, int line, struct trace_key *key,
@@ -273,6 +314,24 @@ void trace_performance_fl(const char *file, int line, uint64_t nanos,
273314
va_end(ap);
274315
}
275316

317+
void trace_performance_leave_fl(const char *file, int line,
318+
uint64_t nanos, const char *format, ...)
319+
{
320+
va_list ap;
321+
uint64_t since;
322+
323+
if (perf_indent)
324+
perf_indent--;
325+
326+
if (!format) /* Allow callers to leave without tracing anything */
327+
return;
328+
329+
since = perf_start_times[perf_indent];
330+
va_start(ap, format);
331+
trace_performance_vprintf_fl(file, line, nanos - since, format, ap);
332+
va_end(ap);
333+
}
334+
276335
#endif /* HAVE_VARIADIC_MACROS */
277336

278337

@@ -411,24 +470,22 @@ uint64_t getnanotime(void)
411470
}
412471
}
413472

414-
static uint64_t command_start_time;
415473
static struct strbuf command_line = STRBUF_INIT;
416474

417475
static void print_command_performance_atexit(void)
418476
{
419-
trace_performance_since(command_start_time, "git command:%s",
420-
command_line.buf);
477+
trace_performance_leave("git command:%s", command_line.buf);
421478
}
422479

423480
void trace_command_performance(const char **argv)
424481
{
425482
if (!trace_want(&trace_perf_key))
426483
return;
427484

428-
if (!command_start_time)
485+
if (!command_line.len)
429486
atexit(print_command_performance_atexit);
430487

431488
strbuf_reset(&command_line);
432489
sq_quote_argv_pretty(&command_line, argv);
433-
command_start_time = getnanotime();
490+
trace_performance_enter();
434491
}

trace.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ extern void trace_disable(struct trace_key *key);
2323
extern uint64_t getnanotime(void);
2424
extern void trace_command_performance(const char **argv);
2525
extern void trace_verbatim(struct trace_key *key, const void *buf, unsigned len);
26+
uint64_t trace_performance_enter(void);
2627

2728
#ifndef HAVE_VARIADIC_MACROS
2829

@@ -45,6 +46,9 @@ extern void trace_performance(uint64_t nanos, const char *format, ...);
4546
__attribute__((format (printf, 2, 3)))
4647
extern void trace_performance_since(uint64_t start, const char *format, ...);
4748

49+
__attribute__((format (printf, 1, 2)))
50+
void trace_performance_leave(const char *format, ...);
51+
4852
#else
4953

5054
/*
@@ -118,6 +122,14 @@ extern void trace_performance_since(uint64_t start, const char *format, ...);
118122
__VA_ARGS__); \
119123
} while (0)
120124

125+
#define trace_performance_leave(...) \
126+
do { \
127+
if (trace_pass_fl(&trace_perf_key)) \
128+
trace_performance_leave_fl(TRACE_CONTEXT, __LINE__, \
129+
getnanotime(), \
130+
__VA_ARGS__); \
131+
} while (0)
132+
121133
/* backend functions, use non-*fl macros instead */
122134
__attribute__((format (printf, 4, 5)))
123135
extern void trace_printf_key_fl(const char *file, int line, struct trace_key *key,
@@ -130,6 +142,9 @@ extern void trace_strbuf_fl(const char *file, int line, struct trace_key *key,
130142
__attribute__((format (printf, 4, 5)))
131143
extern void trace_performance_fl(const char *file, int line,
132144
uint64_t nanos, const char *fmt, ...);
145+
__attribute__((format (printf, 4, 5)))
146+
extern void trace_performance_leave_fl(const char *file, int line,
147+
uint64_t nanos, const char *fmt, ...);
133148
static inline int trace_pass_fl(struct trace_key *key)
134149
{
135150
return key->fd || !key->initialized;

0 commit comments

Comments
 (0)