Add completion benchmark to check completion speed
This commit is contained in:
+89
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.completion
|
||||
|
||||
import kotlinx.coroutines.experimental.channels.ConflatedChannel
|
||||
|
||||
|
||||
interface CompletionBenchmarkSink {
|
||||
fun onCompletionStarted(completionSession: CompletionSession)
|
||||
fun onCompletionEnded(completionSession: CompletionSession)
|
||||
fun onFirstFlush(completionSession: CompletionSession)
|
||||
|
||||
companion object {
|
||||
|
||||
fun enableAndGet(): Impl = Impl().also { _instance = it }
|
||||
|
||||
fun disable() {
|
||||
_instance.let { (it as? Impl)?.channel?.close() }
|
||||
_instance = Empty
|
||||
}
|
||||
|
||||
val instance get() = _instance
|
||||
private var _instance: CompletionBenchmarkSink = Empty
|
||||
}
|
||||
|
||||
private object Empty : CompletionBenchmarkSink {
|
||||
override fun onCompletionStarted(completionSession: CompletionSession) {}
|
||||
|
||||
override fun onCompletionEnded(completionSession: CompletionSession) {}
|
||||
|
||||
override fun onFirstFlush(completionSession: CompletionSession) {}
|
||||
}
|
||||
|
||||
class Impl : CompletionBenchmarkSink {
|
||||
private val pendingSessions = mutableListOf<CompletionSession>()
|
||||
private lateinit var results: CompletionBenchmarkResults
|
||||
val channel = ConflatedChannel<CompletionBenchmarkResults>()
|
||||
|
||||
override fun onCompletionStarted(completionSession: CompletionSession) = synchronized(this) {
|
||||
if (pendingSessions.isEmpty())
|
||||
results = CompletionBenchmarkResults()
|
||||
pendingSessions += completionSession
|
||||
}
|
||||
|
||||
override fun onCompletionEnded(completionSession: CompletionSession) = synchronized(this) {
|
||||
pendingSessions -= completionSession
|
||||
if (pendingSessions.isEmpty()) {
|
||||
results.onEnd()
|
||||
channel.offer(results)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFirstFlush(completionSession: CompletionSession) = synchronized(this) {
|
||||
results.onFirstFlush()
|
||||
}
|
||||
|
||||
fun reset() = synchronized(this) {
|
||||
pendingSessions.clear()
|
||||
}
|
||||
|
||||
class CompletionBenchmarkResults {
|
||||
var start: Long = System.currentTimeMillis()
|
||||
var firstFlush: Long = 0
|
||||
var full: Long = 0
|
||||
fun onFirstFlush() {
|
||||
if (firstFlush == 0L)
|
||||
firstFlush = System.currentTimeMillis() - start
|
||||
}
|
||||
|
||||
fun onEnd() {
|
||||
full = System.currentTimeMillis() - start
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -78,6 +78,10 @@ abstract class CompletionSession(
|
||||
protected val toFromOriginalFileMapper: ToFromOriginalFileMapper,
|
||||
resultSet: CompletionResultSet
|
||||
) {
|
||||
init {
|
||||
CompletionBenchmarkSink.instance.onCompletionStarted(this)
|
||||
}
|
||||
|
||||
protected val position = parameters.position
|
||||
protected val file = position.containingFile as KtFile
|
||||
protected val resolutionFacade = file.getResolutionFacade()
|
||||
@@ -140,7 +144,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(prefixMatcher, parameters, resultSet, createSorter(), (file as? KtCodeFragment)?.extraCompletionFilter)
|
||||
LookupElementsCollector(this, prefixMatcher, parameters, resultSet, createSorter(), (file as? KtCodeFragment)?.extraCompletionFilter)
|
||||
}
|
||||
|
||||
protected val searchScope: GlobalSearchScope = getResolveScope(parameters.originalFile as KtFile)
|
||||
@@ -199,6 +203,14 @@ abstract class CompletionSession(
|
||||
}
|
||||
|
||||
fun complete(): Boolean {
|
||||
return try {
|
||||
_complete()
|
||||
} finally {
|
||||
CompletionBenchmarkSink.instance.onCompletionEnded(this)
|
||||
}
|
||||
}
|
||||
|
||||
private fun _complete(): Boolean {
|
||||
// we restart completion when prefix becomes "get" or "set" to ensure that properties get lower priority comparing to get/set functions (see KT-12299)
|
||||
val prefixPattern = StandardPatterns.string().with(object : PatternCondition<String>("get or set prefix") {
|
||||
override fun accepts(prefix: String, context: ProcessingContext?) = prefix == "get" || prefix == "set"
|
||||
|
||||
+4
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.idea.core.completion.DeclarationLookupObject
|
||||
import java.util.*
|
||||
|
||||
class LookupElementsCollector(
|
||||
private val session: CompletionSession,
|
||||
private val prefixMatcher: PrefixMatcher,
|
||||
private val completionParameters: CompletionParameters,
|
||||
resultSet: CompletionResultSet,
|
||||
@@ -50,8 +51,11 @@ class LookupElementsCollector(
|
||||
var isResultEmpty: Boolean = true
|
||||
private set
|
||||
|
||||
|
||||
fun flushToResultSet() {
|
||||
if (!elements.isEmpty()) {
|
||||
CompletionBenchmarkSink.instance.onFirstFlush(session)
|
||||
|
||||
resultSet.addAllElements(elements)
|
||||
elements.clear()
|
||||
isResultEmpty = false
|
||||
|
||||
Reference in New Issue
Block a user