Skip to content

Commit 701eb4f

Browse files
authored
Merge pull request #18444 from ahoppen/performance-improvements
2 parents df7c76f + b75dd68 commit 701eb4f

File tree

7 files changed

+57
-25
lines changed

7 files changed

+57
-25
lines changed

include/swift/Parse/SyntaxParsingCache.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,10 @@ class SyntaxParsingCache {
9090
getReusedRegions(const SourceFileSyntax &SyntaxTree) const;
9191

9292
private:
93-
llvm::Optional<Syntax> lookUpFrom(const Syntax &Node, size_t Position,
94-
SyntaxKind Kind);
93+
llvm::Optional<Syntax> lookUpFrom(const Syntax &Node, size_t NodeStart,
94+
size_t Position, SyntaxKind Kind);
9595

96-
bool nodeCanBeReused(const Syntax &Node, size_t Position,
96+
bool nodeCanBeReused(const Syntax &Node, size_t Position, size_t NodeStart,
9797
SyntaxKind Kind) const;
9898
};
9999

lib/Parse/SyntaxParsingCache.cpp

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,14 @@
1616
using namespace swift;
1717
using namespace swift::syntax;
1818

19-
bool SyntaxParsingCache::nodeCanBeReused(const Syntax &Node, size_t Position,
19+
bool SyntaxParsingCache::nodeCanBeReused(const Syntax &Node, size_t NodeStart,
20+
size_t Position,
2021
SyntaxKind Kind) const {
21-
auto NodeStart = Node.getAbsolutePositionBeforeLeadingTrivia().getOffset();
22+
// Computing the value of NodeStart on the fly is faster than determining a
23+
// node's absolute position, but make sure the values match in an assertion
24+
// build
25+
assert(NodeStart == Node.getAbsolutePositionBeforeLeadingTrivia().getOffset());
26+
2227
if (NodeStart != Position)
2328
return false;
2429
if (Node.getKind() != Kind)
@@ -50,23 +55,26 @@ bool SyntaxParsingCache::nodeCanBeReused(const Syntax &Node, size_t Position,
5055
}
5156

5257
llvm::Optional<Syntax> SyntaxParsingCache::lookUpFrom(const Syntax &Node,
58+
size_t NodeStart,
5359
size_t Position,
5460
SyntaxKind Kind) {
55-
if (nodeCanBeReused(Node, Position, Kind)) {
61+
if (nodeCanBeReused(Node, NodeStart, Position, Kind)) {
5662
return Node;
5763
}
5864

65+
// Compute the child's position on the fly
66+
size_t ChildStart = NodeStart;
5967
for (size_t I = 0, E = Node.getNumChildren(); I < E; ++I) {
6068
llvm::Optional<Syntax> Child = Node.getChild(I);
6169
if (!Child.hasValue()) {
6270
continue;
6371
}
64-
auto ChildStart =
65-
Child->getAbsolutePositionBeforeLeadingTrivia().getOffset();
6672
auto ChildEnd = ChildStart + Child->getTextLength();
6773
if (ChildStart <= Position && Position < ChildEnd) {
68-
return lookUpFrom(Child.getValue(), Position, Kind);
74+
return lookUpFrom(Child.getValue(), ChildStart, Position, Kind);
6975
}
76+
// The next child starts where the previous child ended
77+
ChildStart = ChildEnd;
7078
}
7179
return llvm::None;
7280
}
@@ -83,7 +91,7 @@ llvm::Optional<Syntax> SyntaxParsingCache::lookUp(size_t NewPosition,
8391
}
8492
}
8593

86-
auto Node = lookUpFrom(OldSyntaxTree, OldPosition, Kind);
94+
auto Node = lookUpFrom(OldSyntaxTree, /*NodeStart=*/0, OldPosition, Kind);
8795
if (Node.hasValue()) {
8896
ReusedNodeIds.insert(Node->getId());
8997
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ class EditorConsumer {
265265

266266
virtual void
267267
handleSyntaxTree(const swift::syntax::SourceFileSyntax &SyntaxTree,
268-
std::unordered_set<unsigned> ReusedNodeIds) = 0;
268+
std::unordered_set<unsigned> &ReusedNodeIds) = 0;
269269
virtual bool syntaxTreeEnabled() {
270270
return syntaxTreeTransferMode() != SyntaxTreeTransferMode::Off;
271271
}

tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1796,12 +1796,6 @@ void SwiftEditorDocument::readSyntaxInfo(EditorConsumer &Consumer) {
17961796

17971797
Impl.ParserDiagnostics = Impl.SyntaxInfo->getDiagnostics();
17981798

1799-
if (Consumer.syntaxTreeEnabled()) {
1800-
std::unordered_set<unsigned> ReusedNodeIds;
1801-
Consumer.handleSyntaxTree(Impl.SyntaxInfo->getSourceFile().getSyntaxRoot(),
1802-
ReusedNodeIds);
1803-
}
1804-
18051799
SwiftSyntaxMap NewMap = SwiftSyntaxMap(Impl.SyntaxMap.Tokens.size() + 16);
18061800

18071801
if (Consumer.syntaxTreeEnabled()) {
@@ -2107,6 +2101,13 @@ void SwiftLangSupport::editorOpen(StringRef Name, llvm::MemoryBuffer *Buf,
21072101

21082102
EditorDoc->readSyntaxInfo(Consumer);
21092103
EditorDoc->readSemanticInfo(Snapshot, Consumer);
2104+
2105+
if (Consumer.syntaxTreeEnabled()) {
2106+
assert(EditorDoc->getSyntaxTree().hasValue());
2107+
std::unordered_set<unsigned> ReusedNodeIds;
2108+
Consumer.handleSyntaxTree(EditorDoc->getSyntaxTree().getValue(),
2109+
ReusedNodeIds);
2110+
}
21102111
}
21112112

21122113

tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include "llvm/ADT/StringRef.h"
3838
#include "llvm/ADT/STLExtras.h"
3939
#include "llvm/Support/MemoryBuffer.h"
40+
#include "llvm/Support/NativeFormatting.h"
4041
#include "llvm/Support/Path.h"
4142
#include "llvm/Support/PrettyStackTrace.h"
4243
#include "llvm/Support/raw_ostream.h"
@@ -2088,7 +2089,7 @@ class SKEditorConsumer : public EditorConsumer {
20882089
void handleSourceText(StringRef Text) override;
20892090

20902091
void handleSyntaxTree(const swift::syntax::SourceFileSyntax &SyntaxTree,
2091-
std::unordered_set<unsigned> ReusedNodeIds) override;
2092+
std::unordered_set<unsigned> &ReusedNodeIds) override;
20922093

20932094
bool syntaxReuseInfoEnabled() override { return Opts.EnableSyntaxReuseInfo; }
20942095
void
@@ -2419,22 +2420,44 @@ void SKEditorConsumer::handleSourceText(StringRef Text) {
24192420
Dict.set(KeySourceText, Text);
24202421
}
24212422

2422-
void SKEditorConsumer::handleSyntaxTree(
2423+
void serializeSyntaxTreeAsJson(
24232424
const swift::syntax::SourceFileSyntax &SyntaxTree,
2424-
std::unordered_set<unsigned> ReusedNodeIds) {
2425-
if (Opts.SyntaxTransferMode == SyntaxTreeTransferMode::Off)
2426-
return;
2427-
2425+
std::unordered_set<unsigned> &ReusedNodeIds,
2426+
ResponseBuilder::Dictionary &Dict) {
2427+
auto StartClock = clock();
2428+
// 4096 is a heuristic buffer size that appears to usually be able to fit an
2429+
// incremental syntax tree
2430+
size_t ReserveBufferSize = 4096;
24282431
std::string SyntaxTreeString;
2432+
SyntaxTreeString.reserve(ReserveBufferSize);
24292433
{
24302434
llvm::raw_string_ostream SyntaxTreeStream(SyntaxTreeString);
2435+
SyntaxTreeStream.SetBufferSize(ReserveBufferSize);
24312436
swift::json::Output::UserInfoMap JsonUserInfo;
24322437
JsonUserInfo[swift::json::OmitNodesUserInfoKey] = &ReusedNodeIds;
24332438
swift::json::Output SyntaxTreeOutput(SyntaxTreeStream, JsonUserInfo,
24342439
/*PrettyPrint=*/false);
24352440
SyntaxTreeOutput << *SyntaxTree.getRaw();
24362441
}
24372442
Dict.set(KeySerializedSyntaxTree, SyntaxTreeString);
2443+
2444+
auto EndClock = clock();
2445+
LOG_SECTION("incrParse Performance", InfoLowPrio) {
2446+
Log->getOS() << "Serialized " << SyntaxTreeString.size() << " bytes in ";
2447+
llvm::write_double(Log->getOS(),
2448+
(double)(EndClock - StartClock) * 1000 / CLOCKS_PER_SEC,
2449+
llvm::FloatStyle::Fixed, 2);
2450+
Log->getOS() << "ms";
2451+
}
2452+
}
2453+
2454+
void SKEditorConsumer::handleSyntaxTree(
2455+
const swift::syntax::SourceFileSyntax &SyntaxTree,
2456+
std::unordered_set<unsigned> &ReusedNodeIds) {
2457+
if (Opts.SyntaxTransferMode == SyntaxTreeTransferMode::Off)
2458+
return;
2459+
2460+
serializeSyntaxTreeAsJson(SyntaxTree, ReusedNodeIds, Dict);
24382461
}
24392462

24402463
void SKEditorConsumer::handleSyntaxReuseRegions(

unittests/SourceKit/SwiftLang/CursorInfoTest.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ class NullEditorConsumer : public EditorConsumer {
7979

8080
void handleSourceText(StringRef Text) override {}
8181
void handleSyntaxTree(const swift::syntax::SourceFileSyntax &SyntaxTree,
82-
std::unordered_set<unsigned> ReusedNodeIds) override {}
82+
std::unordered_set<unsigned> &ReusedNodeIds) override {}
8383

8484
SyntaxTreeTransferMode syntaxTreeTransferMode() override {
8585
return SyntaxTreeTransferMode::Off;

unittests/SourceKit/SwiftLang/EditingTest.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ class DiagConsumer : public EditorConsumer {
8787

8888
void handleSourceText(StringRef Text) override {}
8989
void handleSyntaxTree(const swift::syntax::SourceFileSyntax &SyntaxTree,
90-
std::unordered_set<unsigned> ReusedNodeIds) override {}
90+
std::unordered_set<unsigned> &ReusedNodeIds) override {}
9191

9292
SyntaxTreeTransferMode syntaxTreeTransferMode() override {
9393
return SyntaxTreeTransferMode::Off;

0 commit comments

Comments
 (0)