From bd21b79959fb8744682f52e25169ba0e9dab3bbf Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 24 Nov 2021 18:20:37 +0530 Subject: [PATCH] Only malloc the buffer for fast file copy when needed --- kitty/data-types.h | 1 - kitty/disk-cache.c | 10 +++------- kitty/fast-file-copy.c | 37 +++++++++++++++++++++++++++---------- kitty/fast-file-copy.h | 22 ++++++++++++++++++++++ 4 files changed, 52 insertions(+), 18 deletions(-) create mode 100644 kitty/fast-file-copy.h diff --git a/kitty/data-types.h b/kitty/data-types.h index 6e877af45..e6bcda186 100644 --- a/kitty/data-types.h +++ b/kitty/data-types.h @@ -368,5 +368,4 @@ void play_canberra_sound(const char *which_sound, const char *event_id, bool is_ SPRITE_MAP_HANDLE alloc_sprite_map(unsigned int, unsigned int); SPRITE_MAP_HANDLE free_sprite_map(SPRITE_MAP_HANDLE); const char* get_hyperlink_for_id(const HYPERLINK_POOL_HANDLE, hyperlink_id_type id, bool only_url); -bool copy_between_files(int infd, int outfd, off_t in_pos, size_t len, uint8_t *buf, size_t bufsz); void log_event(const char *format, ...) __attribute__((format(printf, 1, 2))); diff --git a/kitty/disk-cache.c b/kitty/disk-cache.c index 099c70104..d1bdc56cf 100644 --- a/kitty/disk-cache.c +++ b/kitty/disk-cache.c @@ -11,6 +11,7 @@ #include "safe-wrappers.h" #include "kitty-uthash.h" #include "loop-utils.h" +#include "fast-file-copy.h" #include "threading.h" #include "cross-platform-random.h" #include @@ -132,8 +133,7 @@ static void defrag(DiskCache *self) { int new_cache_file = -1; FREE_AFTER_FUNCTION DefragEntry *defrag_entries = NULL; - FREE_AFTER_FUNCTION uint8_t *buf = NULL; - const size_t bufsz = 1024 * 1024; + AutoFreeFastFileCopyBuffer fcb = {0}; bool lock_released = false, ok = false; off_t size_on_disk = size_of_cache_file(self); @@ -164,17 +164,13 @@ defrag(DiskCache *self) { goto cleanup; } lseek(new_cache_file, 0, SEEK_SET); -#ifndef HAS_SENDFILE - buf = malloc(bufsz); - if (!buf) goto cleanup; -#endif mutex(unlock); lock_released = true; off_t current_pos = 0; for (size_t i = 0; i < num_entries_to_defrag; i++) { DefragEntry *e = defrag_entries + i; - if (!copy_between_files(self->cache_file_fd, new_cache_file, e->old_offset, e->data_sz, buf, bufsz)) { + if (!copy_between_files(self->cache_file_fd, new_cache_file, e->old_offset, e->data_sz, &fcb)) { perror("Failed to copy data to new disk cache file during defrag"); goto cleanup; } diff --git a/kitty/fast-file-copy.c b/kitty/fast-file-copy.c index 9105cdbc5..eabb786a3 100644 --- a/kitty/fast-file-copy.c +++ b/kitty/fast-file-copy.c @@ -5,19 +5,15 @@ * Distributed under terms of the GPL3 license. */ -#include "data-types.h" +#include "fast-file-copy.h" #if __linux__ #define HAS_SENDFILE -#endif - -#ifdef HAS_SENDFILE #include #endif -bool -copy_between_files(int infd, int outfd, off_t in_pos, size_t len, uint8_t *buf, size_t bufsz) { #ifdef HAS_SENDFILE - (void)buf; (void)bufsz; +static bool +copy_with_sendfile(int infd, int outfd, off_t in_pos, size_t len) { unsigned num_of_consecutive_zero_returns = 128; while (len) { off_t r = in_pos; @@ -34,9 +30,19 @@ copy_between_files(int infd, int outfd, off_t in_pos, size_t len, uint8_t *buf, num_of_consecutive_zero_returns = 128; in_pos += n; len -= n; } -#else + return true; +} +#endif + +static inline bool +copy_with_buffer(int infd, int outfd, off_t in_pos, size_t len, FastFileCopyBuffer *fcb) { + if (!fcb->buf) { + fcb->sz = 16 * 1024; + fcb->buf = malloc(fcb->sz); + if (!fcb->buf) return false; + } while (len) { - ssize_t amt_read = pread(infd, buf, MIN(len, bufsz), in_pos); + ssize_t amt_read = pread(infd, fcb->buf, MIN(len, fcb->sz), in_pos); if (amt_read < 0) { if (errno == EINTR || errno == EAGAIN) continue; return false; @@ -47,7 +53,7 @@ copy_between_files(int infd, int outfd, off_t in_pos, size_t len, uint8_t *buf, } len -= amt_read; in_pos += amt_read; - uint8_t *p = buf; + uint8_t *p = fcb->buf; while(amt_read) { ssize_t amt_written = write(outfd, p, amt_read); if (amt_written < 0) { @@ -62,6 +68,17 @@ copy_between_files(int infd, int outfd, off_t in_pos, size_t len, uint8_t *buf, p += amt_written; } } + return true; +#undef bufsz +} + +bool +copy_between_files(int infd, int outfd, off_t in_pos, size_t len, FastFileCopyBuffer *fcb) { +#ifdef HAS_SENDFILE + (void)fcb; + return copy_with_sendfile(infd, outfd, in_pos, len); +#else + return copy_with_buffer(infd, outfd, in_pos, len, fcb); #endif return true; } diff --git a/kitty/fast-file-copy.h b/kitty/fast-file-copy.h new file mode 100644 index 000000000..986d0f64e --- /dev/null +++ b/kitty/fast-file-copy.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2021 Kovid Goyal + * + * Distributed under terms of the GPL3 license. + */ + +#pragma once + +#include "data-types.h" + +typedef struct FastFileCopyBuffer { + uint8_t *buf; + size_t sz; +} FastFileCopyBuffer; + +static inline void +free_fast_file_copy_buffer(FastFileCopyBuffer *fcb) { free(fcb->buf); } + +#define FREE_FCB_AFTER_FUNCTION __attribute__ ((__cleanup__(free_fast_file_copy_buffer))) +#define AutoFreeFastFileCopyBuffer FREE_FCB_AFTER_FUNCTION FastFileCopyBuffer + +bool copy_between_files(int infd, int outfd, off_t in_pos, size_t len, FastFileCopyBuffer *fcb);