Only malloc the buffer for fast file copy when needed

This commit is contained in:
Kovid Goyal 2021-11-24 18:20:37 +05:30
parent 732ff7ee58
commit bd21b79959
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
4 changed files with 52 additions and 18 deletions

View File

@ -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)));

View File

@ -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 <structmember.h>
@ -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;
}

View File

@ -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 <sys/sendfile.h>
#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;
}

22
kitty/fast-file-copy.h Normal file
View File

@ -0,0 +1,22 @@
/*
* Copyright (C) 2021 Kovid Goyal <kovid at kovidgoyal.net>
*
* 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);