Skip to content

Commit b395e90

Browse files
committed
[llvm][support] Implement tracing virtual file system
1 parent a9111d4 commit b395e90

File tree

4 files changed

+113
-24
lines changed

4 files changed

+113
-24
lines changed

clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp

Lines changed: 2 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -13,33 +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-
22-
using llvm::RTTIExtends<InstrumentingFilesystem,
23-
llvm::vfs::ProxyFileSystem>::RTTIExtends;
24-
25-
llvm::ErrorOr<llvm::vfs::Status> status(const llvm::Twine &Path) override {
26-
++NumStatusCalls;
27-
return ProxyFileSystem::status(Path);
28-
}
29-
30-
std::error_code getRealPath(const llvm::Twine &Path,
31-
llvm::SmallVectorImpl<char> &Output) override {
32-
++NumGetRealPathCalls;
33-
return ProxyFileSystem::getRealPath(Path, Output);
34-
}
35-
};
36-
} // namespace
37-
3816
TEST(DependencyScanningWorkerFilesystem, CacheStatusFailures) {
3917
auto InMemoryFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
4018

4119
auto InstrumentingFS =
42-
llvm::makeIntrusiveRefCnt<InstrumentingFilesystem>(InMemoryFS);
20+
llvm::makeIntrusiveRefCnt<llvm::vfs::TracingFileSystem>(InMemoryFS);
4321

4422
DependencyScanningFilesystemSharedCache SharedCache;
4523
DependencyScanningWorkerFilesystem DepFS(SharedCache, InstrumentingFS);
@@ -65,7 +43,7 @@ TEST(DependencyScanningFilesystem, CacheGetRealPath) {
6543
InMemoryFS->addFile("/bar", 0, llvm::MemoryBuffer::getMemBuffer(""));
6644

6745
auto InstrumentingFS =
68-
llvm::makeIntrusiveRefCnt<InstrumentingFilesystem>(InMemoryFS);
46+
llvm::makeIntrusiveRefCnt<llvm::vfs::TracingFileSystem>(InMemoryFS);
6947

7048
DependencyScanningFilesystemSharedCache SharedCache;
7149
DependencyScanningWorkerFilesystem DepFS(SharedCache, InstrumentingFS);

llvm/include/llvm/Support/VirtualFileSystem.h

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1125,6 +1125,54 @@ class YAMLVFSWriter {
11251125
void write(llvm::raw_ostream &OS);
11261126
};
11271127

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

llvm/lib/Support/VirtualFileSystem.cpp

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

2880+
void TracingFileSystem::printImpl(raw_ostream &OS, PrintType Type,
2881+
unsigned IndentLevel) const {
2882+
printIndent(OS, IndentLevel);
2883+
OS << "TracingFileSystem\n";
2884+
if (Type == PrintType::Summary)
2885+
return;
2886+
2887+
if (Type == PrintType::Contents)
2888+
Type = PrintType::Summary;
2889+
getUnderlyingFS().print(OS, Type, IndentLevel + 1);
2890+
}
2891+
28802892
const char FileSystem::ID = 0;
28812893
const char OverlayFileSystem::ID = 0;
28822894
const char ProxyFileSystem::ID = 0;
28832895
const char InMemoryFileSystem::ID = 0;
28842896
const char RedirectingFileSystem::ID = 0;
2897+
const char TracingFileSystem::ID = 0;

llvm/unittests/Support/VirtualFileSystemTest.cpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3395,3 +3395,53 @@ TEST(RedirectingFileSystemTest, ExternalPaths) {
33953395

33963396
EXPECT_EQ(CheckFS->SeenPaths, Expected);
33973397
}
3398+
3399+
TEST(TracingFileSystemTest, TracingWorks) {
3400+
auto InMemoryFS = makeIntrusiveRefCnt<vfs::InMemoryFileSystem>();
3401+
auto TracingFS =
3402+
makeIntrusiveRefCnt<vfs::TracingFileSystem>(std::move(InMemoryFS));
3403+
3404+
EXPECT_EQ(TracingFS->NumStatusCalls, 0u);
3405+
EXPECT_EQ(TracingFS->NumOpenFileForReadCalls, 0u);
3406+
EXPECT_EQ(TracingFS->NumDirBeginCalls, 0u);
3407+
EXPECT_EQ(TracingFS->NumGetRealPathCalls, 0u);
3408+
EXPECT_EQ(TracingFS->NumIsLocalCalls, 0u);
3409+
3410+
(void)TracingFS->status("/foo");
3411+
EXPECT_EQ(TracingFS->NumStatusCalls, 1u);
3412+
EXPECT_EQ(TracingFS->NumOpenFileForReadCalls, 0u);
3413+
EXPECT_EQ(TracingFS->NumDirBeginCalls, 0u);
3414+
EXPECT_EQ(TracingFS->NumGetRealPathCalls, 0u);
3415+
EXPECT_EQ(TracingFS->NumIsLocalCalls, 0u);
3416+
3417+
(void)TracingFS->openFileForRead("/foo");
3418+
EXPECT_EQ(TracingFS->NumStatusCalls, 1u);
3419+
EXPECT_EQ(TracingFS->NumOpenFileForReadCalls, 1u);
3420+
EXPECT_EQ(TracingFS->NumDirBeginCalls, 0u);
3421+
EXPECT_EQ(TracingFS->NumGetRealPathCalls, 0u);
3422+
EXPECT_EQ(TracingFS->NumIsLocalCalls, 0u);
3423+
3424+
std::error_code EC;
3425+
(void)TracingFS->dir_begin("/foo", EC);
3426+
EXPECT_EQ(TracingFS->NumStatusCalls, 1u);
3427+
EXPECT_EQ(TracingFS->NumOpenFileForReadCalls, 1u);
3428+
EXPECT_EQ(TracingFS->NumDirBeginCalls, 1u);
3429+
EXPECT_EQ(TracingFS->NumGetRealPathCalls, 0u);
3430+
EXPECT_EQ(TracingFS->NumIsLocalCalls, 0u);
3431+
3432+
SmallString<128> RealPath;
3433+
(void)TracingFS->getRealPath("/foo", RealPath);
3434+
EXPECT_EQ(TracingFS->NumStatusCalls, 1u);
3435+
EXPECT_EQ(TracingFS->NumOpenFileForReadCalls, 1u);
3436+
EXPECT_EQ(TracingFS->NumDirBeginCalls, 1u);
3437+
EXPECT_EQ(TracingFS->NumGetRealPathCalls, 1u);
3438+
EXPECT_EQ(TracingFS->NumIsLocalCalls, 0u);
3439+
3440+
bool IsLocal;
3441+
(void)TracingFS->isLocal("/foo", IsLocal);
3442+
EXPECT_EQ(TracingFS->NumStatusCalls, 1u);
3443+
EXPECT_EQ(TracingFS->NumOpenFileForReadCalls, 1u);
3444+
EXPECT_EQ(TracingFS->NumDirBeginCalls, 1u);
3445+
EXPECT_EQ(TracingFS->NumGetRealPathCalls, 1u);
3446+
EXPECT_EQ(TracingFS->NumIsLocalCalls, 1u);
3447+
}

0 commit comments

Comments
 (0)