sapling/eden/fs/benchmarks/glob.cpp
Xavier Deguillard 949df974db pool eden thrift connections
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
2021-08-10 18:57:52 -07:00

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();