Skip to content

Commit b164fdb

Browse files
authored
Merge pull request swiftlang#12297 from benlangmuir/sourcekitd-stats
[sourcekitd] Add a request to get statistics from the service
2 parents aed39a6 + 9c7d923 commit b164fdb

File tree

14 files changed

+250
-10
lines changed

14 files changed

+250
-10
lines changed

test/SourceKit/Misc/stats.swift

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
func foo() {}
2+
3+
// RUN: %sourcekitd-test -req=syntax-map %s == -req=stats | %FileCheck %s -check-prefix=SYNTAX_1
4+
5+
// SYNTAX_1: 2 {{.*}} source.statistic.num-requests
6+
// SYNTAX_1: 0 {{.*}} source.statistic.num-semantic-requests
7+
// SYNTAX_1: 0 {{.*}} source.statistic.num-ast-builds
8+
// SYNTAX_1: 1 {{.*}} source.statistic.num-open-documents
9+
// SYNTAX_1: 1 {{.*}} source.statistic.max-open-documents
10+
11+
// RUN: %sourcekitd-test -req=syntax-map %s == -req=close %s == -req=stats | %FileCheck %s -check-prefix=SYNTAX_2
12+
13+
// SYNTAX_2: 3 {{.*}} source.statistic.num-requests
14+
// SYNTAX_2: 0 {{.*}} source.statistic.num-semantic-requests
15+
// SYNTAX_2: 0 {{.*}} source.statistic.num-ast-builds
16+
// SYNTAX_2: 0 {{.*}} source.statistic.num-open-documents
17+
// SYNTAX_2: 1 {{.*}} source.statistic.max-open-documents
18+
19+
// RUN: %sourcekitd-test -req=sema %s -- %s == -req=stats | %FileCheck %s -check-prefix=SEMA_1
20+
21+
// SEMA_1: 3 {{.*}} source.statistic.num-requests
22+
// SEMA_1: 0 {{.*}} source.statistic.num-semantic-requests
23+
// SEMA_1: 1 {{.*}} source.statistic.num-ast-builds
24+
// SEMA_1: 1 {{.*}} source.statistic.num-asts-in-memory
25+
// SEMA_1: 1 {{.*}} source.statistic.max-asts-in-memory
26+
// SEMA_1: 0 {{.*}} source.statistic.num-ast-cache-hits
27+
// SEMA_1: 0 {{.*}} source.statistic.num-ast-snaphost-uses
28+
29+
// RUN: %sourcekitd-test -req=sema %s -- %s == -req=edit -pos=1:1 -replace=" " %s == -req=stats | %FileCheck %s -check-prefix=SEMA_2
30+
31+
// SEMA_2: 5 {{.*}} source.statistic.num-requests
32+
// SEMA_2: 0 {{.*}} source.statistic.num-semantic-requests
33+
// SEMA_2: 2 {{.*}} source.statistic.num-ast-builds
34+
// SEMA_2: 1 {{.*}} source.statistic.num-asts-in-memory
35+
// SEMA_2: 2 {{.*}} source.statistic.max-asts-in-memory
36+
// SEMA_2: 0 {{.*}} source.statistic.num-ast-cache-hits
37+
// SEMA_2: 0 {{.*}} source.statistic.num-ast-snaphost-uses
38+
39+
// RUN: %sourcekitd-test -req=sema %s -- %s == -req=cursor -pos=1:6 %s -- %s == -req=stats | %FileCheck %s -check-prefix=SEMA_3
40+
41+
// SEMA_3: 4 {{.*}} source.statistic.num-requests
42+
// SEMA_3: 1 {{.*}} source.statistic.num-semantic-requests
43+
// SEMA_3: 1 {{.*}} source.statistic.num-ast-builds
44+
// SEMA_3: 1 {{.*}} source.statistic.num-asts-in-memory
45+
// SEMA_3: 1 {{.*}} source.statistic.max-asts-in-memory
46+
// SEMA_3: 0 {{.*}} source.statistic.num-ast-cache-hits
47+
// SEMA_3: 1 {{.*}} source.statistic.num-ast-snaphost-uses
48+
49+
// RUN: %sourcekitd-test -req=sema %s -- %s == -req=related-idents -pos=1:6 %s -- %s == -req=stats | %FileCheck %s -check-prefix=SEMA_4
50+
51+
// SEMA_4: 4 {{.*}} source.statistic.num-requests
52+
// SEMA_4: 1 {{.*}} source.statistic.num-semantic-requests
53+
// SEMA_4: 1 {{.*}} source.statistic.num-ast-builds
54+
// SEMA_4: 1 {{.*}} source.statistic.num-asts-in-memory
55+
// SEMA_4: 1 {{.*}} source.statistic.max-asts-in-memory
56+
// SEMA_4: 1 {{.*}} source.statistic.num-ast-cache-hits
57+
// SEMA_4: 0 {{.*}} source.statistic.num-ast-snaphost-uses

tools/SourceKit/include/SourceKit/Core/LangSupport.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,9 @@ class OptionsDictionary {
251251
virtual bool valueForOption(UIdent Key, StringRef &Val) = 0;
252252
};
253253

254+
struct Statistic;
255+
typedef std::function<void(ArrayRef<Statistic *> stats)> StatisticsReceiver;
256+
254257
struct RefactoringInfo {
255258
UIdent Kind;
256259
StringRef KindName;
@@ -626,6 +629,8 @@ class LangSupport {
626629
StringRef ModuleName,
627630
ArrayRef<const char *> Args,
628631
DocInfoConsumer &Consumer) = 0;
632+
633+
virtual void getStatistics(StatisticsReceiver) = 0;
629634
};
630635

631636
} // namespace SourceKit

tools/SourceKit/include/SourceKit/Core/ProtocolUIDs.def

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ KEY(NameKind, "key.namekind")
107107
KEY(LocalizationKey, "key.localization_key")
108108
KEY(IsZeroArgSelector, "key.is_zero_arg_selector")
109109
KEY(SwiftVersion, "key.swift_version")
110+
KEY(Value, "key.value")
110111

111112
KEY(EnableDiagnostics, "key.enablediagnostics")
112113
KEY(GroupName, "key.groupname")
@@ -181,6 +182,7 @@ REQUEST(BuildSettingsRegister, "source.request.buildsettings.register")
181182
REQUEST(ModuleGroups, "source.request.module.groups")
182183
REQUEST(NameTranslation, "source.request.name.translation")
183184
REQUEST(MarkupToXML, "source.request.convert.markup.xml")
185+
REQUEST(Statistics, "source.request.statistics")
184186

185187
REQUEST(SyntacticRename, "source.request.syntacticrename")
186188
REQUEST(FindRenameRanges, "source.request.find-syntactic-rename-ranges")
@@ -340,6 +342,9 @@ KIND(Reference, "source.syntacticrename.reference")
340342
KIND(Call, "source.syntacticrename.call")
341343
KIND(Unknown, "source.syntacticrename.unknown")
342344

345+
KIND(StatNumRequests, "source.statistic.num-requests")
346+
KIND(StatNumSemaRequests, "source.statistic.num-semantic-requests")
347+
343348
#undef KIND
344349
#undef REQUEST
345350
#undef KEY
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
//===--- Statistic.h - ------------------------------------------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef LLVM_SOURCEKIT_SUPPORT_STATISTIC_H
14+
#define LLVM_SOURCEKIT_SUPPORT_STATISTIC_H
15+
16+
#include "SourceKit/Support/UIdent.h"
17+
#include <atomic>
18+
#include <string>
19+
20+
namespace SourceKit {
21+
22+
struct Statistic {
23+
const UIdent name;
24+
const std::string description;
25+
std::atomic<int64_t> value = {0};
26+
27+
Statistic(UIdent name, std::string description)
28+
: name(name), description(std::move(description)) {}
29+
30+
int64_t operator++() {
31+
return 1 + value.fetch_add(1, std::memory_order_relaxed);
32+
}
33+
int64_t operator--() {
34+
return value.fetch_sub(1, std::memory_order_relaxed) - 1;
35+
}
36+
37+
void updateMax(int64_t newValue) {
38+
int64_t prev = value.load(std::memory_order_relaxed);
39+
// Note: compare_exchange_weak updates 'prev' if it fails.
40+
while (newValue > prev && !value.compare_exchange_weak(
41+
prev, newValue, std::memory_order_relaxed)) {
42+
}
43+
}
44+
};
45+
46+
} // namespace SourceKit
47+
48+
#endif // LLVM_SOURCEKIT_SUPPORT_STATISTIC_H

tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -158,13 +158,15 @@ void InvocationOptions::profile(llvm::FoldingSetNodeID &ID) const {
158158
namespace SourceKit {
159159
struct ASTUnit::Implementation {
160160
const uint64_t Generation;
161+
SwiftStatistics &Stats;
161162
SmallVector<ImmutableTextSnapshotRef, 4> Snapshots;
162163
EditorDiagConsumer CollectDiagConsumer;
163164
CompilerInstance CompInst;
164165
OwnedResolver TypeResolver{ nullptr, nullptr };
165166
WorkQueue Queue{ WorkQueue::Dequeuing::Serial, "sourcekit.swift.ConsumeAST" };
166167

167-
Implementation(uint64_t Generation) : Generation(Generation) {}
168+
Implementation(uint64_t Generation, SwiftStatistics &Statistics)
169+
: Generation(Generation), Stats(Statistics) {}
168170

169171
void consumeAsync(SwiftASTConsumerRef ASTConsumer, ASTUnitRef ASTRef);
170172
};
@@ -185,10 +187,14 @@ namespace SourceKit {
185187
});
186188
}
187189

188-
ASTUnit::ASTUnit(uint64_t Generation) : Impl(*new Implementation(Generation)) {
190+
ASTUnit::ASTUnit(uint64_t Generation, SwiftStatistics &Stats)
191+
: Impl(*new Implementation(Generation, Stats)) {
192+
auto numASTs = ++Stats.numASTsInMem;
193+
Stats.maxASTsInMem.updateMax(numASTs);
189194
}
190195

191196
ASTUnit::~ASTUnit() {
197+
--Impl.Stats.numASTsInMem;
192198
delete &Impl;
193199
}
194200

@@ -307,10 +313,12 @@ struct CacheKeyHashInfo<ASTKey> {
307313

308314
struct SwiftASTManager::Implementation {
309315
explicit Implementation(SwiftLangSupport &LangSupport)
310-
: EditorDocs(LangSupport.getEditorDocuments()),
311-
RuntimeResourcePath(LangSupport.getRuntimeResourcePath()) { }
316+
: EditorDocs(LangSupport.getEditorDocuments()),
317+
Stats(LangSupport.getStatistics()),
318+
RuntimeResourcePath(LangSupport.getRuntimeResourcePath()) {}
312319

313320
SwiftEditorDocumentFileMap &EditorDocs;
321+
SwiftStatistics &Stats;
314322
std::string RuntimeResourcePath;
315323
SourceManager SourceMgr;
316324
Cache<ASTKey, ASTProducerRef> ASTCache{ "sourcekit.swift.ASTCache" };
@@ -488,6 +496,7 @@ void SwiftASTManager::processASTAsync(SwiftInvocationRef InvokRef,
488496

489497
if (ASTUnitRef Unit = Producer->getExistingAST()) {
490498
if (ASTConsumer->canUseASTWithSnapshots(Unit->getSnapshots())) {
499+
++Impl.Stats.numASTsUsedWithSnaphots;
491500
Unit->Impl.consumeAsync(std::move(ASTConsumer), Unit);
492501
return;
493502
}
@@ -616,6 +625,8 @@ ASTUnitRef ASTProducer::getASTUnitImpl(SwiftASTManager::Implementation &MgrImpl,
616625
ASTProducerRef ThisProducer = this;
617626
MgrImpl.ASTCache.set(InvokRef->Impl.Key, ThisProducer);
618627
}
628+
} else {
629+
++MgrImpl.Stats.numASTCacheHits;
619630
}
620631

621632
return AST;
@@ -732,6 +743,8 @@ static std::atomic<uint64_t> ASTUnitGeneration{ 0 };
732743
ASTUnitRef ASTProducer::createASTUnit(SwiftASTManager::Implementation &MgrImpl,
733744
ArrayRef<ImmutableTextSnapshotRef> Snapshots,
734745
std::string &Error) {
746+
++MgrImpl.Stats.numASTBuilds;
747+
735748
Stamps.clear();
736749
DependencyStamps.clear();
737750

@@ -770,7 +783,7 @@ ASTUnitRef ASTProducer::createASTUnit(SwiftASTManager::Implementation &MgrImpl,
770783
TraceInfo.Args.Args = Opts.Args;
771784
}
772785

773-
ASTUnitRef ASTRef = new ASTUnit(++ASTUnitGeneration);
786+
ASTUnitRef ASTRef = new ASTUnit(++ASTUnitGeneration, MgrImpl.Stats);
774787
for (auto &Content : Contents) {
775788
if (Content.Snapshot)
776789
ASTRef->Impl.Snapshots.push_back(Content.Snapshot);

tools/SourceKit/lib/SwiftLang/SwiftASTManager.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ namespace SourceKit {
4040
class SwiftEditorDocumentFileMap;
4141
class SwiftLangSupport;
4242
class SwiftInvocation;
43+
struct SwiftStatistics;
4344
typedef RefPtr<SwiftInvocation> SwiftInvocationRef;
4445
class EditorDiagConsumer;
4546

@@ -48,7 +49,7 @@ class ASTUnit : public SourceKit::ThreadSafeRefCountedBase<ASTUnit> {
4849
struct Implementation;
4950
Implementation &Impl;
5051

51-
explicit ASTUnit(uint64_t Generation);
52+
explicit ASTUnit(uint64_t Generation, SwiftStatistics &Statistics);
5253
~ASTUnit();
5354

5455
swift::CompilerInstance &getCompilerInstance() const;

tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2073,6 +2073,8 @@ void SwiftLangSupport::editorOpen(StringRef Name, llvm::MemoryBuffer *Buf,
20732073
LOG_WARN_FUNC("Document already exists in editorOpen(..): " << Name);
20742074
Snapshot = nullptr;
20752075
}
2076+
auto numOpen = ++Stats.numOpenDocs;
2077+
Stats.maxOpenDocs.updateMax(numOpen);
20762078
}
20772079

20782080
if (!Snapshot) {
@@ -2095,8 +2097,12 @@ void SwiftLangSupport::editorOpen(StringRef Name, llvm::MemoryBuffer *Buf,
20952097

20962098
void SwiftLangSupport::editorClose(StringRef Name, bool RemoveCache) {
20972099
auto Removed = EditorDocuments.remove(Name);
2098-
if (!Removed)
2100+
if (Removed) {
2101+
--Stats.numOpenDocs;
2102+
} else {
20992103
IFaceGenContexts.remove(Name);
2104+
}
2105+
21002106
if (Removed && RemoveCache)
21012107
Removed->removeCachedAST();
21022108
// FIXME: Report error if Name did not apply to anything ?

tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -715,6 +715,14 @@ std::string SwiftLangSupport::resolvePathSymlinks(StringRef FilePath) {
715715
#endif
716716
}
717717

718+
void SwiftLangSupport::getStatistics(StatisticsReceiver receiver) {
719+
std::vector<Statistic *> stats = {
720+
#define SWIFT_STATISTIC(VAR, UID, DESC) &Stats.VAR,
721+
#include "SwiftStatistics.def"
722+
};
723+
receiver(stats);
724+
}
725+
718726
CloseClangModuleFiles::~CloseClangModuleFiles() {
719727
clang::Preprocessor &PP = loader.getClangPreprocessor();
720728
clang::ModuleMap &ModMap = PP.getHeaderSearchInfo().getModuleMap();

tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "SwiftInterfaceGenContext.h"
1818
#include "SourceKit/Core/LangSupport.h"
1919
#include "SourceKit/Support/Concurrency.h"
20+
#include "SourceKit/Support/Statistic.h"
2021
#include "SourceKit/Support/ThreadSafeRefCntPtr.h"
2122
#include "SourceKit/Support/Tracing.h"
2223
#include "swift/Basic/ThreadSafeRefCounted.h"
@@ -250,6 +251,12 @@ class RequestRenameRangeConsumer : public swift::ide::FindRenameRangesConsumer,
250251
const swift::DiagnosticInfo &Info) override;
251252
};
252253

254+
struct SwiftStatistics {
255+
#define SWIFT_STATISTIC(VAR, UID, DESC) \
256+
Statistic VAR{UIdent{"source.statistic." #UID}, DESC};
257+
#include "SwiftStatistics.def"
258+
};
259+
253260
class SwiftLangSupport : public LangSupport {
254261
SourceKit::Context &SKCtx;
255262
std::string RuntimeResourcePath;
@@ -260,6 +267,7 @@ class SwiftLangSupport : public LangSupport {
260267
ThreadSafeRefCntPtr<SwiftPopularAPI> PopularAPI;
261268
CodeCompletion::SessionCacheMap CCSessions;
262269
ThreadSafeRefCntPtr<SwiftCustomCompletions> CustomCompletions;
270+
SwiftStatistics Stats;
263271

264272
public:
265273
explicit SwiftLangSupport(SourceKit::Context &SKCtx);
@@ -277,6 +285,8 @@ class SwiftLangSupport : public LangSupport {
277285
return CCCache;
278286
}
279287

288+
SwiftStatistics &getStatistics() { return Stats; }
289+
280290
static SourceKit::UIdent getUIDForDecl(const swift::Decl *D,
281291
bool IsRef = false);
282292
static SourceKit::UIdent getUIDForExtensionOfDecl(const swift::Decl *D);
@@ -492,6 +502,8 @@ class SwiftLangSupport : public LangSupport {
492502
void findModuleGroups(StringRef ModuleName, ArrayRef<const char *> Args,
493503
std::function<void(ArrayRef<StringRef>, StringRef Error)> Receiver) override;
494504

505+
void getStatistics(StatisticsReceiver) override;
506+
495507
private:
496508
swift::SourceFile *getSyntacticSourceFile(llvm::MemoryBuffer *InputBuf,
497509
ArrayRef<const char *> Args,
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//===--- SwiftStatistics.def - ----------------------------------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef SWIFT_STATISTIC
14+
#error "must define SWIFT_STATISTIC to use"
15+
#endif
16+
17+
/// SWIFT_STATISTIC(VAR_NAME, UNIQUE_ID, DESCRIPTION)
18+
19+
SWIFT_STATISTIC(numASTBuilds, num-ast-builds, "# of ASTs built or rebuilt")
20+
SWIFT_STATISTIC(numASTsInMem, num-asts-in-memory, "# of ASTs currently in memory")
21+
SWIFT_STATISTIC(maxASTsInMem, max-asts-in-memory, "maximum # of ASTs ever in memory at once")
22+
SWIFT_STATISTIC(numASTCacheHits, num-ast-cache-hits, "# of ASTs found in the cache without rebuilding")
23+
SWIFT_STATISTIC(numASTsUsedWithSnaphots, num-ast-snaphost-uses, "# of ASTs used with snaphots without rebuilding")
24+
25+
SWIFT_STATISTIC(numOpenDocs, num-open-documents, "# of editor documents currently open")
26+
SWIFT_STATISTIC(maxOpenDocs, max-open-documents, "maximum # of editor documents ever open at once")
27+
28+
#undef SWIFT_STATISTIC

0 commit comments

Comments
 (0)