Skip to content

Commit 44791e8

Browse files
committed
[llvm][support] Implement tracing virtual file system
1 parent 779ba60 commit 44791e8

File tree

4 files changed

+134
-31
lines changed

4 files changed

+134
-31
lines changed

clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp

Lines changed: 3 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -13,39 +13,11 @@
1313

1414
using namespace clang::tooling::dependencies;
1515

16-
namespace {
17-
struct InstrumentingFilesystem
18-
: llvm::RTTIExtends<InstrumentingFilesystem, llvm::vfs::ProxyFileSystem> {
19-
unsigned NumStatusCalls = 0;
20-
unsigned NumGetRealPathCalls = 0;
21-
unsigned NumExistsCalls = 0;
22-
23-
using llvm::RTTIExtends<InstrumentingFilesystem,
24-
llvm::vfs::ProxyFileSystem>::RTTIExtends;
25-
26-
llvm::ErrorOr<llvm::vfs::Status> status(const llvm::Twine &Path) override {
27-
++NumStatusCalls;
28-
return ProxyFileSystem::status(Path);
29-
}
30-
31-
std::error_code getRealPath(const llvm::Twine &Path,
32-
llvm::SmallVectorImpl<char> &Output) override {
33-
++NumGetRealPathCalls;
34-
return ProxyFileSystem::getRealPath(Path, Output);
35-
}
36-
37-
bool exists(const llvm::Twine &Path) override {
38-
++NumExistsCalls;
39-
return ProxyFileSystem::exists(Path);
40-
}
41-
};
42-
} // namespace
43-
4416
TEST(DependencyScanningWorkerFilesystem, CacheStatusFailures) {
4517
auto InMemoryFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
4618

4719
auto InstrumentingFS =
48-
llvm::makeIntrusiveRefCnt<InstrumentingFilesystem>(InMemoryFS);
20+
llvm::makeIntrusiveRefCnt<llvm::vfs::TracingFileSystem>(InMemoryFS);
4921

5022
DependencyScanningFilesystemSharedCache SharedCache;
5123
DependencyScanningWorkerFilesystem DepFS(SharedCache, InstrumentingFS);
@@ -71,7 +43,7 @@ TEST(DependencyScanningFilesystem, CacheGetRealPath) {
7143
InMemoryFS->addFile("/bar", 0, llvm::MemoryBuffer::getMemBuffer(""));
7244

7345
auto InstrumentingFS =
74-
llvm::makeIntrusiveRefCnt<InstrumentingFilesystem>(InMemoryFS);
46+
llvm::makeIntrusiveRefCnt<llvm::vfs::TracingFileSystem>(InMemoryFS);
7547

7648
DependencyScanningFilesystemSharedCache SharedCache;
7749
DependencyScanningWorkerFilesystem DepFS(SharedCache, InstrumentingFS);
@@ -157,7 +129,7 @@ TEST(DependencyScanningFilesystem, RealPathAndStatusInvariants) {
157129
TEST(DependencyScanningFilesystem, CacheStatOnExists) {
158130
auto InMemoryFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
159131
auto InstrumentingFS =
160-
llvm::makeIntrusiveRefCnt<InstrumentingFilesystem>(InMemoryFS);
132+
llvm::makeIntrusiveRefCnt<llvm::vfs::TracingFileSystem>(InMemoryFS);
161133
InMemoryFS->setCurrentWorkingDirectory("/");
162134
InMemoryFS->addFile("/foo", 0, llvm::MemoryBuffer::getMemBuffer(""));
163135
InMemoryFS->addFile("/bar", 0, llvm::MemoryBuffer::getMemBuffer(""));

llvm/include/llvm/Support/VirtualFileSystem.h

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1129,6 +1129,60 @@ class YAMLVFSWriter {
11291129
void write(llvm::raw_ostream &OS);
11301130
};
11311131

1132+
/// File system that tracks the number of calls to the underlying file system.
1133+
/// This is particularly useful when wrapped around \c RealFileSystem to add
1134+
/// lightweight tracking of expensive syscalls.
1135+
class TracingFileSystem
1136+
: public llvm::RTTIExtends<TracingFileSystem, ProxyFileSystem> {
1137+
public:
1138+
static const char ID;
1139+
1140+
std::size_t NumStatusCalls = 0;
1141+
std::size_t NumOpenFileForReadCalls = 0;
1142+
std::size_t NumDirBeginCalls = 0;
1143+
std::size_t NumGetRealPathCalls = 0;
1144+
std::size_t NumExistsCalls = 0;
1145+
std::size_t NumIsLocalCalls = 0;
1146+
1147+
TracingFileSystem(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS)
1148+
: RTTIExtends(std::move(FS)) {}
1149+
1150+
ErrorOr<Status> status(const Twine &Path) override {
1151+
++NumStatusCalls;
1152+
return ProxyFileSystem::status(Path);
1153+
}
1154+
1155+
ErrorOr<std::unique_ptr<File>> openFileForRead(const Twine &Path) override {
1156+
++NumOpenFileForReadCalls;
1157+
return ProxyFileSystem::openFileForRead(Path);
1158+
}
1159+
1160+
directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override {
1161+
++NumDirBeginCalls;
1162+
return ProxyFileSystem::dir_begin(Dir, EC);
1163+
}
1164+
1165+
std::error_code getRealPath(const Twine &Path,
1166+
SmallVectorImpl<char> &Output) override {
1167+
++NumGetRealPathCalls;
1168+
return ProxyFileSystem::getRealPath(Path, Output);
1169+
}
1170+
1171+
bool exists(const Twine &Path) override {
1172+
++NumExistsCalls;
1173+
return ProxyFileSystem::exists(Path);
1174+
}
1175+
1176+
std::error_code isLocal(const Twine &Path, bool &Result) override {
1177+
++NumIsLocalCalls;
1178+
return ProxyFileSystem::isLocal(Path, Result);
1179+
}
1180+
1181+
protected:
1182+
void printImpl(raw_ostream &OS, PrintType Type,
1183+
unsigned IndentLevel) const override;
1184+
};
1185+
11321186
} // namespace vfs
11331187
} // namespace llvm
11341188

llvm/lib/Support/VirtualFileSystem.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2933,8 +2933,21 @@ recursive_directory_iterator::increment(std::error_code &EC) {
29332933
return *this;
29342934
}
29352935

2936+
void TracingFileSystem::printImpl(raw_ostream &OS, PrintType Type,
2937+
unsigned IndentLevel) const {
2938+
printIndent(OS, IndentLevel);
2939+
OS << "TracingFileSystem\n";
2940+
if (Type == PrintType::Summary)
2941+
return;
2942+
2943+
if (Type == PrintType::Contents)
2944+
Type = PrintType::Summary;
2945+
getUnderlyingFS().print(OS, Type, IndentLevel + 1);
2946+
}
2947+
29362948
const char FileSystem::ID = 0;
29372949
const char OverlayFileSystem::ID = 0;
29382950
const char ProxyFileSystem::ID = 0;
29392951
const char InMemoryFileSystem::ID = 0;
29402952
const char RedirectingFileSystem::ID = 0;
2953+
const char TracingFileSystem::ID = 0;

llvm/unittests/Support/VirtualFileSystemTest.cpp

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3560,3 +3560,67 @@ TEST(RedirectingFileSystemTest, ExistsRedirectOnly) {
35603560
EXPECT_FALSE(Redirecting->exists("/b"));
35613561
EXPECT_TRUE(Redirecting->exists("/vfile"));
35623562
}
3563+
3564+
TEST(TracingFileSystemTest, TracingWorks) {
3565+
auto InMemoryFS = makeIntrusiveRefCnt<vfs::InMemoryFileSystem>();
3566+
auto TracingFS =
3567+
makeIntrusiveRefCnt<vfs::TracingFileSystem>(std::move(InMemoryFS));
3568+
3569+
EXPECT_EQ(TracingFS->NumStatusCalls, 0u);
3570+
EXPECT_EQ(TracingFS->NumOpenFileForReadCalls, 0u);
3571+
EXPECT_EQ(TracingFS->NumDirBeginCalls, 0u);
3572+
EXPECT_EQ(TracingFS->NumGetRealPathCalls, 0u);
3573+
EXPECT_EQ(TracingFS->NumExistsCalls, 0u);
3574+
EXPECT_EQ(TracingFS->NumIsLocalCalls, 0u);
3575+
3576+
(void)TracingFS->status("/foo");
3577+
EXPECT_EQ(TracingFS->NumStatusCalls, 1u);
3578+
EXPECT_EQ(TracingFS->NumOpenFileForReadCalls, 0u);
3579+
EXPECT_EQ(TracingFS->NumDirBeginCalls, 0u);
3580+
EXPECT_EQ(TracingFS->NumGetRealPathCalls, 0u);
3581+
EXPECT_EQ(TracingFS->NumExistsCalls, 0u);
3582+
EXPECT_EQ(TracingFS->NumIsLocalCalls, 0u);
3583+
3584+
(void)TracingFS->openFileForRead("/foo");
3585+
EXPECT_EQ(TracingFS->NumStatusCalls, 1u);
3586+
EXPECT_EQ(TracingFS->NumOpenFileForReadCalls, 1u);
3587+
EXPECT_EQ(TracingFS->NumDirBeginCalls, 0u);
3588+
EXPECT_EQ(TracingFS->NumGetRealPathCalls, 0u);
3589+
EXPECT_EQ(TracingFS->NumExistsCalls, 0u);
3590+
EXPECT_EQ(TracingFS->NumIsLocalCalls, 0u);
3591+
3592+
std::error_code EC;
3593+
(void)TracingFS->dir_begin("/foo", EC);
3594+
EXPECT_EQ(TracingFS->NumStatusCalls, 1u);
3595+
EXPECT_EQ(TracingFS->NumOpenFileForReadCalls, 1u);
3596+
EXPECT_EQ(TracingFS->NumDirBeginCalls, 1u);
3597+
EXPECT_EQ(TracingFS->NumGetRealPathCalls, 0u);
3598+
EXPECT_EQ(TracingFS->NumExistsCalls, 0u);
3599+
EXPECT_EQ(TracingFS->NumIsLocalCalls, 0u);
3600+
3601+
SmallString<128> RealPath;
3602+
(void)TracingFS->getRealPath("/foo", RealPath);
3603+
EXPECT_EQ(TracingFS->NumStatusCalls, 1u);
3604+
EXPECT_EQ(TracingFS->NumOpenFileForReadCalls, 1u);
3605+
EXPECT_EQ(TracingFS->NumDirBeginCalls, 1u);
3606+
EXPECT_EQ(TracingFS->NumGetRealPathCalls, 1u);
3607+
EXPECT_EQ(TracingFS->NumExistsCalls, 0u);
3608+
EXPECT_EQ(TracingFS->NumIsLocalCalls, 0u);
3609+
3610+
(void)TracingFS->exists("/foo");
3611+
EXPECT_EQ(TracingFS->NumStatusCalls, 1u);
3612+
EXPECT_EQ(TracingFS->NumOpenFileForReadCalls, 1u);
3613+
EXPECT_EQ(TracingFS->NumDirBeginCalls, 1u);
3614+
EXPECT_EQ(TracingFS->NumGetRealPathCalls, 1u);
3615+
EXPECT_EQ(TracingFS->NumExistsCalls, 1u);
3616+
EXPECT_EQ(TracingFS->NumIsLocalCalls, 0u);
3617+
3618+
bool IsLocal;
3619+
(void)TracingFS->isLocal("/foo", IsLocal);
3620+
EXPECT_EQ(TracingFS->NumStatusCalls, 1u);
3621+
EXPECT_EQ(TracingFS->NumOpenFileForReadCalls, 1u);
3622+
EXPECT_EQ(TracingFS->NumDirBeginCalls, 1u);
3623+
EXPECT_EQ(TracingFS->NumGetRealPathCalls, 1u);
3624+
EXPECT_EQ(TracingFS->NumExistsCalls, 1u);
3625+
EXPECT_EQ(TracingFS->NumIsLocalCalls, 1u);
3626+
}

0 commit comments

Comments
 (0)