Add benchmark for local completion and improve benchmarking
This commit is contained in:
+31
-19
@@ -17,12 +17,13 @@
|
||||
package org.jetbrains.kotlin.idea.completion
|
||||
|
||||
import kotlinx.coroutines.experimental.channels.ConflatedChannel
|
||||
import java.lang.System.currentTimeMillis
|
||||
|
||||
|
||||
interface CompletionBenchmarkSink {
|
||||
fun onCompletionStarted(completionSession: CompletionSession)
|
||||
fun onCompletionEnded(completionSession: CompletionSession)
|
||||
fun onFirstFlush(completionSession: CompletionSession)
|
||||
fun onCompletionEnded(completionSession: CompletionSession, canceled: Boolean)
|
||||
fun onFlush(completionSession: CompletionSession)
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -40,49 +41,60 @@ interface CompletionBenchmarkSink {
|
||||
private object Empty : CompletionBenchmarkSink {
|
||||
override fun onCompletionStarted(completionSession: CompletionSession) {}
|
||||
|
||||
override fun onCompletionEnded(completionSession: CompletionSession) {}
|
||||
override fun onCompletionEnded(completionSession: CompletionSession, canceled: Boolean) {}
|
||||
|
||||
override fun onFirstFlush(completionSession: CompletionSession) {}
|
||||
override fun onFlush(completionSession: CompletionSession) {}
|
||||
}
|
||||
|
||||
class Impl : CompletionBenchmarkSink {
|
||||
private val pendingSessions = mutableListOf<CompletionSession>()
|
||||
private lateinit var results: CompletionBenchmarkResults
|
||||
val channel = ConflatedChannel<CompletionBenchmarkResults>()
|
||||
|
||||
private val perSessionResults = LinkedHashMap<CompletionSession, PerSessionResults>()
|
||||
private var start: Long = 0
|
||||
|
||||
override fun onCompletionStarted(completionSession: CompletionSession) = synchronized(this) {
|
||||
if (pendingSessions.isEmpty())
|
||||
results = CompletionBenchmarkResults()
|
||||
start = currentTimeMillis()
|
||||
pendingSessions += completionSession
|
||||
perSessionResults[completionSession] = PerSessionResults()
|
||||
}
|
||||
|
||||
override fun onCompletionEnded(completionSession: CompletionSession) = synchronized(this) {
|
||||
override fun onCompletionEnded(completionSession: CompletionSession, canceled: Boolean) = synchronized(this) {
|
||||
pendingSessions -= completionSession
|
||||
perSessionResults[completionSession]?.onEnd(canceled)
|
||||
if (pendingSessions.isEmpty()) {
|
||||
results.onEnd()
|
||||
channel.offer(results)
|
||||
val firstFlush = perSessionResults.values.filterNot { results -> results.canceled }.map { it.firstFlush }.min() ?: 0
|
||||
val full = perSessionResults.values.map { it.full }.max() ?: 0
|
||||
channel.offer(CompletionBenchmarkResults(firstFlush, full))
|
||||
reset()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFirstFlush(completionSession: CompletionSession) = synchronized(this) {
|
||||
results.onFirstFlush()
|
||||
override fun onFlush(completionSession: CompletionSession) = synchronized(this) {
|
||||
perSessionResults[completionSession]?.onFirstFlush()
|
||||
Unit
|
||||
}
|
||||
|
||||
fun reset() = synchronized(this) {
|
||||
pendingSessions.clear()
|
||||
perSessionResults.clear()
|
||||
}
|
||||
|
||||
class CompletionBenchmarkResults {
|
||||
var start: Long = System.currentTimeMillis()
|
||||
var firstFlush: Long = 0
|
||||
var full: Long = 0
|
||||
data class CompletionBenchmarkResults(var firstFlush: Long = 0, var full: Long = 0)
|
||||
|
||||
private inner class PerSessionResults {
|
||||
var firstFlush = 0L
|
||||
var full = 0L
|
||||
var canceled = false
|
||||
|
||||
fun onFirstFlush() {
|
||||
if (firstFlush == 0L)
|
||||
firstFlush = System.currentTimeMillis() - start
|
||||
firstFlush = currentTimeMillis() - start
|
||||
}
|
||||
|
||||
fun onEnd() {
|
||||
full = System.currentTimeMillis() - start
|
||||
fun onEnd(canceled: Boolean) {
|
||||
full = currentTimeMillis() - start
|
||||
this.canceled = canceled
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.intellij.codeInsight.completion.CompletionUtil
|
||||
import com.intellij.codeInsight.completion.impl.CamelHumpMatcher
|
||||
import com.intellij.codeInsight.completion.impl.RealPrefixMatchingWeigher
|
||||
import com.intellij.codeInsight.lookup.LookupElement
|
||||
import com.intellij.openapi.progress.ProcessCanceledException
|
||||
import com.intellij.patterns.PatternCondition
|
||||
import com.intellij.patterns.StandardPatterns
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
@@ -144,7 +145,7 @@ abstract class CompletionSession(
|
||||
|
||||
// LookupElementsCollector instantiation is deferred because virtual call to createSorter uses data from derived classes
|
||||
protected val collector: LookupElementsCollector by lazy(LazyThreadSafetyMode.NONE) {
|
||||
LookupElementsCollector(this, prefixMatcher, parameters, resultSet, createSorter(), (file as? KtCodeFragment)?.extraCompletionFilter)
|
||||
LookupElementsCollector({ CompletionBenchmarkSink.instance.onFlush(this) }, prefixMatcher, parameters, resultSet, createSorter(), (file as? KtCodeFragment)?.extraCompletionFilter)
|
||||
}
|
||||
|
||||
protected val searchScope: GlobalSearchScope = getResolveScope(parameters.originalFile as KtFile)
|
||||
@@ -204,9 +205,12 @@ abstract class CompletionSession(
|
||||
|
||||
fun complete(): Boolean {
|
||||
return try {
|
||||
_complete()
|
||||
} finally {
|
||||
CompletionBenchmarkSink.instance.onCompletionEnded(this)
|
||||
_complete().also {
|
||||
CompletionBenchmarkSink.instance.onCompletionEnded(this, false)
|
||||
}
|
||||
} catch (pce: ProcessCanceledException) {
|
||||
CompletionBenchmarkSink.instance.onCompletionEnded(this, true)
|
||||
throw pce
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -29,7 +29,7 @@ import org.jetbrains.kotlin.idea.core.completion.DeclarationLookupObject
|
||||
import java.util.*
|
||||
|
||||
class LookupElementsCollector(
|
||||
private val session: CompletionSession,
|
||||
private val onFlush: () -> Unit,
|
||||
private val prefixMatcher: PrefixMatcher,
|
||||
private val completionParameters: CompletionParameters,
|
||||
resultSet: CompletionResultSet,
|
||||
@@ -54,7 +54,7 @@ class LookupElementsCollector(
|
||||
|
||||
fun flushToResultSet() {
|
||||
if (!elements.isEmpty()) {
|
||||
CompletionBenchmarkSink.instance.onFirstFlush(session)
|
||||
onFlush()
|
||||
|
||||
resultSet.addAllElements(elements)
|
||||
elements.clear()
|
||||
|
||||
Reference in New Issue
Block a user