Skip to content

Commit 6aa3085

Browse files
kbleesgitster
authored andcommitted
trace: improve trace performance
The trace API currently rechecks the environment variable and reopens the trace file on every API call. This has the ugly side effect that errors (e.g. file cannot be opened, or the user specified a relative path) are also reported on every call. Performance can be improved by about factor three by remembering the environment state and keeping the file open. Replace the 'const char *key' parameter in the API with a pointer to a 'struct trace_key' that bundles the environment variable name with additional, trace-internal state. Change the call sites of these APIs to use a static 'struct trace_key' instead of a string constant. In trace.c::get_trace_fd(), save and reuse the file descriptor in 'struct trace_key'. Add a 'trace_disable()' API, so that packet_trace() can cleanly disable tracing when it encounters packed data (instead of using unsetenv()). Signed-off-by: Karsten Blees <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 0d04242 commit 6aa3085

File tree

6 files changed

+78
-59
lines changed

6 files changed

+78
-59
lines changed

builtin/receive-pack.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,7 @@ static int update_shallow_ref(struct command *cmd, struct shallow_info *si)
438438
uint32_t mask = 1 << (cmd->index % 32);
439439
int i;
440440

441-
trace_printf_key("GIT_TRACE_SHALLOW",
441+
trace_printf_key(&trace_shallow,
442442
"shallow: update_shallow_ref %s\n", cmd->ref_name);
443443
for (i = 0; i < si->shallow->nr; i++)
444444
if (si->used_shallow[i] &&

commit.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,7 @@ extern void assign_shallow_commits_to_refs(struct shallow_info *info,
235235
int *ref_status);
236236
extern int delayed_reachability_test(struct shallow_info *si, int c);
237237
extern void prune_shallow(int show_only);
238+
extern struct trace_key trace_shallow;
238239

239240
int is_descendant_of(struct commit *, struct commit_list *);
240241
int in_merge_bases(struct commit *, struct commit *);

pkt-line.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
char packet_buffer[LARGE_PACKET_MAX];
55
static const char *packet_trace_prefix = "git";
6-
static const char trace_key[] = "GIT_TRACE_PACKET";
6+
static struct trace_key trace_packet = TRACE_KEY_INIT(PACKET);
77

88
void packet_trace_identity(const char *prog)
99
{
@@ -15,7 +15,7 @@ static void packet_trace(const char *buf, unsigned int len, int write)
1515
int i;
1616
struct strbuf out;
1717

18-
if (!trace_want(trace_key))
18+
if (!trace_want(&trace_packet))
1919
return;
2020

2121
/* +32 is just a guess for header + quoting */
@@ -27,7 +27,7 @@ static void packet_trace(const char *buf, unsigned int len, int write)
2727
if ((len >= 4 && starts_with(buf, "PACK")) ||
2828
(len >= 5 && starts_with(buf+1, "PACK"))) {
2929
strbuf_addstr(&out, "PACK ...");
30-
unsetenv(trace_key);
30+
trace_disable(&trace_packet);
3131
}
3232
else {
3333
/* XXX we should really handle printable utf8 */
@@ -43,7 +43,7 @@ static void packet_trace(const char *buf, unsigned int len, int write)
4343
}
4444

4545
strbuf_addch(&out, '\n');
46-
trace_strbuf(trace_key, &out);
46+
trace_strbuf(&trace_packet, &out);
4747
strbuf_release(&out);
4848
}
4949

shallow.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ void prune_shallow(int show_only)
325325
strbuf_release(&sb);
326326
}
327327

328-
#define TRACE_KEY "GIT_TRACE_SHALLOW"
328+
struct trace_key trace_shallow = TRACE_KEY_INIT(SHALLOW);
329329

330330
/*
331331
* Step 1, split sender shallow commits into "ours" and "theirs"
@@ -334,7 +334,7 @@ void prune_shallow(int show_only)
334334
void prepare_shallow_info(struct shallow_info *info, struct sha1_array *sa)
335335
{
336336
int i;
337-
trace_printf_key(TRACE_KEY, "shallow: prepare_shallow_info\n");
337+
trace_printf_key(&trace_shallow, "shallow: prepare_shallow_info\n");
338338
memset(info, 0, sizeof(*info));
339339
info->shallow = sa;
340340
if (!sa)
@@ -365,7 +365,7 @@ void remove_nonexistent_theirs_shallow(struct shallow_info *info)
365365
{
366366
unsigned char (*sha1)[20] = info->shallow->sha1;
367367
int i, dst;
368-
trace_printf_key(TRACE_KEY, "shallow: remove_nonexistent_theirs_shallow\n");
368+
trace_printf_key(&trace_shallow, "shallow: remove_nonexistent_theirs_shallow\n");
369369
for (i = dst = 0; i < info->nr_theirs; i++) {
370370
if (i != dst)
371371
info->theirs[dst] = info->theirs[i];
@@ -516,7 +516,7 @@ void assign_shallow_commits_to_refs(struct shallow_info *info,
516516
int *shallow, nr_shallow = 0;
517517
struct paint_info pi;
518518

519-
trace_printf_key(TRACE_KEY, "shallow: assign_shallow_commits_to_refs\n");
519+
trace_printf_key(&trace_shallow, "shallow: assign_shallow_commits_to_refs\n");
520520
shallow = xmalloc(sizeof(*shallow) * (info->nr_ours + info->nr_theirs));
521521
for (i = 0; i < info->nr_ours; i++)
522522
shallow[nr_shallow++] = info->ours[i];
@@ -622,7 +622,7 @@ static void post_assign_shallow(struct shallow_info *info,
622622
int bitmap_nr = (info->ref->nr + 31) / 32;
623623
struct commit_array ca;
624624

625-
trace_printf_key(TRACE_KEY, "shallow: post_assign_shallow\n");
625+
trace_printf_key(&trace_shallow, "shallow: post_assign_shallow\n");
626626
if (ref_status)
627627
memset(ref_status, 0, sizeof(*ref_status) * info->ref->nr);
628628

trace.c

Lines changed: 54 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -26,43 +26,66 @@
2626
#include "quote.h"
2727

2828
/* Get a trace file descriptor from "key" env variable. */
29-
static int get_trace_fd(const char *key, int *need_close)
29+
static int get_trace_fd(struct trace_key *key)
3030
{
31-
char *trace = getenv(key);
31+
static struct trace_key trace_default = { "GIT_TRACE" };
32+
const char *trace;
33+
34+
/* use default "GIT_TRACE" if NULL */
35+
if (!key)
36+
key = &trace_default;
37+
38+
/* don't open twice */
39+
if (key->initialized)
40+
return key->fd;
41+
42+
trace = getenv(key->key);
3243

3344
if (!trace || !strcmp(trace, "") ||
3445
!strcmp(trace, "0") || !strcasecmp(trace, "false"))
35-
return 0;
36-
if (!strcmp(trace, "1") || !strcasecmp(trace, "true"))
37-
return STDERR_FILENO;
38-
if (strlen(trace) == 1 && isdigit(*trace))
39-
return atoi(trace);
40-
if (is_absolute_path(trace)) {
46+
key->fd = 0;
47+
else if (!strcmp(trace, "1") || !strcasecmp(trace, "true"))
48+
key->fd = STDERR_FILENO;
49+
else if (strlen(trace) == 1 && isdigit(*trace))
50+
key->fd = atoi(trace);
51+
else if (is_absolute_path(trace)) {
4152
int fd = open(trace, O_WRONLY | O_APPEND | O_CREAT, 0666);
4253
if (fd == -1) {
4354
fprintf(stderr,
4455
"Could not open '%s' for tracing: %s\n"
4556
"Defaulting to tracing on stderr...\n",
4657
trace, strerror(errno));
47-
return STDERR_FILENO;
58+
key->fd = STDERR_FILENO;
59+
} else {
60+
key->fd = fd;
61+
key->need_close = 1;
4862
}
49-
*need_close = 1;
50-
return fd;
63+
} else {
64+
fprintf(stderr, "What does '%s' for %s mean?\n"
65+
"If you want to trace into a file, then please set "
66+
"%s to an absolute pathname (starting with /).\n"
67+
"Defaulting to tracing on stderr...\n",
68+
trace, key->key, key->key);
69+
key->fd = STDERR_FILENO;
5170
}
5271

53-
fprintf(stderr, "What does '%s' for %s mean?\n", trace, key);
54-
fprintf(stderr, "If you want to trace into a file, "
55-
"then please set %s to an absolute pathname "
56-
"(starting with /).\n", key);
57-
fprintf(stderr, "Defaulting to tracing on stderr...\n");
72+
key->initialized = 1;
73+
return key->fd;
74+
}
5875

59-
return STDERR_FILENO;
76+
void trace_disable(struct trace_key *key)
77+
{
78+
if (key->need_close)
79+
close(key->fd);
80+
key->fd = 0;
81+
key->initialized = 1;
82+
key->need_close = 0;
6083
}
6184

6285
static const char err_msg[] = "Could not trace into fd given by "
6386
"GIT_TRACE environment variable";
6487

65-
static void trace_vprintf(const char *key, const char *format, va_list ap)
88+
static void trace_vprintf(struct trace_key *key, const char *format, va_list ap)
6689
{
6790
struct strbuf buf = STRBUF_INIT;
6891

@@ -75,7 +98,7 @@ static void trace_vprintf(const char *key, const char *format, va_list ap)
7598
strbuf_release(&buf);
7699
}
77100

78-
void trace_printf_key(const char *key, const char *format, ...)
101+
void trace_printf_key(struct trace_key *key, const char *format, ...)
79102
{
80103
va_list ap;
81104
va_start(ap, format);
@@ -87,31 +110,24 @@ void trace_printf(const char *format, ...)
87110
{
88111
va_list ap;
89112
va_start(ap, format);
90-
trace_vprintf("GIT_TRACE", format, ap);
113+
trace_vprintf(NULL, format, ap);
91114
va_end(ap);
92115
}
93116

94-
void trace_strbuf(const char *key, const struct strbuf *buf)
117+
void trace_strbuf(struct trace_key *key, const struct strbuf *buf)
95118
{
96-
int fd, need_close = 0;
97-
98-
fd = get_trace_fd(key, &need_close);
119+
int fd = get_trace_fd(key);
99120
if (!fd)
100121
return;
101122

102123
write_or_whine_pipe(fd, buf->buf, buf->len, err_msg);
103-
104-
if (need_close)
105-
close(fd);
106124
}
107125

108126
void trace_argv_printf(const char **argv, const char *format, ...)
109127
{
110128
struct strbuf buf = STRBUF_INIT;
111129
va_list ap;
112-
int fd, need_close = 0;
113-
114-
fd = get_trace_fd("GIT_TRACE", &need_close);
130+
int fd = get_trace_fd(NULL);
115131
if (!fd)
116132
return;
117133

@@ -124,9 +140,6 @@ void trace_argv_printf(const char **argv, const char *format, ...)
124140
strbuf_addch(&buf, '\n');
125141
write_or_whine_pipe(fd, buf.buf, buf.len, err_msg);
126142
strbuf_release(&buf);
127-
128-
if (need_close)
129-
close(fd);
130143
}
131144

132145
static const char *quote_crnl(const char *path)
@@ -155,11 +168,11 @@ static const char *quote_crnl(const char *path)
155168
/* FIXME: move prefix to startup_info struct and get rid of this arg */
156169
void trace_repo_setup(const char *prefix)
157170
{
158-
static const char *key = "GIT_TRACE_SETUP";
171+
static struct trace_key key = TRACE_KEY_INIT(SETUP);
159172
const char *git_work_tree;
160173
char cwd[PATH_MAX];
161174

162-
if (!trace_want(key))
175+
if (!trace_want(&key))
163176
return;
164177

165178
if (!getcwd(cwd, PATH_MAX))
@@ -171,18 +184,13 @@ void trace_repo_setup(const char *prefix)
171184
if (!prefix)
172185
prefix = "(null)";
173186

174-
trace_printf_key(key, "setup: git_dir: %s\n", quote_crnl(get_git_dir()));
175-
trace_printf_key(key, "setup: worktree: %s\n", quote_crnl(git_work_tree));
176-
trace_printf_key(key, "setup: cwd: %s\n", quote_crnl(cwd));
177-
trace_printf_key(key, "setup: prefix: %s\n", quote_crnl(prefix));
187+
trace_printf_key(&key, "setup: git_dir: %s\n", quote_crnl(get_git_dir()));
188+
trace_printf_key(&key, "setup: worktree: %s\n", quote_crnl(git_work_tree));
189+
trace_printf_key(&key, "setup: cwd: %s\n", quote_crnl(cwd));
190+
trace_printf_key(&key, "setup: prefix: %s\n", quote_crnl(prefix));
178191
}
179192

180-
int trace_want(const char *key)
193+
int trace_want(struct trace_key *key)
181194
{
182-
const char *trace = getenv(key);
183-
184-
if (!trace || !strcmp(trace, "") ||
185-
!strcmp(trace, "0") || !strcasecmp(trace, "false"))
186-
return 0;
187-
return 1;
195+
return !!get_trace_fd(key);
188196
}

trace.h

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,24 @@
44
#include "git-compat-util.h"
55
#include "strbuf.h"
66

7+
struct trace_key {
8+
const char * const key;
9+
int fd;
10+
unsigned int initialized : 1;
11+
unsigned int need_close : 1;
12+
};
13+
14+
#define TRACE_KEY_INIT(name) { "GIT_TRACE_" #name, 0, 0, 0 }
15+
716
__attribute__((format (printf, 1, 2)))
817
extern void trace_printf(const char *format, ...);
918
__attribute__((format (printf, 2, 3)))
1019
extern void trace_argv_printf(const char **argv, const char *format, ...);
1120
extern void trace_repo_setup(const char *prefix);
12-
extern int trace_want(const char *key);
21+
extern int trace_want(struct trace_key *key);
22+
extern void trace_disable(struct trace_key *key);
1323
__attribute__((format (printf, 2, 3)))
14-
extern void trace_printf_key(const char *key, const char *format, ...);
15-
extern void trace_strbuf(const char *key, const struct strbuf *buf);
24+
extern void trace_printf_key(struct trace_key *key, const char *format, ...);
25+
extern void trace_strbuf(struct trace_key *key, const struct strbuf *buf);
1626

1727
#endif /* TRACE_H */

0 commit comments

Comments
 (0)