Skip to content

Commit edbc396

Browse files
committed
perf: add declarations in bulk
1 parent 07aeef0 commit edbc396

File tree

6 files changed

+41
-24
lines changed

6 files changed

+41
-24
lines changed

app/src/main/kotlin/org/kotlinlsp/index/db/Database.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import org.kotlinlsp.index.db.adapters.put
99
import java.io.File
1010
import kotlin.io.path.absolutePathString
1111

12-
const val CURRENT_SCHEMA_VERSION = 4 // Increment on schema changes
12+
const val CURRENT_SCHEMA_VERSION = 5 // Increment on schema changes
1313
const val VERSION_KEY = "__version"
1414

1515
class Database(rootFolder: String) {

app/src/main/kotlin/org/kotlinlsp/index/db/Declaration.kt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import kotlinx.serialization.SerialName
44
import kotlinx.serialization.Serializable
55
import org.kotlinlsp.common.info
66
import org.kotlinlsp.index.db.adapters.put
7+
import org.kotlinlsp.index.db.adapters.putBulk
78

89
@Serializable
910
sealed class Declaration() {
@@ -76,7 +77,8 @@ sealed class Declaration() {
7677
) : Declaration()
7778
}
7879

79-
fun Database.putDeclaration(decl: Declaration) {
80-
val key = "${decl.name}:${decl.file}:${decl.startOffset}:${decl.endOffset}"
81-
declarationsDb.put(key, decl)
80+
fun Declaration.id() = "${name}:${file}:${startOffset}:${endOffset}"
81+
82+
fun Database.putDeclarations(declarations: Iterable<Declaration>) {
83+
declarationsDb.putBulk(declarations.map { Pair(it.id(), it) })
8284
}

app/src/main/kotlin/org/kotlinlsp/index/db/File.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ data class File(
1414
val lastModified: Instant,
1515
val modificationStamp: Long,
1616
val indexed: Boolean,
17+
val declarationKeys: MutableList<String> = mutableListOf()
1718
) {
1819
companion object {
1920
fun fromKtFile(ktFile: KtFile, project: Project, indexed: Boolean): File = project.read {
@@ -43,6 +44,7 @@ fun File.toDto(): FileDto = FileDto(
4344
lastModified = lastModified.toEpochMilli(),
4445
modificationStamp = modificationStamp,
4546
indexed = indexed,
47+
declarationKeys = declarationKeys
4648
)
4749

4850
@Serializable
@@ -51,6 +53,7 @@ data class FileDto(
5153
val lastModified: Long,
5254
val modificationStamp: Long,
5355
val indexed: Boolean,
56+
val declarationKeys: List<String>
5457
)
5558

5659
fun Database.file(path: String): File? {

app/src/main/kotlin/org/kotlinlsp/index/db/adapters/DatabaseAdapter.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import kotlinx.serialization.protobuf.ProtoBuf
77

88
interface DatabaseAdapter {
99
fun putByteArray(key: String, value: ByteArray)
10+
fun putByteArrayBulk(values: Iterable<Pair<String, ByteArray>>)
1011
fun getByteArray(key: String): ByteArray?
1112
fun prefixSearch(prefix: String): Sequence<Pair<String, ByteArray>>
1213
fun remove(key: String)
@@ -19,6 +20,11 @@ inline fun <reified T: Any> DatabaseAdapter.put(key: String, value: T) {
1920
putByteArray(key, ProtoBuf.encodeToByteArray(value))
2021
}
2122

23+
@OptIn(ExperimentalSerializationApi::class)
24+
inline fun <reified T: Any> DatabaseAdapter.putBulk(values: Iterable<Pair<String, T>>) {
25+
putByteArrayBulk(values.map { Pair(it.first, ProtoBuf.encodeToByteArray(it.second)) })
26+
}
27+
2228
@OptIn(ExperimentalSerializationApi::class)
2329
inline fun <reified T> DatabaseAdapter.get(key: String): T? {
2430
val data = getByteArray(key) ?: return null

app/src/main/kotlin/org/kotlinlsp/index/db/adapters/RocksDBAdapter.kt

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,10 @@
11
package org.kotlinlsp.index.db.adapters
22

3-
import kotlinx.serialization.*
4-
import kotlinx.serialization.protobuf.ProtoBuf
5-
import org.rocksdb.InfoLogLevel
6-
import org.rocksdb.Options
7-
import org.rocksdb.ReadOptions
8-
import org.rocksdb.RocksDB
3+
import org.rocksdb.*
94
import java.io.File
10-
import java.io.Serial
115
import java.nio.charset.Charset
126
import java.nio.file.Path
137
import kotlin.io.path.absolutePathString
14-
import kotlin.reflect.KClass
158

169
class RocksDBAdapter(private val path: Path): DatabaseAdapter {
1710
companion object {
@@ -32,6 +25,15 @@ class RocksDBAdapter(private val path: Path): DatabaseAdapter {
3225
db.put(key.toByteArray(), value)
3326
}
3427

28+
override fun putByteArrayBulk(values: Iterable<Pair<String, ByteArray>>) {
29+
val batch = WriteBatch()
30+
values.forEach { (key, value) ->
31+
batch.put(key.toByteArray(), value)
32+
}
33+
db.write(WriteOptions(), batch)
34+
batch.close()
35+
}
36+
3537
override fun getByteArray(key: String): ByteArray? {
3638
val data = db.get(key.toByteArray()) ?: return null
3739
return data

app/src/main/kotlin/org/kotlinlsp/index/worker/IndexKtFile.kt

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,34 +13,38 @@ import org.kotlinlsp.index.db.*
1313
fun indexKtFile(project: Project, ktFile: KtFile, db: Database) {
1414
val newFile = File.fromKtFile(ktFile, project, indexed = true)
1515

16+
// Check if skipping the indexing of that file
1617
val existingFile = db.file(newFile.path)
1718
if (
1819
File.shouldBeSkipped(existingFile = existingFile, newFile = newFile) &&
1920
existingFile?.indexed == true // Already indexed
2021
) return
2122

22-
// TODO Remove declarations for this file first
23+
// Remove declarations for this file first
24+
existingFile?.declarationKeys?.forEach {
25+
db.declarationsDb.remove(it)
26+
}
27+
28+
// Get declarations metadata
2329
val declarations = project.read {
24-
val list = mutableListOf<KtDeclaration>()
30+
val list = mutableListOf<Declaration>()
2531
ktFile.accept(object : KtTreeVisitorVoid() {
2632
override fun visitDeclaration(dcl: KtDeclaration) {
27-
list.add(dcl)
33+
val record = analyze(dcl) {
34+
analyzeDeclaration(newFile.path, dcl)
35+
} ?: return
36+
list.add(record)
2837
super.visitDeclaration(dcl)
2938
}
3039
})
3140
return@read list
3241
}
3342

34-
declarations.forEach {
35-
val record = analyze(it) {
36-
analyzeDeclaration(newFile.path, it)
37-
} ?: return@forEach
38-
39-
// TODO Put all declarations in bulk to improve performance
40-
db.putDeclaration(record)
41-
}
43+
// Save declarations
44+
db.putDeclarations(declarations)
4245

43-
// Update the file timestamp and package
46+
// Update the file timestamp, package and declaration names
47+
newFile.declarationKeys.addAll(declarations.map { it.id() })
4448
db.setFile(newFile)
4549
}
4650

0 commit comments

Comments
 (0)