Skip to content

Commit c2509c5

Browse files
committed
Merge branch 'jv/pkt-line-batch'
Reduce number of write(2) system calls while sending the ref advertisement. * jv/pkt-line-batch: upload-pack: use stdio in send_ref callbacks pkt-line: add stdio packet write functions
2 parents ed8794e + 70afef5 commit c2509c5

File tree

6 files changed

+72
-5
lines changed

6 files changed

+72
-5
lines changed

cache.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1745,6 +1745,8 @@ extern const char *git_mailmap_blob;
17451745
void maybe_flush_or_die(FILE *, const char *);
17461746
__attribute__((format (printf, 2, 3)))
17471747
void fprintf_or_die(FILE *, const char *fmt, ...);
1748+
void fwrite_or_die(FILE *f, const void *buf, size_t count);
1749+
void fflush_or_die(FILE *f);
17481750

17491751
#define COPY_READ_ERROR (-2)
17501752
#define COPY_WRITE_ERROR (-3)

ls-refs.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ static int send_ref(const char *refname, const struct object_id *oid,
107107
}
108108

109109
strbuf_addch(&data->buf, '\n');
110-
packet_write(1, data->buf.buf, data->buf.len);
110+
packet_fwrite(stdout, data->buf.buf, data->buf.len);
111111

112112
return 0;
113113
}
@@ -173,7 +173,7 @@ int ls_refs(struct repository *r, struct strvec *keys,
173173
strvec_push(&data.prefixes, "");
174174
for_each_fullref_in_prefixes(get_git_namespace(), data.prefixes.v,
175175
send_ref, &data, 0);
176-
packet_flush(1);
176+
packet_fflush(stdout);
177177
strvec_clear(&data.prefixes);
178178
strbuf_release(&data.buf);
179179
return 0;

pkt-line.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,43 @@ void packet_write(int fd_out, const char *buf, size_t size)
243243
die("%s", err.buf);
244244
}
245245

246+
void packet_fwrite(FILE *f, const char *buf, size_t size)
247+
{
248+
size_t packet_size;
249+
char header[4];
250+
251+
if (size > LARGE_PACKET_DATA_MAX)
252+
die(_("packet write failed - data exceeds max packet size"));
253+
254+
packet_trace(buf, size, 1);
255+
packet_size = size + 4;
256+
257+
set_packet_header(header, packet_size);
258+
fwrite_or_die(f, header, 4);
259+
fwrite_or_die(f, buf, size);
260+
}
261+
262+
void packet_fwrite_fmt(FILE *fh, const char *fmt, ...)
263+
{
264+
static struct strbuf buf = STRBUF_INIT;
265+
va_list args;
266+
267+
strbuf_reset(&buf);
268+
269+
va_start(args, fmt);
270+
format_packet(&buf, "", fmt, args);
271+
va_end(args);
272+
273+
fwrite_or_die(fh, buf.buf, buf.len);
274+
}
275+
276+
void packet_fflush(FILE *f)
277+
{
278+
packet_trace("0000", 4, 1);
279+
fwrite_or_die(f, "0000", 4);
280+
fflush_or_die(f);
281+
}
282+
246283
void packet_buf_write(struct strbuf *buf, const char *fmt, ...)
247284
{
248285
va_list args;

pkt-line.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,17 @@ int packet_write_fmt_gently(int fd, const char *fmt, ...) __attribute__((format
3535
int write_packetized_from_fd_no_flush(int fd_in, int fd_out);
3636
int write_packetized_from_buf_no_flush(const char *src_in, size_t len, int fd_out);
3737

38+
/*
39+
* Stdio versions of packet_write functions. When mixing these with fd
40+
* based functions, take care to call fflush(3) before doing fd writes or
41+
* closing the fd.
42+
*/
43+
void packet_fwrite(FILE *f, const char *buf, size_t size);
44+
void packet_fwrite_fmt(FILE *f, const char *fmt, ...) __attribute__((format (printf, 2, 3)));
45+
46+
/* packet_fflush writes a flush packet and flushes the stdio buffer of f */
47+
void packet_fflush(FILE *f);
48+
3849
/*
3950
* Read a packetized line into the buffer, which must be at least size bytes
4051
* long. The return value specifies the number of bytes read into the buffer.

upload-pack.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1207,7 +1207,7 @@ static int send_ref(const char *refname, const struct object_id *oid,
12071207

12081208
format_symref_info(&symref_info, &data->symref);
12091209
format_session_id(&session_id, data);
1210-
packet_write_fmt(1, "%s %s%c%s%s%s%s%s%s%s object-format=%s agent=%s\n",
1210+
packet_fwrite_fmt(stdout, "%s %s%c%s%s%s%s%s%s%s object-format=%s agent=%s\n",
12111211
oid_to_hex(oid), refname_nons,
12121212
0, capabilities,
12131213
(data->allow_uor & ALLOW_TIP_SHA1) ?
@@ -1223,11 +1223,11 @@ static int send_ref(const char *refname, const struct object_id *oid,
12231223
strbuf_release(&symref_info);
12241224
strbuf_release(&session_id);
12251225
} else {
1226-
packet_write_fmt(1, "%s %s\n", oid_to_hex(oid), refname_nons);
1226+
packet_fwrite_fmt(stdout, "%s %s\n", oid_to_hex(oid), refname_nons);
12271227
}
12281228
capabilities = NULL;
12291229
if (!peel_iterated_oid(oid, &peeled))
1230-
packet_write_fmt(1, "%s %s^{}\n", oid_to_hex(&peeled), refname_nons);
1230+
packet_fwrite_fmt(stdout, "%s %s^{}\n", oid_to_hex(&peeled), refname_nons);
12311231
return 0;
12321232
}
12331233

@@ -1348,6 +1348,11 @@ void upload_pack(struct upload_pack_options *options)
13481348
reset_timeout(data.timeout);
13491349
head_ref_namespaced(send_ref, &data);
13501350
for_each_namespaced_ref(send_ref, &data);
1351+
/*
1352+
* fflush stdout before calling advertise_shallow_grafts because send_ref
1353+
* uses stdio.
1354+
*/
1355+
fflush_or_die(stdout);
13511356
advertise_shallow_grafts(1);
13521357
packet_flush(1);
13531358
} else {

write-or-die.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,15 @@ void write_or_die(int fd, const void *buf, size_t count)
7070
die_errno("write error");
7171
}
7272
}
73+
74+
void fwrite_or_die(FILE *f, const void *buf, size_t count)
75+
{
76+
if (fwrite(buf, 1, count, f) != count)
77+
die_errno("fwrite error");
78+
}
79+
80+
void fflush_or_die(FILE *f)
81+
{
82+
if (fflush(f))
83+
die_errno("fflush error");
84+
}

0 commit comments

Comments
 (0)