mirror of
https://github.com/facebook/sapling.git
synced 2025-01-06 21:48:36 +03:00
Separate FUSE and Hg counter structs
Summary: Some threads update FUSE counters, some threads update HgBackingStore counters, and some threads update HgImporter counters. No thread updates all of FUSE counters, HgBackingStore counters, and HgImporter counters. FUSE threads and HgImporter threads allocate the full set of counters (EdenThreadStats), even though many of the allocated counters can never be used during the thread's lifetime. Reduce redundant allocation (and overhead during counter aggregation): split EdenThreadStats into three classes (FuseThreadStats, HgBackingStoreThreadStats, and HgImporterThreadStats) so different threads can allocate different sets of counters. This diff should not change observable behavior. Reviewed By: simpkins Differential Revision: D14822273 fbshipit-source-id: cfd238187d20a0b8d3959673401ecad894e2095b
This commit is contained in:
parent
5436028259
commit
761d5d2c8e
@ -175,45 +175,45 @@ void installSignalHandler() {
|
||||
|
||||
struct FuseChannel::HandlerEntry {
|
||||
Handler handler;
|
||||
EdenThreadStats::HistogramPtr histogram;
|
||||
FuseThreadStats::HistogramPtr histogram;
|
||||
};
|
||||
|
||||
const FuseChannel::HandlerMap FuseChannel::handlerMap_ = {
|
||||
{FUSE_READ, {&FuseChannel::fuseRead, &EdenThreadStats::read}},
|
||||
{FUSE_WRITE, {&FuseChannel::fuseWrite, &EdenThreadStats::write}},
|
||||
{FUSE_LOOKUP, {&FuseChannel::fuseLookup, &EdenThreadStats::lookup}},
|
||||
{FUSE_FORGET, {&FuseChannel::fuseForget, &EdenThreadStats::forget}},
|
||||
{FUSE_GETATTR, {&FuseChannel::fuseGetAttr, &EdenThreadStats::getattr}},
|
||||
{FUSE_SETATTR, {&FuseChannel::fuseSetAttr, &EdenThreadStats::setattr}},
|
||||
{FUSE_READLINK, {&FuseChannel::fuseReadLink, &EdenThreadStats::readlink}},
|
||||
{FUSE_SYMLINK, {&FuseChannel::fuseSymlink, &EdenThreadStats::symlink}},
|
||||
{FUSE_MKNOD, {&FuseChannel::fuseMknod, &EdenThreadStats::mknod}},
|
||||
{FUSE_MKDIR, {&FuseChannel::fuseMkdir, &EdenThreadStats::mkdir}},
|
||||
{FUSE_UNLINK, {&FuseChannel::fuseUnlink, &EdenThreadStats::unlink}},
|
||||
{FUSE_RMDIR, {&FuseChannel::fuseRmdir, &EdenThreadStats::rmdir}},
|
||||
{FUSE_RENAME, {&FuseChannel::fuseRename, &EdenThreadStats::rename}},
|
||||
{FUSE_LINK, {&FuseChannel::fuseLink, &EdenThreadStats::link}},
|
||||
{FUSE_OPEN, {&FuseChannel::fuseOpen, &EdenThreadStats::open}},
|
||||
{FUSE_STATFS, {&FuseChannel::fuseStatFs, &EdenThreadStats::statfs}},
|
||||
{FUSE_RELEASE, {&FuseChannel::fuseRelease, &EdenThreadStats::release}},
|
||||
{FUSE_FSYNC, {&FuseChannel::fuseFsync, &EdenThreadStats::fsync}},
|
||||
{FUSE_SETXATTR, {&FuseChannel::fuseSetXAttr, &EdenThreadStats::setxattr}},
|
||||
{FUSE_GETXATTR, {&FuseChannel::fuseGetXAttr, &EdenThreadStats::getxattr}},
|
||||
{FUSE_READ, {&FuseChannel::fuseRead, &FuseThreadStats::read}},
|
||||
{FUSE_WRITE, {&FuseChannel::fuseWrite, &FuseThreadStats::write}},
|
||||
{FUSE_LOOKUP, {&FuseChannel::fuseLookup, &FuseThreadStats::lookup}},
|
||||
{FUSE_FORGET, {&FuseChannel::fuseForget, &FuseThreadStats::forget}},
|
||||
{FUSE_GETATTR, {&FuseChannel::fuseGetAttr, &FuseThreadStats::getattr}},
|
||||
{FUSE_SETATTR, {&FuseChannel::fuseSetAttr, &FuseThreadStats::setattr}},
|
||||
{FUSE_READLINK, {&FuseChannel::fuseReadLink, &FuseThreadStats::readlink}},
|
||||
{FUSE_SYMLINK, {&FuseChannel::fuseSymlink, &FuseThreadStats::symlink}},
|
||||
{FUSE_MKNOD, {&FuseChannel::fuseMknod, &FuseThreadStats::mknod}},
|
||||
{FUSE_MKDIR, {&FuseChannel::fuseMkdir, &FuseThreadStats::mkdir}},
|
||||
{FUSE_UNLINK, {&FuseChannel::fuseUnlink, &FuseThreadStats::unlink}},
|
||||
{FUSE_RMDIR, {&FuseChannel::fuseRmdir, &FuseThreadStats::rmdir}},
|
||||
{FUSE_RENAME, {&FuseChannel::fuseRename, &FuseThreadStats::rename}},
|
||||
{FUSE_LINK, {&FuseChannel::fuseLink, &FuseThreadStats::link}},
|
||||
{FUSE_OPEN, {&FuseChannel::fuseOpen, &FuseThreadStats::open}},
|
||||
{FUSE_STATFS, {&FuseChannel::fuseStatFs, &FuseThreadStats::statfs}},
|
||||
{FUSE_RELEASE, {&FuseChannel::fuseRelease, &FuseThreadStats::release}},
|
||||
{FUSE_FSYNC, {&FuseChannel::fuseFsync, &FuseThreadStats::fsync}},
|
||||
{FUSE_SETXATTR, {&FuseChannel::fuseSetXAttr, &FuseThreadStats::setxattr}},
|
||||
{FUSE_GETXATTR, {&FuseChannel::fuseGetXAttr, &FuseThreadStats::getxattr}},
|
||||
{FUSE_LISTXATTR,
|
||||
{&FuseChannel::fuseListXAttr, &EdenThreadStats::listxattr}},
|
||||
{&FuseChannel::fuseListXAttr, &FuseThreadStats::listxattr}},
|
||||
{FUSE_REMOVEXATTR,
|
||||
{&FuseChannel::fuseRemoveXAttr, &EdenThreadStats::removexattr}},
|
||||
{FUSE_FLUSH, {&FuseChannel::fuseFlush, &EdenThreadStats::flush}},
|
||||
{FUSE_OPENDIR, {&FuseChannel::fuseOpenDir, &EdenThreadStats::opendir}},
|
||||
{FUSE_READDIR, {&FuseChannel::fuseReadDir, &EdenThreadStats::readdir}},
|
||||
{&FuseChannel::fuseRemoveXAttr, &FuseThreadStats::removexattr}},
|
||||
{FUSE_FLUSH, {&FuseChannel::fuseFlush, &FuseThreadStats::flush}},
|
||||
{FUSE_OPENDIR, {&FuseChannel::fuseOpenDir, &FuseThreadStats::opendir}},
|
||||
{FUSE_READDIR, {&FuseChannel::fuseReadDir, &FuseThreadStats::readdir}},
|
||||
{FUSE_RELEASEDIR,
|
||||
{&FuseChannel::fuseReleaseDir, &EdenThreadStats::releasedir}},
|
||||
{FUSE_FSYNCDIR, {&FuseChannel::fuseFsyncDir, &EdenThreadStats::fsyncdir}},
|
||||
{FUSE_ACCESS, {&FuseChannel::fuseAccess, &EdenThreadStats::access}},
|
||||
{FUSE_CREATE, {&FuseChannel::fuseCreate, &EdenThreadStats::create}},
|
||||
{FUSE_BMAP, {&FuseChannel::fuseBmap, &EdenThreadStats::bmap}},
|
||||
{&FuseChannel::fuseReleaseDir, &FuseThreadStats::releasedir}},
|
||||
{FUSE_FSYNCDIR, {&FuseChannel::fuseFsyncDir, &FuseThreadStats::fsyncdir}},
|
||||
{FUSE_ACCESS, {&FuseChannel::fuseAccess, &FuseThreadStats::access}},
|
||||
{FUSE_CREATE, {&FuseChannel::fuseCreate, &FuseThreadStats::create}},
|
||||
{FUSE_BMAP, {&FuseChannel::fuseBmap, &FuseThreadStats::bmap}},
|
||||
{FUSE_BATCH_FORGET,
|
||||
{&FuseChannel::fuseBatchForget, &EdenThreadStats::forgetmulti}},
|
||||
{&FuseChannel::fuseBatchForget, &FuseThreadStats::forgetmulti}},
|
||||
};
|
||||
|
||||
static iovec inline make_iovec(const void* addr, size_t len) {
|
||||
|
@ -53,7 +53,7 @@ RequestData& RequestData::create(
|
||||
|
||||
void RequestData::startRequest(
|
||||
EdenStats* stats,
|
||||
EdenThreadStats::HistogramPtr histogram) {
|
||||
FuseThreadStats::HistogramPtr histogram) {
|
||||
startTime_ = steady_clock::now();
|
||||
DCHECK(latencyHistogram_ == nullptr);
|
||||
latencyHistogram_ = histogram;
|
||||
@ -64,7 +64,7 @@ void RequestData::finishRequest() {
|
||||
const auto now = steady_clock::now();
|
||||
const auto now_since_epoch = duration_cast<seconds>(now.time_since_epoch());
|
||||
const auto diff = duration_cast<microseconds>(now - startTime_);
|
||||
stats_->getStatsForCurrentThread().recordLatency(
|
||||
stats_->getFuseStatsForCurrentThread().recordLatency(
|
||||
latencyHistogram_, diff, now_since_epoch);
|
||||
latencyHistogram_ = nullptr;
|
||||
stats_ = nullptr;
|
||||
|
@ -26,7 +26,7 @@ class RequestData : public folly::RequestData {
|
||||
fuse_in_header fuseHeader_;
|
||||
// Needed to track stats
|
||||
std::chrono::time_point<std::chrono::steady_clock> startTime_;
|
||||
EdenThreadStats::HistogramPtr latencyHistogram_{nullptr};
|
||||
FuseThreadStats::HistogramPtr latencyHistogram_{nullptr};
|
||||
EdenStats* stats_{nullptr};
|
||||
Dispatcher* dispatcher_{nullptr};
|
||||
|
||||
@ -56,7 +56,7 @@ class RequestData : public folly::RequestData {
|
||||
// a FUSE request, false otherwise.
|
||||
static bool isFuseRequest();
|
||||
|
||||
void startRequest(EdenStats* stats, EdenThreadStats::HistogramPtr histogram);
|
||||
void startRequest(EdenStats* stats, FuseThreadStats::HistogramPtr histogram);
|
||||
void finishRequest();
|
||||
|
||||
// Returns the associated dispatcher instance
|
||||
|
@ -116,7 +116,9 @@ class HgImporterThreadFactory : public folly::ThreadFactory {
|
||||
std::thread newThread(folly::Func&& func) override {
|
||||
return delegate_.newThread([this, func = std::move(func)]() mutable {
|
||||
threadLocalImporter.reset(new HgImporterManager(
|
||||
repository_, localStore_, getSharedStatsForCurrentThread(stats_)));
|
||||
repository_,
|
||||
localStore_,
|
||||
getSharedHgImporterStatsForCurrentThread(stats_)));
|
||||
func();
|
||||
});
|
||||
}
|
||||
@ -252,7 +254,7 @@ HgBackingStore::HgBackingStore(
|
||||
initializeDatapackImport(repository);
|
||||
#endif
|
||||
HgImporter importer(
|
||||
repository, localStore, getSharedStatsForCurrentThread(stats));
|
||||
repository, localStore, getSharedHgImporterStatsForCurrentThread(stats));
|
||||
const auto& options = importer.getOptions();
|
||||
initializeTreeManifestImport(options, repository);
|
||||
repoName_ = options.repoName;
|
||||
@ -473,8 +475,8 @@ Future<unique_ptr<Tree>> HgBackingStore::getTree(const Hash& id) {
|
||||
batch = std::move(writeBatch),
|
||||
watch = std::move(watch)](auto tree) {
|
||||
batch->flush();
|
||||
stats->getStatsForCurrentThread().hgBackingStoreGetTree.addValue(
|
||||
watch.elapsed().count());
|
||||
stats->getHgBackingStoreStatsForCurrentThread()
|
||||
.hgBackingStoreGetTree.addValue(watch.elapsed().count());
|
||||
return tree;
|
||||
});
|
||||
}
|
||||
@ -541,7 +543,7 @@ Future<unique_ptr<Tree>> HgBackingStore::importTreeImpl(
|
||||
writeBatch->put(
|
||||
KeySpace::TreeFamily, edenTreeID, serialized.second.coalesce());
|
||||
auto count = watch.elapsed().count();
|
||||
stats->getStatsForCurrentThread()
|
||||
stats->getHgBackingStoreStatsForCurrentThread()
|
||||
.mononokeBackingStoreGetTree.addValue(count);
|
||||
return makeFuture(std::move(tree));
|
||||
})
|
||||
@ -768,7 +770,7 @@ Future<unique_ptr<Blob>> HgBackingStore::getBlob(const Hash& id) {
|
||||
return mononoke->getBlob(revHashCopy)
|
||||
.ensure([stats = stats_, watch = std::move(watch)]() {
|
||||
auto count = watch.elapsed().count();
|
||||
stats->getStatsForCurrentThread()
|
||||
stats->getHgBackingStoreStatsForCurrentThread()
|
||||
.mononokeBackingStoreGetBlob.addValue(count);
|
||||
})
|
||||
.thenError([this,
|
||||
|
@ -250,7 +250,7 @@ class HgImporterEofError : public HgImporterError {
|
||||
HgImporter::HgImporter(
|
||||
AbsolutePathPiece repoPath,
|
||||
LocalStore* store,
|
||||
std::shared_ptr<EdenThreadStats> stats,
|
||||
std::shared_ptr<HgImporterThreadStats> stats,
|
||||
std::optional<AbsolutePath> importHelperScript)
|
||||
: repoPath_{repoPath}, store_{store}, stats_{std::move(stats)} {
|
||||
std::vector<string> cmd;
|
||||
@ -706,7 +706,7 @@ HgImporter::ChunkHeader HgImporter::readChunkHeader(
|
||||
HgImporter::TransactionID HgImporter::sendManifestRequest(
|
||||
folly::StringPiece revName) {
|
||||
#if defined(EDEN_HAVE_STATS)
|
||||
stats_->hgImporterManifest.addValue(1);
|
||||
stats_->manifest.addValue(1);
|
||||
#endif
|
||||
|
||||
auto txnID = nextRequestID_++;
|
||||
@ -729,7 +729,7 @@ HgImporter::TransactionID HgImporter::sendManifestRequest(
|
||||
HgImporter::TransactionID HgImporter::sendManifestNodeRequest(
|
||||
folly::StringPiece revName) {
|
||||
#if defined(EDEN_HAVE_STATS)
|
||||
stats_->hgImporterManifestNodeForCommit.addValue(1);
|
||||
stats_->manifestNodeForCommit.addValue(1);
|
||||
#endif
|
||||
|
||||
auto txnID = nextRequestID_++;
|
||||
@ -753,7 +753,7 @@ HgImporter::TransactionID HgImporter::sendFileRequest(
|
||||
RelativePathPiece path,
|
||||
Hash revHash) {
|
||||
#if defined(EDEN_HAVE_STATS)
|
||||
stats_->hgImporterCatFile.addValue(1);
|
||||
stats_->catFile.addValue(1);
|
||||
#endif
|
||||
|
||||
auto txnID = nextRequestID_++;
|
||||
@ -779,7 +779,7 @@ HgImporter::TransactionID HgImporter::sendFileRequest(
|
||||
HgImporter::TransactionID HgImporter::sendPrefetchFilesRequest(
|
||||
const std::vector<std::pair<RelativePath, Hash>>& files) {
|
||||
#if defined(EDEN_HAVE_STATS)
|
||||
stats_->hgImporterPrefetchFiles.addValue(1);
|
||||
stats_->prefetchFiles.addValue(1);
|
||||
#endif
|
||||
|
||||
auto txnID = nextRequestID_++;
|
||||
@ -838,7 +838,7 @@ HgImporter::TransactionID HgImporter::sendFetchTreeRequest(
|
||||
RelativePathPiece path,
|
||||
Hash pathManifestNode) {
|
||||
#if defined(EDEN_HAVE_STATS)
|
||||
stats_->hgImporterFetchTree.addValue(1);
|
||||
stats_->fetchTree.addValue(1);
|
||||
#endif
|
||||
|
||||
auto txnID = nextRequestID_++;
|
||||
@ -945,7 +945,7 @@ const ImporterOptions& HgImporter::getOptions() const {
|
||||
HgImporterManager::HgImporterManager(
|
||||
AbsolutePathPiece repoPath,
|
||||
LocalStore* store,
|
||||
std::shared_ptr<EdenThreadStats> stats,
|
||||
std::shared_ptr<HgImporterThreadStats> stats,
|
||||
std::optional<AbsolutePath> importHelperScript)
|
||||
: repoPath_{repoPath},
|
||||
store_{store},
|
||||
|
@ -124,7 +124,8 @@ class Importer {
|
||||
* the following reasons:
|
||||
*
|
||||
* * HgImporter does not synchronize its own members.
|
||||
* * HgImporter accesses EdenThreadStats, and EdenThreadStats is thread-bound.
|
||||
* * HgImporter accesses HgImporterThreadStats, and HgImporterThreadStats is
|
||||
* thread-bound.
|
||||
*/
|
||||
class HgImporter : public Importer {
|
||||
public:
|
||||
@ -138,7 +139,7 @@ class HgImporter : public Importer {
|
||||
HgImporter(
|
||||
AbsolutePathPiece repoPath,
|
||||
LocalStore* store,
|
||||
std::shared_ptr<EdenThreadStats>,
|
||||
std::shared_ptr<HgImporterThreadStats>,
|
||||
std::optional<AbsolutePath> importHelperScript = std::nullopt);
|
||||
|
||||
virtual ~HgImporter();
|
||||
@ -298,7 +299,7 @@ class HgImporter : public Importer {
|
||||
#endif
|
||||
const AbsolutePath repoPath_;
|
||||
LocalStore* const store_{nullptr};
|
||||
std::shared_ptr<EdenThreadStats> const stats_;
|
||||
std::shared_ptr<HgImporterThreadStats> const stats_;
|
||||
ImporterOptions options_;
|
||||
uint32_t nextRequestID_{0};
|
||||
/**
|
||||
@ -339,7 +340,7 @@ class HgImporterManager : public Importer {
|
||||
HgImporterManager(
|
||||
AbsolutePathPiece repoPath,
|
||||
LocalStore* store,
|
||||
std::shared_ptr<EdenThreadStats>,
|
||||
std::shared_ptr<HgImporterThreadStats>,
|
||||
std::optional<AbsolutePath> importHelperScript = std::nullopt);
|
||||
|
||||
Hash importFlatManifest(folly::StringPiece revName) override;
|
||||
@ -361,7 +362,7 @@ class HgImporterManager : public Importer {
|
||||
|
||||
const AbsolutePath repoPath_;
|
||||
LocalStore* const store_{nullptr};
|
||||
std::shared_ptr<EdenThreadStats> const stats_;
|
||||
std::shared_ptr<HgImporterThreadStats> const stats_;
|
||||
const std::optional<AbsolutePath> importHelperScript_;
|
||||
};
|
||||
|
||||
|
@ -50,7 +50,7 @@ struct HgBackingStoreTest : TestRepo, ::testing::Test {
|
||||
std::shared_ptr<EdenStats> stats{std::make_shared<EdenStats>()};
|
||||
HgImporter importer{repo.path(),
|
||||
localStore.get(),
|
||||
getSharedStatsForCurrentThread(stats)};
|
||||
getSharedHgImporterStatsForCurrentThread(stats)};
|
||||
std::shared_ptr<HgBackingStore> backingStore{
|
||||
std::make_shared<HgBackingStore>(&importer, localStore.get(), stats)};
|
||||
std::shared_ptr<ObjectStore> objectStore{
|
||||
|
@ -158,7 +158,7 @@ class HgImportErrorTest : public ::testing::Test {
|
||||
importer_ = make_unique<ImporterType>(
|
||||
testPath_,
|
||||
localStore_.get(),
|
||||
getSharedStatsForCurrentThread(stats_),
|
||||
getSharedHgImporterStatsForCurrentThread(stats_),
|
||||
fakeImportHelper);
|
||||
backingStore_ =
|
||||
make_shared<HgBackingStore>(importer_.get(), localStore_.get(), stats_);
|
||||
|
@ -47,7 +47,8 @@ class HgImportTest : public ::testing::Test {
|
||||
AbsolutePath testPath_{testDir_.path().string()};
|
||||
HgRepo repo_{testPath_ + "repo"_pc};
|
||||
MemoryLocalStore localStore_;
|
||||
std::shared_ptr<EdenThreadStats> stats_ = std::make_shared<EdenThreadStats>();
|
||||
std::shared_ptr<HgImporterThreadStats> stats_ =
|
||||
std::make_shared<HgImporterThreadStats>();
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
@ -27,25 +27,39 @@ constexpr std::chrono::microseconds kBucketSize{1000};
|
||||
namespace facebook {
|
||||
namespace eden {
|
||||
|
||||
EdenThreadStats& EdenStats::getStatsForCurrentThread() {
|
||||
return *threadLocalStats_.get();
|
||||
FuseThreadStats& EdenStats::getFuseStatsForCurrentThread() {
|
||||
return *threadLocalFuseStats_.get();
|
||||
}
|
||||
|
||||
HgBackingStoreThreadStats& EdenStats::getHgBackingStoreStatsForCurrentThread() {
|
||||
return *threadLocalHgBackingStoreStats_.get();
|
||||
}
|
||||
|
||||
HgImporterThreadStats& EdenStats::getHgImporterStatsForCurrentThread() {
|
||||
return *threadLocalHgImporterStats_.get();
|
||||
}
|
||||
|
||||
void EdenStats::aggregate() {
|
||||
for (auto& stats : threadLocalStats_.accessAllThreads()) {
|
||||
for (auto& stats : threadLocalFuseStats_.accessAllThreads()) {
|
||||
stats.aggregate();
|
||||
}
|
||||
for (auto& stats : threadLocalHgBackingStoreStats_.accessAllThreads()) {
|
||||
stats.aggregate();
|
||||
}
|
||||
for (auto& stats : threadLocalHgImporterStats_.accessAllThreads()) {
|
||||
stats.aggregate();
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<EdenThreadStats> getSharedStatsForCurrentThread(
|
||||
std::shared_ptr<HgImporterThreadStats> getSharedHgImporterStatsForCurrentThread(
|
||||
std::shared_ptr<EdenStats> stats) {
|
||||
return std::shared_ptr<EdenThreadStats>(
|
||||
stats, &stats->getStatsForCurrentThread());
|
||||
return std::shared_ptr<HgImporterThreadStats>(
|
||||
stats, &stats->getHgImporterStatsForCurrentThread());
|
||||
}
|
||||
|
||||
EdenThreadStats::EdenThreadStats() {}
|
||||
EdenThreadStatsBase::EdenThreadStatsBase() {}
|
||||
|
||||
EdenThreadStats::Histogram EdenThreadStats::createHistogram(
|
||||
EdenThreadStatsBase::Histogram EdenThreadStatsBase::createHistogram(
|
||||
const std::string& name) {
|
||||
return Histogram{this,
|
||||
name,
|
||||
@ -59,7 +73,7 @@ EdenThreadStats::Histogram EdenThreadStats::createHistogram(
|
||||
}
|
||||
|
||||
#if defined(EDEN_HAVE_STATS)
|
||||
EdenThreadStats::Timeseries EdenThreadStats::createTimeseries(
|
||||
EdenThreadStatsBase::Timeseries EdenThreadStatsBase::createTimeseries(
|
||||
const std::string& name) {
|
||||
auto timeseries = Timeseries{this, name};
|
||||
timeseries.exportStat(facebook::stats::COUNT);
|
||||
@ -67,7 +81,7 @@ EdenThreadStats::Timeseries EdenThreadStats::createTimeseries(
|
||||
}
|
||||
#endif
|
||||
|
||||
void EdenThreadStats::recordLatency(
|
||||
void FuseThreadStats::recordLatency(
|
||||
HistogramPtr item,
|
||||
std::chrono::microseconds elapsed,
|
||||
std::chrono::seconds now) {
|
||||
|
@ -17,7 +17,9 @@
|
||||
namespace facebook {
|
||||
namespace eden {
|
||||
|
||||
class EdenThreadStats;
|
||||
class FuseThreadStats;
|
||||
class HgBackingStoreThreadStats;
|
||||
class HgImporterThreadStats;
|
||||
|
||||
class EdenStats {
|
||||
public:
|
||||
@ -26,7 +28,21 @@ class EdenStats {
|
||||
*
|
||||
* The returned object can be used only on the current thread.
|
||||
*/
|
||||
EdenThreadStats& getStatsForCurrentThread();
|
||||
FuseThreadStats& getFuseStatsForCurrentThread();
|
||||
|
||||
/**
|
||||
* This function can be called on any thread.
|
||||
*
|
||||
* The returned object can be used only on the current thread.
|
||||
*/
|
||||
HgBackingStoreThreadStats& getHgBackingStoreStatsForCurrentThread();
|
||||
|
||||
/**
|
||||
* This function can be called on any thread.
|
||||
*
|
||||
* The returned object can be used only on the current thread.
|
||||
*/
|
||||
HgImporterThreadStats& getHgImporterStatsForCurrentThread();
|
||||
|
||||
/**
|
||||
* This function can be called on any thread.
|
||||
@ -36,29 +52,44 @@ class EdenStats {
|
||||
private:
|
||||
class ThreadLocalTag {};
|
||||
|
||||
folly::ThreadLocal<EdenThreadStats, ThreadLocalTag, void> threadLocalStats_;
|
||||
folly::ThreadLocal<FuseThreadStats, ThreadLocalTag, void>
|
||||
threadLocalFuseStats_;
|
||||
folly::ThreadLocal<HgBackingStoreThreadStats, ThreadLocalTag, void>
|
||||
threadLocalHgBackingStoreStats_;
|
||||
folly::ThreadLocal<HgImporterThreadStats, ThreadLocalTag, void>
|
||||
threadLocalHgImporterStats_;
|
||||
};
|
||||
|
||||
std::shared_ptr<EdenThreadStats> getSharedStatsForCurrentThread(
|
||||
std::shared_ptr<HgImporterThreadStats> getSharedHgImporterStatsForCurrentThread(
|
||||
std::shared_ptr<EdenStats>);
|
||||
|
||||
/**
|
||||
* EdenThreadStats contains various thread-local stats structures.
|
||||
* EdenThreadStatsBase is a base class for a group of thread-local stats
|
||||
* structures.
|
||||
*
|
||||
* Each EdenThreadStats object should only be used from a single thread.
|
||||
* The EdenStats object should be used to maintain one EdenThreadStats object
|
||||
* Each EdenThreadStatsBase object should only be used from a single thread. The
|
||||
* EdenStats object should be used to maintain one EdenThreadStatsBase object
|
||||
* for each thread that needs to access/update the stats.
|
||||
*/
|
||||
class EdenThreadStats : public facebook::stats::ThreadLocalStatsT<
|
||||
facebook::stats::TLStatsThreadSafe> {
|
||||
class EdenThreadStatsBase : public facebook::stats::ThreadLocalStatsT<
|
||||
facebook::stats::TLStatsThreadSafe> {
|
||||
public:
|
||||
using Histogram = TLHistogram;
|
||||
#if defined(EDEN_HAVE_STATS)
|
||||
using Timeseries = TLTimeseries;
|
||||
#endif
|
||||
|
||||
explicit EdenThreadStats();
|
||||
explicit EdenThreadStatsBase();
|
||||
|
||||
protected:
|
||||
Histogram createHistogram(const std::string& name);
|
||||
#if defined(EDEN_HAVE_STATS)
|
||||
Timeseries createTimeseries(const std::string& name);
|
||||
#endif
|
||||
};
|
||||
|
||||
class FuseThreadStats : public EdenThreadStatsBase {
|
||||
public:
|
||||
// We track latency in units of microseconds, hence the _us suffix
|
||||
// in the histogram names below.
|
||||
|
||||
@ -96,31 +127,11 @@ class EdenThreadStats : public facebook::stats::ThreadLocalStatsT<
|
||||
Histogram poll{createHistogram("fuse.poll_us")};
|
||||
Histogram forgetmulti{createHistogram("fuse.forgetmulti_us")};
|
||||
|
||||
#if defined(EDEN_HAVE_STATS)
|
||||
/**
|
||||
* @see HgImporter
|
||||
*/
|
||||
Timeseries hgImporterCatFile{createTimeseries("hg_importer.cat_file")};
|
||||
Timeseries hgImporterFetchTree{createTimeseries("hg_importer.fetch_tree")};
|
||||
Timeseries hgImporterManifest{createTimeseries("hg_importer.manifest")};
|
||||
Timeseries hgImporterManifestNodeForCommit{
|
||||
createTimeseries("hg_importer.manifest_node_for_commit")};
|
||||
Timeseries hgImporterPrefetchFiles{
|
||||
createTimeseries("hg_importer.prefetch_files")};
|
||||
#endif
|
||||
|
||||
Histogram hgBackingStoreGetTree{createHistogram("store.hg.get_tree")};
|
||||
Histogram hgBackingStoreGetBlob{createHistogram("store.hg.get_file")};
|
||||
Histogram mononokeBackingStoreGetTree{
|
||||
createHistogram("store.mononoke.get_tree")};
|
||||
Histogram mononokeBackingStoreGetBlob{
|
||||
createHistogram("store.mononoke.get_blob")};
|
||||
|
||||
// Since we can potentially finish a request in a different
|
||||
// thread from the one used to initiate it, we use HistogramPtr
|
||||
// as a helper for referencing the pointer-to-member that we
|
||||
// want to update at the end of the request.
|
||||
using HistogramPtr = Histogram EdenThreadStats::*;
|
||||
using HistogramPtr = Histogram FuseThreadStats::*;
|
||||
|
||||
/** Record a the latency for an operation.
|
||||
* item is the pointer-to-member for one of the histograms defined
|
||||
@ -133,11 +144,35 @@ class EdenThreadStats : public facebook::stats::ThreadLocalStatsT<
|
||||
HistogramPtr item,
|
||||
std::chrono::microseconds elapsed,
|
||||
std::chrono::seconds now);
|
||||
};
|
||||
|
||||
/**
|
||||
* @see HgBackingStore
|
||||
*/
|
||||
class HgBackingStoreThreadStats : public EdenThreadStatsBase {
|
||||
public:
|
||||
Histogram hgBackingStoreGetTree{createHistogram("store.hg.get_tree")};
|
||||
Histogram mononokeBackingStoreGetTree{
|
||||
createHistogram("store.mononoke.get_tree")};
|
||||
Histogram mononokeBackingStoreGetBlob{
|
||||
createHistogram("store.mononoke.get_blob")};
|
||||
};
|
||||
|
||||
/**
|
||||
* @see HgImporter
|
||||
* @see HgBackingStore
|
||||
*/
|
||||
class HgImporterThreadStats : public EdenThreadStatsBase {
|
||||
public:
|
||||
Histogram hgBackingStoreGetBlob{createHistogram("store.hg.get_file")};
|
||||
|
||||
private:
|
||||
Histogram createHistogram(const std::string& name);
|
||||
#if defined(EDEN_HAVE_STATS)
|
||||
Timeseries createTimeseries(const std::string& name);
|
||||
Timeseries catFile{createTimeseries("hg_importer.cat_file")};
|
||||
Timeseries fetchTree{createTimeseries("hg_importer.fetch_tree")};
|
||||
Timeseries manifest{createTimeseries("hg_importer.manifest")};
|
||||
Timeseries manifestNodeForCommit{
|
||||
createTimeseries("hg_importer.manifest_node_for_commit")};
|
||||
Timeseries prefetchFiles{createTimeseries("hg_importer.prefetch_files")};
|
||||
#endif
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user