Skip to content

Commit 178641d

Browse files
committed
[sourcekit] Introduce a lazy representation for DocumentStructure responses
Previously, document structure responses were created using XPC dictionaries, but this forced deserialization of the large nested dictionaries no matter what the access pattern was. The new format uses our custom buffer machinery, and only deserializes dictionaries that are actually needed. The performance improvement is around 25% for an editor.open, and 35-40% for an editor.replacetext request in the large files I've tested. The performance improvements are in serialization (inside the service), deserialization (client), and disposal of the response object (client). rdar://problem/28789756
1 parent dfe2f43 commit 178641d

File tree

8 files changed

+723
-108
lines changed

8 files changed

+723
-108
lines changed

tools/SourceKit/tools/sourcekitd/include/sourcekitd/CompactArray.h

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ namespace sourcekitd {
2121
class CompactArrayBuilderImpl {
2222
public:
2323
std::unique_ptr<llvm::MemoryBuffer> createBuffer() const;
24+
void appendTo(llvm::SmallVectorImpl<char> &Buf) const;
2425

26+
size_t sizeInBytes() const;
2527
bool empty() const;
2628

2729
protected:
@@ -35,30 +37,12 @@ class CompactArrayBuilderImpl {
3537

3638
private:
3739
unsigned getOffsetForString(llvm::StringRef Str);
40+
void copyInto(char *BufPtr, size_t Length) const;
3841

3942
llvm::SmallVector<uint8_t, 256> EntriesBuffer;
4043
llvm::SmallString<256> StringBuffer;
4144
};
4245

43-
template <typename ...EntryTypes>
44-
class CompactArrayBuilder : public CompactArrayBuilderImpl {
45-
public:
46-
void addEntry(EntryTypes... Args) {
47-
add(Args...);
48-
}
49-
50-
private:
51-
template <typename T, typename ...Targs>
52-
void add(T Val, Targs... Args) {
53-
add(Val);
54-
add(Args...);
55-
}
56-
57-
template <typename T>
58-
void add(T Val) {
59-
addImpl(Val);
60-
}
61-
};
6246

6347
template <typename T>
6448
struct CompactArrayField {
@@ -88,6 +72,31 @@ struct CompactArrayEntriesSizer<T> {
8872
}
8973
};
9074

75+
template <typename ...EntryTypes>
76+
class CompactArrayBuilder : public CompactArrayBuilderImpl {
77+
public:
78+
void addEntry(EntryTypes... Args) {
79+
add(Args...);
80+
count += 1;
81+
}
82+
83+
size_t size() const { return count; }
84+
85+
private:
86+
template <typename T, typename ...Targs>
87+
void add(T Val, Targs... Args) {
88+
add(Val);
89+
add(Args...);
90+
}
91+
92+
template <typename T>
93+
void add(T Val) {
94+
addImpl(Val);
95+
}
96+
97+
size_t count = 0;
98+
};
99+
91100
class CompactArrayReaderImpl {
92101
protected:
93102
CompactArrayReaderImpl(void *Buf) : Buf(Buf) {}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
//===--- DocStructureArray.h - ----------------------------------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See http://swift.org/LICENSE.txt for license information
9+
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef LLVM_SOURCEKITD_DOC_STRUCTURE_ARRAY_H
14+
#define LLVM_SOURCEKITD_DOC_STRUCTURE_ARRAY_H
15+
16+
#include "sourcekitd/Internal.h"
17+
#include "llvm/ADT/SmallString.h"
18+
19+
namespace sourcekitd {
20+
21+
VariantFunctions *getVariantFunctionsForDocStructureArray();
22+
VariantFunctions *getVariantFunctionsForDocStructureElementArray();
23+
VariantFunctions *getVariantFunctionsForInheritedTypesArray();
24+
VariantFunctions *getVariantFunctionsForAttributesArray();
25+
26+
class DocStructureArrayBuilder {
27+
public:
28+
DocStructureArrayBuilder();
29+
~DocStructureArrayBuilder();
30+
31+
void beginSubStructure(unsigned Offset, unsigned Length,
32+
SourceKit::UIdent Kind, SourceKit::UIdent AccessLevel,
33+
SourceKit::UIdent SetterAccessLevel,
34+
unsigned NameOffset, unsigned NameLength,
35+
unsigned BodyOffset, unsigned BodyLength,
36+
llvm::StringRef DisplayName, llvm::StringRef TypeName,
37+
llvm::StringRef RuntimeName,
38+
llvm::StringRef SelectorName,
39+
llvm::ArrayRef<llvm::StringRef> InheritedTypes,
40+
llvm::ArrayRef<SourceKit::UIdent> Attrs);
41+
42+
void addElement(SourceKit::UIdent Kind, unsigned Offset, unsigned Length);
43+
44+
void endSubStructure();
45+
46+
std::unique_ptr<llvm::MemoryBuffer> createBuffer();
47+
48+
private:
49+
struct Implementation;
50+
Implementation &impl;
51+
};
52+
53+
} // end namespace sourcekitd
54+
55+
#endif // LLVM_SOURCEKITD_DOC_STRUCTURE_ARRAY_H

tools/SourceKit/tools/sourcekitd/include/sourcekitd/Internal.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ enum class CustomBufferKind {
4747
TokenAnnotationsArray,
4848
DocSupportAnnotationArray,
4949
CodeCompletionResultsArray,
50+
DocStructureArray,
51+
InheritedTypesArray,
52+
DocStructureElementArray,
53+
AttributesArray,
5054
};
5155

5256
class ResponseBuilder {

tools/SourceKit/tools/sourcekitd/lib/API/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
set(sourcekitdAPI_sources
22
CodeCompletionResultsArray.cpp
33
CompactArray.cpp
4+
DocStructureArray.cpp
45
DocSupportAnnotationArray.cpp
56
Requests.cpp
67
sourcekitdAPI-Common.cpp

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

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,12 @@ void CompactArrayBuilderImpl::addImpl(StringRef Val) {
4343
}
4444

4545
void CompactArrayBuilderImpl::addImpl(UIdent Val) {
46-
sourcekitd_uid_t uid = SKDUIDFromUIdent(Val);
47-
addScalar(uid, EntriesBuffer);
46+
if (Val.isValid()) {
47+
sourcekitd_uid_t uid = SKDUIDFromUIdent(Val);
48+
addScalar(uid, EntriesBuffer);
49+
} else {
50+
addScalar(sourcekitd_uid_t(nullptr), EntriesBuffer);
51+
}
4852
}
4953

5054
void CompactArrayBuilderImpl::addImpl(Optional<llvm::StringRef> Val) {
@@ -67,27 +71,37 @@ unsigned CompactArrayBuilderImpl::getOffsetForString(StringRef Str) {
6771

6872
std::unique_ptr<llvm::MemoryBuffer>
6973
CompactArrayBuilderImpl::createBuffer() const {
70-
size_t EntriesBufSize = EntriesBuffer.size();
7174
std::unique_ptr<llvm::MemoryBuffer> Buf;
72-
Buf = llvm::MemoryBuffer::getNewUninitMemBuffer(
73-
sizeof(uint64_t) +
74-
EntriesBufSize +
75-
StringBuffer.size());
76-
77-
char *BufPtr = (char*)Buf->getBufferStart();
78-
*reinterpret_cast<uint64_t*>(BufPtr) = EntriesBufSize;
79-
BufPtr += sizeof(uint64_t);
75+
Buf = llvm::MemoryBuffer::getNewUninitMemBuffer(sizeInBytes());
76+
copyInto(const_cast<char *>(Buf->getBufferStart()), Buf->getBufferSize());
77+
return Buf;
78+
}
79+
80+
void CompactArrayBuilderImpl::appendTo(SmallVectorImpl<char> &Buf) const {
81+
size_t OrigSize = Buf.size();
82+
size_t NewSize = OrigSize + sizeInBytes();
83+
Buf.resize(NewSize);
84+
copyInto(Buf.data() + OrigSize, NewSize - OrigSize);
85+
}
86+
87+
void CompactArrayBuilderImpl::copyInto(char *BufPtr, size_t Length) const {
88+
uint64_t EntriesBufSize = EntriesBuffer.size();
89+
assert(Length >= sizeInBytes());
90+
memcpy(BufPtr, &EntriesBufSize, sizeof(EntriesBufSize));
91+
BufPtr += sizeof(EntriesBufSize);
8092
memcpy(BufPtr, EntriesBuffer.data(), EntriesBufSize);
8193
BufPtr += EntriesBufSize;
8294
memcpy(BufPtr, StringBuffer.data(), StringBuffer.size());
83-
84-
return Buf;
8595
}
8696

8797
bool CompactArrayBuilderImpl::empty() const {
8898
return EntriesBuffer.empty();
8999
}
90100

101+
size_t CompactArrayBuilderImpl::sizeInBytes() const {
102+
return sizeof(uint64_t) + EntriesBuffer.size() + StringBuffer.size();
103+
}
104+
91105
template <typename T>
92106
static void readScalar(const uint8_t *Buf, T &Val) {
93107
memcpy(&Val, Buf, sizeof(Val));

0 commit comments

Comments
 (0)