Skip to content

Commit f4b1aae

Browse files
rlyerlymeta-codesync[bot]
authored andcommitted
Remove redundant copy on the flush path
Summary: On the flush path we allocate a new IO-aligned buffer, copy the region buffer into it and then write the copy to the device. I'm not sure why this extra copy exists, especially since our Region buffers are already [IO-aligned](https://www.internalfb.com/code/fbsource/[d0fda3b969458b99e1492aafece94ea93ca7c4a4]/fbcode/cachelib/navy/block_cache/RegionManager.cpp?lines=65-66). It also doesn't increase concurrency by, for example, allowing us to return the Region buffer to the clean pool earlier because we're still blocking on the device write. Remove this redundant copy and just directly write the region buffer to the device. Reviewed By: AlnisM, byahn0996 Differential Revision: D94241607 fbshipit-source-id: a5c94f75ade247df658e981803461a2ee9d2af71
1 parent dada14c commit f4b1aae

8 files changed

Lines changed: 49 additions & 9 deletions

File tree

cachelib/allocator/nvmcache/NavyConfig.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,11 @@ class BlockCacheConfig {
555555
return *this;
556556
}
557557

558+
BlockCacheConfig& setDirectFlush(bool enable) noexcept {
559+
directFlush_ = enable;
560+
return *this;
561+
}
562+
558563
BlockCacheConfig& setAllocatorCount(uint32_t numAllocators) noexcept {
559564
allocatorsPerPriority_ = {numAllocators};
560565
return *this;
@@ -617,6 +622,8 @@ class BlockCacheConfig {
617622

618623
bool isRecoverEvictionPolicy() const { return recoverEvictionPolicy_; }
619624

625+
bool isDirectFlush() const { return directFlush_; }
626+
620627
bool isCombinedEntryBlockEnabled() const { return useCombinedEntryBlock_; }
621628

622629
const BlockCacheReinsertionConfig& getReinsertionConfig() const {
@@ -666,6 +673,9 @@ class BlockCacheConfig {
666673
// Whether to persist and recover eviction policy ordering across restarts.
667674
bool recoverEvictionPolicy_{false};
668675

676+
// Whether to write region buffer directly without intermediate copy.
677+
bool directFlush_{false};
678+
669679
// Whether to use Combined entry block (For index entries and small sized
670680
// items).
671681
// Only FixedSizeIndex will support this and it doesn't work with

cachelib/allocator/nvmcache/NavySetup.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ uint64_t setupBlockCache(const navy::BlockCacheConfig& blockCacheConfig,
181181

182182
blockCache->setRecoverEvictionPolicy(
183183
blockCacheConfig.isRecoverEvictionPolicy());
184+
blockCache->setDirectFlush(blockCacheConfig.isDirectFlush());
184185
blockCache->setUseCombinedEntryBlock(
185186
blockCacheConfig.isCombinedEntryBlockEnabled());
186187
blockCache->setNumAllocatorsPerPriority(

cachelib/navy/Factory.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,8 @@ class BlockCacheProtoImpl final : public BlockCacheProto {
135135
config_.recoverEvictionPolicy = enable;
136136
}
137137

138+
void setDirectFlush(bool enable) override { config_.directFlush = enable; }
139+
138140
void setUseCombinedEntryBlock(bool useCombinedEntryBlock) override {
139141
config_.useCombinedEntryBlock = useCombinedEntryBlock;
140142
}

cachelib/navy/Factory.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,9 @@ class BlockCacheProto {
9595
// (Optional) Persist and recover eviction policy ordering across restarts.
9696
virtual void setRecoverEvictionPolicy(bool enable) = 0;
9797

98+
// (Optional) Set if direct flush without intermediate copy is enabled.
99+
virtual void setDirectFlush(bool enable) = 0;
100+
98101
// (Optional) Set if the combined entry block is enabled.
99102
virtual void setUseCombinedEntryBlock(bool useCombinedEntryBlock) = 0;
100103

cachelib/navy/block_cache/BlockCache.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,8 @@ BlockCache::BlockCache(Config&& config, ValidConfigTag)
248248
config.inMemBufFlushRetryLimit,
249249
config.regionManagerFlushAsync,
250250
true /* allowReadDuringReclaim */,
251-
config.recoverEvictionPolicy},
251+
config.recoverEvictionPolicy,
252+
config.directFlush},
252253
allocator_{regionManager_, config.allocatorsPerPriority},
253254
reinsertionPolicy_{makeReinsertionPolicy(config.reinsertionConfig)} {
254255
validate(config);

cachelib/navy/block_cache/BlockCache.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,11 @@ class BlockCache final : public Engine {
111111
// no effect on eviction ordering.
112112
bool recoverEvictionPolicy{false};
113113

114+
// Whether to write region buffer directly to device on flush path without
115+
// allocating an intermediate IO buffer and copying. Default false preserves
116+
// old behavior for safe rollout. When true, avoids redundant copy.
117+
bool directFlush{false};
118+
114119
// name of this BC instance
115120
std::string name{};
116121

cachelib/navy/block_cache/RegionManager.cpp

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ RegionManager::RegionManager(uint32_t numRegions,
3636
uint16_t inMemBufFlushRetryLimit,
3737
bool workerFlushAsync,
3838
bool allowReadDuringReclaim,
39-
bool recoverEvictionPolicy)
39+
bool recoverEvictionPolicy,
40+
bool directFlush)
4041
: numPriorities_{numPriorities},
4142
inMemBufFlushRetryLimit_{inMemBufFlushRetryLimit},
4243
numRegions_{numRegions},
@@ -49,12 +50,14 @@ RegionManager::RegionManager(uint32_t numRegions,
4950
workerFlushAsync_{workerFlushAsync},
5051
allowReadDuringReclaim_(allowReadDuringReclaim),
5152
recoverEvictionPolicy_{recoverEvictionPolicy},
53+
directFlush_{directFlush},
5254
evictCb_{evictCb},
5355
cleanupCb_{cleanupCb},
5456
numInMemBuffers_{numInMemBuffers},
5557
placementHandle_{device_.allocatePlacementHandle()} {
56-
XLOGF(INFO, "{} regions, {} bytes each, allowReadDuringReclaim {}",
57-
numRegions_, regionSize_, allowReadDuringReclaim);
58+
XLOGF(INFO,
59+
"{} regions, {} bytes each, allowReadDuringReclaim {}, directFlush {}",
60+
numRegions_, regionSize_, allowReadDuringReclaim, directFlush);
5861
for (uint32_t i = 0; i < numRegions; i++) {
5962
regions_[i] = std::make_unique<Region>(RegionId{i}, regionSize_);
6063
}
@@ -125,10 +128,19 @@ void RegionManager::reset() {
125128
Region::FlushRes RegionManager::flushBuffer(const RegionId& rid) {
126129
auto& region = getRegion(rid);
127130
auto callBack = [this](RelAddress addr, BufferView view) {
128-
auto writeBuffer = device_.makeIOBuffer(view.size());
129-
writeBuffer.copyFrom(0, view);
130-
if (!deviceWrite(addr, std::move(writeBuffer))) {
131-
return false;
131+
if (directFlush_) {
132+
XDCHECK_EQ(0u, reinterpret_cast<uintptr_t>(view.data()) %
133+
device_.getIOAlignmentSize());
134+
XDCHECK_EQ(0u, view.size() % device_.getIOAlignmentSize());
135+
if (!deviceWrite(addr, view)) {
136+
return false;
137+
}
138+
} else {
139+
auto writeBuffer = device_.makeIOBuffer(view.size());
140+
writeBuffer.copyFrom(0, view);
141+
if (!deviceWrite(addr, std::move(writeBuffer))) {
142+
return false;
143+
}
132144
}
133145
numInMemBufWaitingFlush_.dec();
134146
return true;

cachelib/navy/block_cache/RegionManager.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ class RegionManager {
9090
// convinced there's no missing corner cases.
9191
// @param recoverEvictionPolicy whether to persist and recover eviction
9292
// policy ordering across restarts
93+
// @param directFlush whether to write region buffer directly
94+
// to device without intermediate copy
9395
RegionManager(uint32_t numRegions,
9496
uint64_t regionSize,
9597
uint64_t baseOffset,
@@ -105,7 +107,8 @@ class RegionManager {
105107
uint16_t inMemBufFlushRetryLimit,
106108
bool workerFlushAsync,
107109
bool allowReadDuringReclaim = false,
108-
bool recoverEvictionPolicy = false);
110+
bool recoverEvictionPolicy = false,
111+
bool directFlush = false);
109112
RegionManager(const RegionManager&) = delete;
110113
RegionManager& operator=(const RegionManager&) = delete;
111114

@@ -373,6 +376,9 @@ class RegionManager {
373376
// Whether to persist and recover eviction policy ordering across restarts
374377
const bool recoverEvictionPolicy_{false};
375378

379+
// Whether to write region buffer directly without intermediate copy
380+
const bool directFlush_{false};
381+
376382
const RegionEvictCallback evictCb_;
377383
const RegionCleanupCallback cleanupCb_;
378384

0 commit comments

Comments
 (0)