mirror of
https://github.com/facebook/sapling.git
synced 2024-10-09 16:31:02 +03:00
949df974db
Summary: Whenever a file is modified in an EdenFS mount and a watchman subscription is active, watchman will be nodified and will issue a getFilesChangedSince Thrift call. In order to do that, Watchman ends up always re-creating a new connection to EdenFS, causing the .eden/socket or .eden/config to be re-read in order to find EdenFS's socket. For workloads with heavy write traffic to EdenFS, this readlink/read can add up. On Windows, writing ~2.5GB worth of data lead Watchman to read over 650MB worth of data from the .eden/config! Reviewed By: kmancini Differential Revision: D29508654 fbshipit-source-id: 60440d645340bc4fe16ea9618d7a5080740e4d87
127 lines
3.5 KiB
C++
127 lines
3.5 KiB
C++
/*
|
|
* 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 <folly/io/async/EventBaseThread.h>
|
|
#include <thrift/lib/cpp2/async/HeaderClientChannel.h>
|
|
#include "eden/fs/benchharness/Bench.h"
|
|
#include "eden/fs/service/gen-cpp2/EdenService.h"
|
|
#include "eden/fs/utils/PathFuncs.h"
|
|
#include "watchman/cppclient/WatchmanClient.h"
|
|
|
|
DEFINE_string(query, "", "Query to run");
|
|
DEFINE_string(repo, "", "Repository to run the query against");
|
|
DEFINE_string(watchman_socket, "", "Socket to the watchman daemon");
|
|
|
|
namespace {
|
|
|
|
using namespace facebook::eden;
|
|
using namespace watchman;
|
|
|
|
AbsolutePath validateArguments() {
|
|
if (FLAGS_query.empty()) {
|
|
throw std::invalid_argument("A query argument must be passed in");
|
|
}
|
|
|
|
if (FLAGS_repo.empty()) {
|
|
throw std::invalid_argument("A repo must be passed in");
|
|
}
|
|
|
|
return AbsolutePath{FLAGS_repo};
|
|
}
|
|
|
|
void eden_glob(benchmark::State& state) {
|
|
auto path = validateArguments();
|
|
|
|
auto socketPath = path + ".eden/socket"_relpath;
|
|
|
|
auto evbThread = folly::EventBaseThread();
|
|
auto eventBase = evbThread.getEventBase();
|
|
|
|
auto socket = folly::AsyncSocket::newSocket(
|
|
eventBase, folly::SocketAddress::makeFromPath(socketPath.stringPiece()));
|
|
auto channel =
|
|
apache::thrift::HeaderClientChannel::newChannel(std::move(socket));
|
|
auto client = std::make_unique<EdenServiceAsyncClient>(std::move(channel));
|
|
|
|
GlobParams param;
|
|
param.mountPoint_ref() = path.stringPiece();
|
|
param.globs_ref() = std::vector<std::string>{FLAGS_query};
|
|
param.includeDotfiles_ref() = false;
|
|
param.prefetchFiles_ref() = false;
|
|
param.suppressFileList_ref() = false;
|
|
param.wantDtype_ref() = false;
|
|
param.prefetchMetadata_ref() = false;
|
|
|
|
for (auto _ : state) {
|
|
auto start = std::chrono::high_resolution_clock::now();
|
|
auto result = client->semifuture_globFiles(param).via(eventBase).get();
|
|
auto end = std::chrono::high_resolution_clock::now();
|
|
|
|
benchmark::DoNotOptimize(result);
|
|
|
|
auto elapsed =
|
|
std::chrono::duration_cast<std::chrono::duration<double>>(end - start);
|
|
state.SetIterationTime(elapsed.count());
|
|
}
|
|
}
|
|
|
|
void watchman_glob(benchmark::State& state) {
|
|
auto path = validateArguments();
|
|
|
|
auto evbThread = folly::EventBaseThread();
|
|
auto eventBase = evbThread.getEventBase();
|
|
|
|
folly::Optional<std::string> sockPath;
|
|
if (!FLAGS_watchman_socket.empty()) {
|
|
sockPath = FLAGS_watchman_socket;
|
|
}
|
|
|
|
WatchmanClient client(eventBase, std::move(sockPath));
|
|
client.connect().get();
|
|
auto watch = client.watch(path.stringPiece()).get();
|
|
|
|
folly::dynamic query =
|
|
folly::dynamic::object("glob", folly::dynamic::array(FLAGS_query))(
|
|
"fields", folly::dynamic::array("name"));
|
|
|
|
for (auto _ : state) {
|
|
auto start = std::chrono::high_resolution_clock::now();
|
|
auto res = client.query(query, watch).get();
|
|
auto end = std::chrono::high_resolution_clock::now();
|
|
|
|
benchmark::DoNotOptimize(res);
|
|
|
|
auto elapsed =
|
|
std::chrono::duration_cast<std::chrono::duration<double>>(end - start);
|
|
state.SetIterationTime(elapsed.count());
|
|
}
|
|
}
|
|
|
|
BENCHMARK(eden_glob)
|
|
->UseManualTime()
|
|
->Unit(benchmark::kMillisecond)
|
|
->Threads(1)
|
|
->Threads(2)
|
|
->Threads(4)
|
|
->Threads(8)
|
|
->Threads(16)
|
|
->Threads(32);
|
|
|
|
BENCHMARK(watchman_glob)
|
|
->UseManualTime()
|
|
->Unit(benchmark::kMillisecond)
|
|
->Threads(1)
|
|
->Threads(2)
|
|
->Threads(4)
|
|
->Threads(8)
|
|
->Threads(16)
|
|
->Threads(32);
|
|
|
|
} // namespace
|
|
|
|
EDEN_BENCHMARK_MAIN();
|