json: optimize file write

- Use larger buffer, reducing system call overhead.
- Always write full blocks, minimizing read-before-write.
This commit is contained in:
CismonX 2025-01-15 22:34:38 +08:00
parent d4a370c223
commit 95d6ff6b52
No known key found for this signature in database
GPG key ID: 3094873E29A482FB

View file

@ -40,11 +40,12 @@
#include "prng.h" #include "prng.h"
#include "xstd.h" #include "xstd.h"
#define DUMP_BUFSIZE ( 32 * 1024 )
struct dump_ctx { struct dump_ctx {
int fd; int fd;
char *buf; size_t blksize;
size_t buf_len; size_t data_len;
size_t data_len; char buf[DUMP_BUFSIZE];
}; };
// Forward declaration start // Forward declaration start
@ -61,11 +62,13 @@ dump_cb (
struct dump_ctx *ctx = user_data; struct dump_ctx *ctx = user_data;
size_t new_len = ctx->data_len + buf_len; size_t new_len = ctx->data_len + buf_len;
if (new_len <= ctx->buf_len) { if (new_len <= DUMP_BUFSIZE) {
memcpy(ctx->buf + ctx->data_len, buf, buf_len); memcpy(ctx->buf + ctx->data_len, buf, buf_len);
ctx->data_len = new_len; ctx->data_len = new_len;
return 0; return 0;
} }
new_len %= ctx->blksize;
buf_len -= new_len;
struct iovec bufv[] = { struct iovec bufv[] = {
{ .iov_base = ctx->buf, .iov_len = ctx->data_len }, { .iov_base = ctx->buf, .iov_len = ctx->data_len },
@ -74,7 +77,8 @@ dump_cb (
if (0 != write_iov(ctx->fd, bufv, 2)) { if (0 != write_iov(ctx->fd, bufv, 2)) {
return -1; return -1;
} }
ctx->data_len = 0; memcpy(ctx->buf, buf + buf_len, new_len);
ctx->data_len = new_len;
return 0; return 0;
} }
@ -200,16 +204,19 @@ json_dumpfd_ex (
log_printf("fstat(): %s", xstrerror(errno)); log_printf("fstat(): %s", xstrerror(errno));
return -1; return -1;
} }
int status = -1; size_t blksize = stat_buf.st_blksize;
if (unlikely(blksize == 0 || DUMP_BUFSIZE % blksize != 0)) {
debug_printf("unexpected st_blksize: %zu", blksize);
blksize = DUMP_BUFSIZE;
}
struct dump_ctx ctx = { struct dump_ctx ctx;
.fd = fd, ctx.fd = fd,
.buf = xmalloc(stat_buf.st_blksize), ctx.blksize = blksize,
.buf_len = stat_buf.st_blksize, ctx.data_len = 0;
};
if (0 != json_dump_callback(json, dump_cb, &ctx, flags)) { if (0 != json_dump_callback(json, dump_cb, &ctx, flags)) {
log_puts("json_dump_callback() failed"); log_puts("json_dump_callback() failed");
goto end; return -1;
} }
if (ctx.data_len > 0) { if (ctx.data_len > 0) {
struct iovec buf = { struct iovec buf = {
@ -217,17 +224,13 @@ json_dumpfd_ex (
.iov_len = ctx.data_len, .iov_len = ctx.data_len,
}; };
if (0 != write_iov(fd, &buf, 1)) { if (0 != write_iov(fd, &buf, 1)) {
goto end; return -1;
} }
} }
if (unlikely(0 != xfsync(fd))) { if (unlikely(0 != xfsync(fd))) {
goto end; return -1;
} }
status = 0; return 0;
end:
free(ctx.buf);
return status;
} }
json_t * json_t *