mirror of
https://github.com/facebook/sapling.git
synced 2025-01-08 14:46:47 +03:00
count fetch statistics during diff and checkout
Summary: During checkout and stats, count every object fetch and which level of cache it was served from. Reviewed By: simpkins Differential Revision: D19186333 fbshipit-source-id: fc0a74db297b9c723682e245996a7befd762f933
This commit is contained in:
parent
34732ab62c
commit
58f352b807
@ -13,7 +13,7 @@
|
|||||||
#include "eden/fs/inodes/EdenMount.h"
|
#include "eden/fs/inodes/EdenMount.h"
|
||||||
#include "eden/fs/inodes/InodePtrFwd.h"
|
#include "eden/fs/inodes/InodePtrFwd.h"
|
||||||
#include "eden/fs/service/gen-cpp2/eden_types.h"
|
#include "eden/fs/service/gen-cpp2/eden_types.h"
|
||||||
#include "eden/fs/store/IObjectStore.h"
|
#include "eden/fs/store/StatsFetchContext.h"
|
||||||
#include "eden/fs/utils/PathFuncs.h"
|
#include "eden/fs/utils/PathFuncs.h"
|
||||||
|
|
||||||
namespace folly {
|
namespace folly {
|
||||||
@ -102,7 +102,7 @@ class CheckoutContext {
|
|||||||
/**
|
/**
|
||||||
* Return the fetch context associated with this checkout context.
|
* Return the fetch context associated with this checkout context.
|
||||||
*/
|
*/
|
||||||
ObjectFetchContext& getFetchContext() {
|
StatsFetchContext& getFetchContext() {
|
||||||
return fetchContext_;
|
return fetchContext_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,7 +111,7 @@ class CheckoutContext {
|
|||||||
EdenMount* const mount_;
|
EdenMount* const mount_;
|
||||||
folly::Synchronized<EdenMount::ParentInfo>::LockedPtr parentsLock_;
|
folly::Synchronized<EdenMount::ParentInfo>::LockedPtr parentsLock_;
|
||||||
RenameLock renameLock_;
|
RenameLock renameLock_;
|
||||||
ObjectFetchContext fetchContext_;
|
StatsFetchContext fetchContext_;
|
||||||
|
|
||||||
// The checkout processing may occur across many threads,
|
// The checkout processing may occur across many threads,
|
||||||
// if some data load operations complete asynchronously on other threads.
|
// if some data load operations complete asynchronously on other threads.
|
||||||
|
@ -113,7 +113,7 @@ class EdenMount::JournalDiffCallback : public DiffCallback {
|
|||||||
<< folly::exceptionStr(ew);
|
<< folly::exceptionStr(ew);
|
||||||
}
|
}
|
||||||
|
|
||||||
FOLLY_NODISCARD Future<folly::Unit> performDiff(
|
FOLLY_NODISCARD Future<StatsFetchContext> performDiff(
|
||||||
EdenMount* mount,
|
EdenMount* mount,
|
||||||
TreeInodePtr rootInode,
|
TreeInodePtr rootInode,
|
||||||
std::shared_ptr<const Tree> rootTree) {
|
std::shared_ptr<const Tree> rootTree) {
|
||||||
@ -127,7 +127,8 @@ class EdenMount::JournalDiffCallback : public DiffCallback {
|
|||||||
std::move(rootTree),
|
std::move(rootTree),
|
||||||
rawContext->getToplevelIgnore(),
|
rawContext->getToplevelIgnore(),
|
||||||
false)
|
false)
|
||||||
.ensure([diffContext = std::move(diffContext), rootInode]() {});
|
.thenValue([diffContext = std::move(diffContext), rootInode](
|
||||||
|
folly::Unit) { return diffContext->getFetchContext(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
/** moves the Unclean Path information out of this diff callback instance,
|
/** moves the Unclean Path information out of this diff callback instance,
|
||||||
@ -798,10 +799,9 @@ folly::Future<CheckoutResult> EdenMount::checkout(
|
|||||||
|
|
||||||
auto& fromTree = std::get<0>(treeResults);
|
auto& fromTree = std::get<0>(treeResults);
|
||||||
return journalDiffCallback->performDiff(this, getRootInode(), fromTree)
|
return journalDiffCallback->performDiff(this, getRootInode(), fromTree)
|
||||||
.thenValue([ctx, journalDiffCallback, treeResults](Unit) {
|
.thenValue([ctx, journalDiffCallback, treeResults](
|
||||||
// TODO: Merge results from JournalDiffCallback into ctx
|
const StatsFetchContext& diffFetchContext) {
|
||||||
(void)ctx;
|
ctx->getFetchContext().merge(diffFetchContext);
|
||||||
(void)journalDiffCallback;
|
|
||||||
return treeResults;
|
return treeResults;
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
#include <folly/Range.h>
|
#include <folly/Range.h>
|
||||||
#include <folly/futures/Future.h>
|
#include <folly/futures/Future.h>
|
||||||
|
|
||||||
#include "eden/fs/store/IObjectStore.h"
|
#include "eden/fs/store/StatsFetchContext.h"
|
||||||
#include "eden/fs/utils/PathFuncs.h"
|
#include "eden/fs/utils/PathFuncs.h"
|
||||||
|
|
||||||
namespace folly {
|
namespace folly {
|
||||||
@ -77,7 +77,7 @@ class DiffContext {
|
|||||||
const GitIgnoreStack* getToplevelIgnore() const;
|
const GitIgnoreStack* getToplevelIgnore() const;
|
||||||
bool isCancelled() const;
|
bool isCancelled() const;
|
||||||
LoadFileFunction getLoadFileContentsFromPath() const;
|
LoadFileFunction getLoadFileContentsFromPath() const;
|
||||||
ObjectFetchContext& getFetchContext() {
|
StatsFetchContext& getFetchContext() {
|
||||||
return fetchContext_;
|
return fetchContext_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,7 +85,7 @@ class DiffContext {
|
|||||||
std::unique_ptr<TopLevelIgnores> topLevelIgnores_;
|
std::unique_ptr<TopLevelIgnores> topLevelIgnores_;
|
||||||
const LoadFileFunction loadFileContentsFromPath_;
|
const LoadFileFunction loadFileContentsFromPath_;
|
||||||
apache::thrift::ResponseChannelRequest* const FOLLY_NULLABLE request_;
|
apache::thrift::ResponseChannelRequest* const FOLLY_NULLABLE request_;
|
||||||
ObjectFetchContext fetchContext_;
|
StatsFetchContext fetchContext_;
|
||||||
};
|
};
|
||||||
} // namespace eden
|
} // namespace eden
|
||||||
} // namespace facebook
|
} // namespace facebook
|
||||||
|
@ -35,7 +35,7 @@ class ObjectFetchContext {
|
|||||||
*
|
*
|
||||||
* Suitable for use as an index into an array of size kObjectTypeEnumMax
|
* Suitable for use as an index into an array of size kObjectTypeEnumMax
|
||||||
*/
|
*/
|
||||||
enum ObjectType {
|
enum ObjectType : unsigned {
|
||||||
Blob,
|
Blob,
|
||||||
BlobMetadata,
|
BlobMetadata,
|
||||||
Tree,
|
Tree,
|
||||||
@ -47,7 +47,7 @@ class ObjectFetchContext {
|
|||||||
*
|
*
|
||||||
* Suitable for use as an index into an array of size kOriginEnumMax.
|
* Suitable for use as an index into an array of size kOriginEnumMax.
|
||||||
*/
|
*/
|
||||||
enum Origin {
|
enum Origin : unsigned {
|
||||||
FromMemoryCache,
|
FromMemoryCache,
|
||||||
FromDiskCache,
|
FromDiskCache,
|
||||||
FromBackingStore,
|
FromBackingStore,
|
||||||
|
53
eden/fs/store/StatsFetchContext.cpp
Normal file
53
eden/fs/store/StatsFetchContext.cpp
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This software may be used and distributed according to the terms of the
|
||||||
|
* GNU General Public License version 2.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "eden/fs/store/StatsFetchContext.h"
|
||||||
|
#include <folly/logging/xlog.h>
|
||||||
|
|
||||||
|
namespace facebook {
|
||||||
|
namespace eden {
|
||||||
|
|
||||||
|
StatsFetchContext::StatsFetchContext(const StatsFetchContext& other) {
|
||||||
|
for (size_t y = 0; y < ObjectFetchContext::kObjectTypeEnumMax; ++y) {
|
||||||
|
for (size_t x = 0; x < ObjectFetchContext::kOriginEnumMax; ++x) {
|
||||||
|
// This could almost certainly use a more relaxed memory ordering.
|
||||||
|
counts_[y][x] = other.counts_[y][x].load();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void StatsFetchContext::didFetch(ObjectType type, const Hash&, Origin origin) {
|
||||||
|
XCHECK(type < ObjectFetchContext::kObjectTypeEnumMax)
|
||||||
|
<< "type is out of range: " << type;
|
||||||
|
XCHECK(origin < ObjectFetchContext::kOriginEnumMax)
|
||||||
|
<< "origin is out of range: " << type;
|
||||||
|
counts_[type][origin].fetch_add(1, std::memory_order_acq_rel);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t StatsFetchContext::countFetchesOfType(ObjectType type) const {
|
||||||
|
XCHECK(type < ObjectFetchContext::kObjectTypeEnumMax)
|
||||||
|
<< "type is out of range: " << type;
|
||||||
|
uint64_t result = 0;
|
||||||
|
for (unsigned origin = 0; origin < ObjectFetchContext::kOriginEnumMax;
|
||||||
|
++origin) {
|
||||||
|
result += counts_[type][origin].load(std::memory_order_acquire);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StatsFetchContext::merge(const StatsFetchContext& other) {
|
||||||
|
for (unsigned type = 0; type < ObjectFetchContext::kObjectTypeEnumMax;
|
||||||
|
++type) {
|
||||||
|
for (unsigned origin = 0; origin < ObjectFetchContext::kOriginEnumMax;
|
||||||
|
++origin) {
|
||||||
|
counts_[type][origin] += other.counts_[type][origin];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace eden
|
||||||
|
} // namespace facebook
|
36
eden/fs/store/StatsFetchContext.h
Normal file
36
eden/fs/store/StatsFetchContext.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This software may be used and distributed according to the terms of the
|
||||||
|
* GNU General Public License version 2.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
#include "eden/fs/store/IObjectStore.h"
|
||||||
|
|
||||||
|
namespace facebook {
|
||||||
|
namespace eden {
|
||||||
|
|
||||||
|
class StatsFetchContext : public ObjectFetchContext {
|
||||||
|
public:
|
||||||
|
StatsFetchContext() = default;
|
||||||
|
StatsFetchContext(const StatsFetchContext& other);
|
||||||
|
|
||||||
|
void didFetch(ObjectType type, const Hash& id, Origin origin) override;
|
||||||
|
|
||||||
|
uint64_t countFetchesOfType(ObjectType type) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sums the counts from another fetch context into this one.
|
||||||
|
*/
|
||||||
|
void merge(const StatsFetchContext& other);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::atomic<uint64_t> counts_[ObjectFetchContext::kObjectTypeEnumMax]
|
||||||
|
[ObjectFetchContext::kOriginEnumMax] = {};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace eden
|
||||||
|
} // namespace facebook
|
Loading…
Reference in New Issue
Block a user