Add benchmark for local completion and improve benchmarking

This commit is contained in:
Simon Ogorodnik
2017-07-19 04:43:49 +03:00
parent 4df6db141c
commit ccfcfd8721
8 changed files with 516 additions and 293 deletions
@@ -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
}
}
@@ -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()