From 3d7ea5b4d4ad27d2fe46d7b875f9c11343b51b14 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Thu, 4 Jan 2024 01:19:23 -0600 Subject: [PATCH] Changed bypassing writes to update buffer with write tail While I'm happy to have figured out the previous range update logic, it is quite complicated, and that translates to code cost. Updating the buffer with the write tail is 1. simpler, and 2. keeps the buffer updated with the most recent relevant data. Relying on the previous bypassing/buffer strategy would have been error prone anyways. The optimization could fall apart the moment you _increase_ the buffer size, and it doesn't extend well to multiple open file handles. The problem with multiple file handles is we don't know what range of bytes have been affected when we broadcast a sync. So we just overwrite all other open file buffers. Fortunately, LFS_O_DESYNC provides an interesting way to avoid this, and optimize in-file readd->writes. Code changes, not really that much in the grand scheme of things. For comparison I included the code cost for unconditionally clearing the buffer during bypassing writes: code stack update overlap: 33356 3072 clear buffer: 33292 (-0.2%) 3072 (+0.0%) overwrite buffer: 33316 (-0.1%) 3072 (+0.0%) --- lfs.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/lfs.c b/lfs.c index 02769499..17de60b8 100644 --- a/lfs.c +++ b/lfs.c @@ -10612,19 +10612,15 @@ lfs_ssize_t lfsr_file_write(lfs_t *lfs, lfsr_file_t *file, goto failed; } - // update our buffer if we overlap + // after success, fill our buffer with the tail of our write // - // but do this after writing so we can't fail - if (pos_ < buffer_pos_ + buffer_size_ - && pos_ + size > buffer_pos_) { - memcpy(&file->buffer[pos_ - lfs_min32(buffer_pos_, pos_)], - &buffer_[buffer_pos_ - lfs_min32(pos_, buffer_pos_)], - lfs_min32( - buffer_size_ - ( - pos_ - lfs_min32(buffer_pos_, pos_)), - size - ( - buffer_pos_ - lfs_min32(pos_, buffer_pos_)))); - } + // note we need to clear the buffer anyways to avoid any + // out-of-date data + memcpy(file->buffer, + &buffer_[size - lfs->cfg->cache_size], + lfs->cfg->cache_size); + buffer_pos_ = pos_ + size - lfs->cfg->cache_size; + buffer_size_ = lfs->cfg->cache_size; pos_ += size; buffer_ += size;