diff --git a/turbonfs/inc/file_cache.h b/turbonfs/inc/file_cache.h index 12debd1f..7a7c1c9e 100644 --- a/turbonfs/inc/file_cache.h +++ b/turbonfs/inc/file_cache.h @@ -1600,9 +1600,28 @@ class bytes_chunk_cache */ static const uint64_t max_dirty_allowed_per_file = max_dirty_extent_bytes() * 4; - const bool local_pressure = + bool local_pressure = (bytes_dirty + bytes_commit_pending) > max_dirty_allowed_per_file; + /* + * In case of smaller writes, number of dirty membufs will be more + * than the dirty bytes. So we also check if number of dirty membufs + * exceed a threshold, which is derived from max dirty extent bytes. + * This will help in keep our byte cache map size under control. + * + * Note: Block size below 64KB consider as smaller writes for those, + * if we have more than 16 x (max_dirty_extent_bytes()/1MB) membufs + * dirty, we consider that as local pressure. + * f.e. max_dirty_extent_bytes() = 1GB cause 16K dirty membufs to + * trigger inline write. + */ + if (!local_pressure) { + static const uint64_t max_dirty_membufs_allowed_per_file = + (max_dirty_extent_bytes() * 16)/(1024 * 1024ULL); + local_pressure = num_dirty_membufs > + max_dirty_membufs_allowed_per_file; + } + /* * TODO: Add counter/stats for counting how many times we forced * inline write due to local and how many times due to global @@ -1772,6 +1791,7 @@ class bytes_chunk_cache std::atomic bytes_allocated = 0; std::atomic bytes_cached = 0; std::atomic bytes_dirty = 0; + std::atomic num_dirty_membufs = 0; std::atomic bytes_flushing = 0; std::atomic bytes_commit_pending = 0; std::atomic bytes_uptodate = 0; @@ -1791,6 +1811,7 @@ class bytes_chunk_cache static std::atomic bytes_allocated_g; static std::atomic bytes_cached_g; static std::atomic bytes_dirty_g; + static std::atomic num_dirty_membufs_g; static std::atomic bytes_flushing_g; static std::atomic bytes_commit_pending_g; static std::atomic bytes_uptodate_g; diff --git a/turbonfs/src/file_cache.cpp b/turbonfs/src/file_cache.cpp index e14d5959..a25d6c75 100644 --- a/turbonfs/src/file_cache.cpp +++ b/turbonfs/src/file_cache.cpp @@ -29,7 +29,6 @@ namespace aznfsc { /* static */ std::atomic bytes_chunk_cache::num_caches = 0; - /* static */ std::atomic bytes_chunk_cache::num_chunks_g = 0; /* static */ std::atomic bytes_chunk_cache::num_get_g = 0; /* static */ std::atomic bytes_chunk_cache::bytes_get_g = 0; @@ -40,6 +39,7 @@ namespace aznfsc { /* static */ std::atomic bytes_chunk_cache::bytes_allocated_g = 0; /* static */ std::atomic bytes_chunk_cache::bytes_cached_g = 0; /* static */ std::atomic bytes_chunk_cache::bytes_dirty_g = 0; +/* static */ std::atomic bytes_chunk_cache::num_dirty_membufs_g = 0; /* static */ std::atomic bytes_chunk_cache::bytes_flushing_g = 0; /* static */ std::atomic bytes_chunk_cache::bytes_commit_pending_g = 0; /* static */ std::atomic bytes_chunk_cache::bytes_uptodate_g = 0; @@ -795,6 +795,8 @@ void membuf::set_dirty() bcc->bytes_dirty_g += length; bcc->bytes_dirty += length; + bcc->num_dirty_membufs++; + bcc->num_dirty_membufs_g++; assert(bcc->bytes_dirty <= AZNFSC_MAX_FILE_SIZE); @@ -819,6 +821,10 @@ void membuf::clear_dirty() assert(bcc->bytes_dirty >= length); assert(bcc->bytes_dirty_g >= length); + assert(bcc->num_dirty_membufs > 0); + assert(bcc->num_dirty_membufs_g > 0); + bcc->num_dirty_membufs--; + bcc->num_dirty_membufs_g--; bcc->bytes_dirty -= length; bcc->bytes_dirty_g -= length;