Skip to content

Commit a0a96ec

Browse files
Jaesoo Leefacebook-github-bot
authored andcommitted
run flush on reclaim thread
Summary: As discovered in T177120945, it seems like there is some regression in p99 latency of insert requests with navy-async. The reason for this might be the fact that we are running the flush in line if issued for insert request on NavyThread. However, since the flush could take long, this could cause unnecessarily high latency, particularly, if flushes are executed multiple times on the same NavyThread as part of insert requests back-to-back. Since the flush can be executed async, this change makes the flush to be run by the reclaim threads. In doing so, this change also adds a feature to get the reference to the current NavyThread via global function. Reviewed By: haowu14 Differential Revision: D53491112 fbshipit-source-id: 309d43c9fc23343d006344661f618f03c9d30843
1 parent d4ff947 commit a0a96ec

7 files changed

Lines changed: 65 additions & 12 deletions

File tree

cachelib/navy/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ add_library (cachelib_navy
3333
common/Device.cpp
3434
common/FdpNvme.cpp
3535
common/Hash.cpp
36+
common/NavyThread.cpp
3637
common/SizeDistribution.cpp
3738
common/Types.cpp
3839
driver/Driver.cpp

cachelib/navy/block_cache/Allocator.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <cassert>
2323
#include <utility>
2424

25+
#include "cachelib/navy/common/NavyThread.h"
2526
#include "cachelib/navy/common/Utils.h"
2627

2728
namespace facebook::cachelib::navy {
@@ -84,7 +85,7 @@ std::tuple<RegionDescriptor, uint32_t, RelAddress> Allocator::allocateWith(
8485
// picked ended up being full.
8586
XDCHECK(!rid.valid());
8687

87-
if (canWait && !folly::fibers::onFiber()) {
88+
if (canWait && !getCurrentNavyThread()) {
8889
// Waiting on main thread could cause indefinite blocking, so do not wait
8990
canWait = false;
9091
}

cachelib/navy/block_cache/Region.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
#include "cachelib/navy/block_cache/Region.h"
1818

19+
#include "cachelib/navy/common/NavyThread.h"
20+
1921
namespace facebook::cachelib::navy {
2022

2123
bool Region::readyForReclaim(bool wait) {
@@ -50,7 +52,7 @@ RegionDescriptor Region::openForRead() {
5052
std::unique_lock<TimedMutex> l{lock_};
5153
if (flags_ & kBlockAccess) {
5254
// Region is currently in reclaim, retry later
53-
if (folly::fibers::onFiber()) {
55+
if (getCurrentNavyThread()) {
5456
// If we are on fiber, we can just sleep here
5557
cond_.wait(l);
5658
}

cachelib/navy/block_cache/RegionManager.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ RegionManager::RegionManager(uint32_t numRegions,
6363
auto name = fmt::format("region_manager_{}", i);
6464
workers_.emplace_back(
6565
std::make_unique<NavyThread>(name, NavyThread::Options(stackSize)));
66+
workerSet_.insert(workers_.back().get());
6667
workers_.back()->addTaskRemote(
6768
[name]() { XLOGF(INFO, "{} started", name); });
6869
}
@@ -263,7 +264,7 @@ void RegionManager::doFlush(RegionId rid, bool async) {
263264
getRegion(rid).setPendingFlush();
264265
numInMemBufWaitingFlush_.inc();
265266

266-
if (!async || folly::fibers::onFiber()) {
267+
if (!async || isOnWorker()) {
267268
doFlushInternal(rid);
268269
} else {
269270
getNextWorker().addTaskRemote([this, rid]() { doFlushInternal(rid); });

cachelib/navy/block_cache/RegionManager.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,15 @@ class RegionManager {
273273
return *(workers_[numReclaimScheduled_.add_fetch(1) % workers_.size()]);
274274
}
275275

276+
bool isOnWorker() {
277+
auto* thread = getCurrentNavyThread();
278+
if (!thread) {
279+
return false;
280+
}
281+
282+
return workerSet_.count(thread) > 0;
283+
}
284+
276285
void doReclaim();
277286
void doFlushInternal(RegionId rid);
278287

@@ -313,6 +322,7 @@ class RegionManager {
313322
// The thread that runs the flush and reclaim. For Navy-async thread mode, the
314323
// async flushes will be run in-line on fiber by the async NavyThread itself
315324
std::vector<std::unique_ptr<NavyThread>> workers_;
325+
std::unordered_set<NavyThread*> workerSet_;
316326
mutable AtomicCounter numReclaimScheduled_;
317327

318328
const RegionEvictCallback evictCb_;
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "cachelib/navy/common/NavyThread.h"
18+
19+
namespace facebook::cachelib::navy {
20+
21+
static thread_local NavyThread* currentNavyThread_ = nullptr;
22+
23+
NavyThread* getCurrentNavyThread() { return currentNavyThread_; }
24+
25+
NavyThread::NavyThread(folly::StringPiece name, Options options) {
26+
th_ = std::make_unique<folly::ScopedEventBaseThread>(name.str());
27+
28+
folly::fibers::FiberManager::Options opts;
29+
opts.stackSize =
30+
options.stackSize ? options.stackSize : Options::kDefaultStackSize;
31+
auto& eb = *th_->getEventBase();
32+
fm_ = &folly::fibers::getFiberManager(eb, opts);
33+
34+
eb.runInEventBaseThreadAndWait([this]() { currentNavyThread_ = this; });
35+
}
36+
37+
NavyThread::~NavyThread() { th_.reset(); }
38+
39+
} // namespace facebook::cachelib::navy

cachelib/navy/common/NavyThread.h

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,12 @@ namespace facebook {
3131
namespace cachelib {
3232
namespace navy {
3333

34+
class NavyThread;
35+
36+
// @return the current NavyThread context if running on NavyThread. nullptr
37+
// otherwise.
38+
NavyThread* getCurrentNavyThread();
39+
3440
/**
3541
* NavyThread is a wrapper class that wraps folly::ScopedEventBaseThread and
3642
* FiberManager. The purpose of NavyThread is to start a new thread running
@@ -58,16 +64,9 @@ class NavyThread {
5864
/**
5965
* Initializes with current EventBaseManager and passed-in thread name.
6066
*/
61-
explicit NavyThread(folly::StringPiece name, Options options = Options()) {
62-
th_ = std::make_unique<folly::ScopedEventBaseThread>(name.str());
63-
64-
folly::fibers::FiberManager::Options opts;
65-
opts.stackSize =
66-
options.stackSize ? options.stackSize : Options::kDefaultStackSize;
67-
fm_ = &folly::fibers::getFiberManager(*th_->getEventBase(), opts);
68-
}
67+
explicit NavyThread(folly::StringPiece name, Options options = Options());
6968

70-
~NavyThread() { th_.reset(); }
69+
~NavyThread();
7170

7271
/**
7372
* Add the passed-in task to the FiberManager.

0 commit comments

Comments
 (0)