Added copy-paste performance tests
This commit is contained in:
@@ -1281,6 +1281,10 @@ fun main(args: Array<String>) {
|
||||
model("copyPaste/conversion", testMethod = "doPerfTest", pattern = """^([^\.]+)\.java$""")
|
||||
}
|
||||
|
||||
testClass<AbstractPerformanceLiteralKotlinToKotlinCopyPasteTest> {
|
||||
model("copyPaste/literal", testMethod = "doPerfTest", pattern = """^([^\.]+)\.kt$""")
|
||||
}
|
||||
|
||||
testClass<AbstractPerformanceHighlightingTest> {
|
||||
model("highlighter", testMethod = "doPerfTest")
|
||||
}
|
||||
|
||||
@@ -111,6 +111,7 @@ import org.jetbrains.kotlin.idea.maven.AbstractKotlinMavenInspectionTest
|
||||
import org.jetbrains.kotlin.idea.maven.configuration.AbstractMavenConfigureProjectByChangingFileTest
|
||||
import org.jetbrains.kotlin.idea.navigation.*
|
||||
import org.jetbrains.kotlin.idea.parameterInfo.AbstractParameterInfoTest
|
||||
import org.jetbrains.kotlin.idea.perf.*
|
||||
import org.jetbrains.kotlin.idea.quickfix.AbstractQuickFixMultiFileTest
|
||||
import org.jetbrains.kotlin.idea.quickfix.AbstractQuickFixMultiModuleTest
|
||||
import org.jetbrains.kotlin.idea.quickfix.AbstractQuickFixTest
|
||||
@@ -1210,6 +1211,52 @@ fun main(args: Array<String>) {
|
||||
}
|
||||
}
|
||||
|
||||
testGroup("idea/performanceTests", "idea/testData") {
|
||||
testClass<AbstractPerformanceJavaToKotlinCopyPasteConversionTest> {
|
||||
model("copyPaste/conversion", testMethod = "doPerfTest", pattern = """^([^\.]+)\.java$""")
|
||||
}
|
||||
|
||||
testClass<AbstractPerformanceNewJavaToKotlinCopyPasteConversionTest> {
|
||||
model("copyPaste/conversion", testMethod = "doPerfTest", pattern = """^([^\.]+)\.java$""")
|
||||
}
|
||||
|
||||
testClass<AbstractPerformanceLiteralKotlinToKotlinCopyPasteTest> {
|
||||
model("copyPaste/literal", testMethod = "doPerfTest", pattern = """^([^\.]+)\.kt$""")
|
||||
}
|
||||
|
||||
testClass<AbstractPerformanceHighlightingTest> {
|
||||
model("highlighter", testMethod = "doPerfTest")
|
||||
}
|
||||
|
||||
testClass<AbstractPerformanceAddImportTest> {
|
||||
model("addImport", testMethod = "doPerfTest", pattern = KT_WITHOUT_DOTS_IN_NAME)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
testGroup("idea/performanceTests", "idea/idea-completion/testData") {
|
||||
testClass<AbstractPerformanceCompletionIncrementalResolveTest> {
|
||||
model("incrementalResolve", testMethod = "doPerfTest")
|
||||
}
|
||||
|
||||
testClass<AbstractPerformanceBasicCompletionHandlerTest> {
|
||||
model("handlers/basic", testMethod = "doPerfTest", pattern = KT_WITHOUT_DOTS_IN_NAME)
|
||||
}
|
||||
|
||||
testClass<AbstractPerformanceSmartCompletionHandlerTest> {
|
||||
model("handlers/smart", testMethod = "doPerfTest")
|
||||
}
|
||||
|
||||
testClass<AbstractPerformanceKeywordCompletionHandlerTest> {
|
||||
model("handlers/keywords", testMethod = "doPerfTest")
|
||||
}
|
||||
|
||||
testClass<AbstractPerformanceCompletionCharFilterTest> {
|
||||
model("handlers/charFilter", testMethod = "doPerfTest", pattern = KT_WITHOUT_DOTS_IN_NAME)
|
||||
}
|
||||
}
|
||||
/*
|
||||
testGroup("plugins/android-extensions/android-extensions-idea/tests", "plugins/android-extensions/android-extensions-idea/testData") {
|
||||
testClass<AbstractAndroidCompletionTest> {
|
||||
model("android/completion", recursive = false, extension = null)
|
||||
|
||||
+2
-1
@@ -11,6 +11,7 @@ import com.intellij.openapi.application.runWriteAction
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||
import org.jetbrains.kotlin.idea.completion.CompletionBindingContextProvider
|
||||
import org.jetbrains.kotlin.idea.perf.Stats.Companion.WARM_UP
|
||||
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
|
||||
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
|
||||
import org.jetbrains.kotlin.idea.testFramework.commitAllDocuments
|
||||
@@ -56,7 +57,7 @@ abstract class AbstractPerformanceCompletionIncrementalResolveTest : KotlinLight
|
||||
}
|
||||
|
||||
private fun doWarmUpPerfTest() {
|
||||
innerPerfTest("warm-up") {
|
||||
innerPerfTest(WARM_UP) {
|
||||
myFixture.configureByText(
|
||||
KotlinFileType.INSTANCE,
|
||||
"class Foo {\n private val value: String? = n<caret>\n}"
|
||||
|
||||
+2
-1
@@ -9,6 +9,7 @@ import com.intellij.codeInsight.daemon.impl.HighlightInfo
|
||||
import com.intellij.openapi.application.runWriteAction
|
||||
import com.intellij.testFramework.fixtures.impl.CodeInsightTestFixtureImpl.ensureIndexesUpToDate
|
||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||
import org.jetbrains.kotlin.idea.perf.Stats.Companion.WARM_UP
|
||||
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
|
||||
import org.jetbrains.kotlin.idea.testFramework.commitAllDocuments
|
||||
|
||||
@@ -45,7 +46,7 @@ abstract class AbstractPerformanceHighlightingTest : KotlinLightCodeInsightFixtu
|
||||
}
|
||||
|
||||
private fun doWarmUpPerfTest() {
|
||||
innerPerfTest("warm-up") {
|
||||
innerPerfTest(WARM_UP) {
|
||||
myFixture.configureByText(
|
||||
KotlinFileType.INSTANCE,
|
||||
"class Foo {\n private val value: String? = null\n}"
|
||||
|
||||
+3
-1
@@ -12,6 +12,7 @@ import com.intellij.psi.PsiDocumentManager
|
||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||
import org.jetbrains.kotlin.idea.conversion.copy.AbstractJavaToKotlinCopyPasteConversionTest
|
||||
import org.jetbrains.kotlin.idea.conversion.copy.ConvertJavaCopyPasteProcessor
|
||||
import org.jetbrains.kotlin.idea.perf.Stats.Companion.WARM_UP
|
||||
import org.jetbrains.kotlin.idea.testFramework.commitAllDocuments
|
||||
import org.jetbrains.kotlin.j2k.J2kConverterExtension
|
||||
import org.jetbrains.kotlin.test.InTextDirectivesUtils
|
||||
@@ -47,7 +48,7 @@ abstract class AbstractPerformanceJavaToKotlinCopyPasteConversionTest(private va
|
||||
|
||||
private fun doWarmUpPerfTest() {
|
||||
stats().perfTest<Unit, Unit>(
|
||||
testName = "warm-up",
|
||||
testName = WARM_UP,
|
||||
setUp = {
|
||||
with(myFixture) {
|
||||
configureByText(JavaFileType.INSTANCE, "<selection>public class Foo {\nprivate String value;\n}</selection>")
|
||||
@@ -105,6 +106,7 @@ abstract class AbstractPerformanceJavaToKotlinCopyPasteConversionTest(private va
|
||||
commitAllDocuments()
|
||||
validate(path, noConversionExpected)
|
||||
|
||||
// to avoid VFS refresh
|
||||
myFixture.performEditorAction(IdeActions.ACTION_UNDO)
|
||||
}
|
||||
)
|
||||
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.perf
|
||||
|
||||
import com.intellij.openapi.actionSystem.IdeActions
|
||||
import com.intellij.openapi.application.runWriteAction
|
||||
import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx
|
||||
import com.intellij.psi.PsiFile
|
||||
import org.jetbrains.kotlin.idea.AbstractCopyPasteTest
|
||||
import org.jetbrains.kotlin.idea.perf.Stats.Companion.WARM_UP
|
||||
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
|
||||
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||
import java.io.File
|
||||
|
||||
/**
|
||||
* Inspired by AbstractLiteralKotlinToKotlinCopyPasteTest
|
||||
*/
|
||||
abstract class AbstractPerformanceLiteralKotlinToKotlinCopyPasteTest : AbstractCopyPasteTest() {
|
||||
|
||||
companion object {
|
||||
val BASE_PATH = PluginTestCaseBase.getTestDataPathBase() + "/copyPaste/literal"
|
||||
|
||||
@JvmStatic
|
||||
var warmedUp: Boolean = false
|
||||
|
||||
@JvmStatic
|
||||
val stats: Stats = Stats("Literal-k2k-CopyPaste")
|
||||
|
||||
init {
|
||||
// there is no @AfterClass for junit3.8
|
||||
Runtime.getRuntime().addShutdownHook(Thread(Runnable { stats.close() }))
|
||||
}
|
||||
}
|
||||
|
||||
override fun getTestDataPath() = BASE_PATH
|
||||
|
||||
override fun getProjectDescriptor() = KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE
|
||||
|
||||
override fun setUp() {
|
||||
super.setUp()
|
||||
|
||||
if (!warmedUp) {
|
||||
doWarmUpPerfTest()
|
||||
warmedUp = true
|
||||
}
|
||||
}
|
||||
|
||||
private fun doWarmUpPerfTest() {
|
||||
val fileEditorManager = FileEditorManagerEx.getInstance(project)
|
||||
stats.perfTest<Pair<PsiFile, PsiFile>, Unit>(
|
||||
testName = WARM_UP,
|
||||
iterations = 1,
|
||||
setUp = {
|
||||
val file1 = myFixture.configureByText(
|
||||
"src.kt",
|
||||
"class Foo {\n <selection>private val value: String? = n<caret></selection>\n}"
|
||||
)
|
||||
val file2 = myFixture.configureByText("target.kt", "<caret>")
|
||||
it.setUpValue = Pair(file1, file2)
|
||||
},
|
||||
test = {
|
||||
fileEditorManager.setSelectedEditor(it.setUpValue!!.first.virtualFile, "")
|
||||
myFixture.performEditorAction(IdeActions.ACTION_COPY)
|
||||
|
||||
fileEditorManager.setSelectedEditor(it.setUpValue!!.second.virtualFile, "")
|
||||
myFixture.performEditorAction(IdeActions.ACTION_PASTE)
|
||||
},
|
||||
tearDown = {
|
||||
assertEquals("private val value: String? = n", it.setUpValue!!.second.text)
|
||||
|
||||
// to avoid VFS refresh
|
||||
myFixture.performEditorAction(IdeActions.ACTION_UNDO)
|
||||
|
||||
runWriteAction {
|
||||
it.setUpValue!!.first.delete()
|
||||
it.setUpValue!!.second.delete()
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
fun doPerfTest(path: String) {
|
||||
val testName = getTestName(false)
|
||||
|
||||
val fileEditorManager = FileEditorManagerEx.getInstance(project)
|
||||
stats.perfTest<Array<PsiFile>, Unit>(
|
||||
testName = testName,
|
||||
setUp = {
|
||||
it.setUpValue = myFixture.configureByFiles("$testName.kt", "$testName.to.kt")
|
||||
},
|
||||
test = {
|
||||
fileEditorManager.setSelectedEditor(it.setUpValue!![0].virtualFile, "")
|
||||
myFixture.performEditorAction(IdeActions.ACTION_COPY)
|
||||
|
||||
fileEditorManager.setSelectedEditor(it.setUpValue!![1].virtualFile, "")
|
||||
myFixture.performEditorAction(IdeActions.ACTION_PASTE)
|
||||
},
|
||||
tearDown = {
|
||||
KotlinTestUtils.assertEqualsToFile(File(path.replace(".kt", ".expected.kt")), it.setUpValue!![1].text)
|
||||
|
||||
// to avoid VFS refresh
|
||||
myFixture.performEditorAction(IdeActions.ACTION_UNDO)
|
||||
|
||||
runWriteAction {
|
||||
it.setUpValue!!.forEach { f -> f.delete() }
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.perf;
|
||||
|
||||
import com.intellij.testFramework.TestDataPath;
|
||||
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
||||
import org.jetbrains.kotlin.test.TargetBackend;
|
||||
import org.jetbrains.kotlin.test.TestMetadata;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
|
||||
@SuppressWarnings("all")
|
||||
@TestMetadata("idea/testData/copyPaste/literal")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public class PerformanceLiteralKotlinToKotlinCopyPasteTestGenerated extends AbstractPerformanceLiteralKotlinToKotlinCopyPasteTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doPerfTest, TargetBackend.ANY, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInLiteral() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/copyPaste/literal"), Pattern.compile("^([^\\.]+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("CollectionLiteralReference.kt")
|
||||
public void testCollectionLiteralReference() throws Exception {
|
||||
runTest("idea/testData/copyPaste/literal/CollectionLiteralReference.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("DontEscapeEntries.kt")
|
||||
public void testDontEscapeEntries() throws Exception {
|
||||
runTest("idea/testData/copyPaste/literal/DontEscapeEntries.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("DontEscapeEntries2.kt")
|
||||
public void testDontEscapeEntries2() throws Exception {
|
||||
runTest("idea/testData/copyPaste/literal/DontEscapeEntries2.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("DontEscapeThis.kt")
|
||||
public void testDontEscapeThis() throws Exception {
|
||||
runTest("idea/testData/copyPaste/literal/DontEscapeThis.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("DontUnescapeLiteralWIthCode.kt")
|
||||
public void testDontUnescapeLiteralWIthCode() throws Exception {
|
||||
runTest("idea/testData/copyPaste/literal/DontUnescapeLiteralWIthCode.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("UnescapeFullSelection.kt")
|
||||
public void testUnescapeFullSelection() throws Exception {
|
||||
runTest("idea/testData/copyPaste/literal/UnescapeFullSelection.kt");
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.idea.perf
|
||||
|
||||
import org.jetbrains.kotlin.idea.perf.WholeProjectPerformanceTest.Companion.nsToMs
|
||||
import org.jetbrains.kotlin.idea.perf.profilers.async.DummyProfilerHandler
|
||||
import org.jetbrains.kotlin.idea.perf.profilers.async.ProfilerHandler
|
||||
import org.jetbrains.kotlin.idea.testFramework.logMessage
|
||||
import org.jetbrains.kotlin.util.PerformanceCounter
|
||||
@@ -26,8 +27,6 @@ class Stats(val name: String = "", val header: Array<String> = arrayOf("Name", "
|
||||
|
||||
private val statsOutput: BufferedWriter
|
||||
|
||||
private val profilerHandler = ProfilerHandler.getInstance()
|
||||
|
||||
init {
|
||||
statsOutput = statsFile.bufferedWriter()
|
||||
|
||||
@@ -121,15 +120,40 @@ class Stats(val name: String = "", val header: Array<String> = arrayOf("Name", "
|
||||
iterations: Int = 20,
|
||||
setUp: (TestData<SV, TV>) -> Unit = { },
|
||||
test: (TestData<SV, TV>) -> Unit,
|
||||
tearDown: (TestData<SV, TV>) -> Unit = { }
|
||||
tearDown: (TestData<SV, TV>) -> Unit = { },
|
||||
profileEnabled: Boolean = false
|
||||
) {
|
||||
|
||||
tcSuite(testName) {
|
||||
warmUpPhase(warmUpIterations, testName, setUp, test, tearDown)
|
||||
val statInfoArray = mainPhase(iterations, testName, setUp, test, tearDown)
|
||||
val warmPhaseData = PhaseData(
|
||||
iterations = warmUpIterations,
|
||||
testName = testName,
|
||||
setUp = setUp,
|
||||
test = test,
|
||||
tearDown = tearDown,
|
||||
profileEnabled = profileEnabled
|
||||
)
|
||||
val mainPhaseData = PhaseData(
|
||||
iterations = iterations,
|
||||
testName = testName,
|
||||
setUp = setUp,
|
||||
test = test,
|
||||
tearDown = tearDown,
|
||||
profileEnabled = profileEnabled
|
||||
)
|
||||
val block = {
|
||||
warmUpPhase(warmPhaseData)
|
||||
val statInfoArray = mainPhase(mainPhaseData)
|
||||
|
||||
assertEquals(iterations, statInfoArray.size)
|
||||
appendTimings(testName, statInfoArray)
|
||||
if (testName != WARM_UP) {
|
||||
appendTimings(testName, statInfoArray)
|
||||
}
|
||||
}
|
||||
|
||||
if (testName != WARM_UP) {
|
||||
tcSuite(testName, block)
|
||||
} else {
|
||||
block()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,7 +164,7 @@ class Stats(val name: String = "", val header: Array<String> = arrayOf("Name", "
|
||||
) {
|
||||
for (statInfoIndex in statInfoArray.withIndex()) {
|
||||
val attempt = statInfoIndex.index
|
||||
val statInfo = statInfoIndex.value!!
|
||||
val statInfo = statInfoIndex.value ?: continue
|
||||
val n = "$name: $prefix ${attemptFn(attempt)}"
|
||||
printTestStarted(n)
|
||||
val t = statInfo[ERROR_KEY] as? Throwable
|
||||
@@ -168,83 +192,67 @@ class Stats(val name: String = "", val header: Array<String> = arrayOf("Name", "
|
||||
append("$name: $prefix", statInfosArray)
|
||||
}
|
||||
|
||||
private fun <K, T> mainPhase(
|
||||
iterations: Int,
|
||||
testName: String,
|
||||
setUp: (TestData<K, T>) -> Unit,
|
||||
test: (TestData<K, T>) -> Unit,
|
||||
tearDown: (TestData<K, T>) -> Unit
|
||||
): Array<StatInfos> {
|
||||
val statInfosArray = phase(testName, "", iterations, setUp, test, tearDown)
|
||||
private fun <SV, TV> warmUpPhase(phaseData: PhaseData<SV, TV>) {
|
||||
val warmUpStatInfosArray = phase(phaseData, WARM_UP)
|
||||
|
||||
if (phaseData.testName != WARM_UP) {
|
||||
printWarmUpTimings(phaseData.testName, warmUpStatInfosArray)
|
||||
}
|
||||
|
||||
warmUpStatInfosArray.filterNotNull().map { it[ERROR_KEY] as? Exception }.firstOrNull()?.let { throw it }
|
||||
}
|
||||
|
||||
private fun <SV, TV> mainPhase(phaseData: PhaseData<SV, TV>): Array<StatInfos> {
|
||||
val statInfosArray = phase(phaseData, "")
|
||||
|
||||
// do not estimate stability for warm-up
|
||||
if (!testName.contains(WARM_UP)) {
|
||||
if (!phaseData.testName.contains(WARM_UP)) {
|
||||
val calcMean = calcMean(statInfosArray)
|
||||
val stabilityPercentage = round(calcMean.stdDev * 100.0 / calcMean.mean).toInt()
|
||||
logMessage { "$testName stability is $stabilityPercentage %" }
|
||||
check(stabilityPercentage <= 10) { "$testName is not stable: stability above $stabilityPercentage %" }
|
||||
logMessage { "${phaseData.testName} stability is $stabilityPercentage %" }
|
||||
check(stabilityPercentage <= 10) { "${phaseData.testName} is not stable: stability above $stabilityPercentage %" }
|
||||
}
|
||||
|
||||
return statInfosArray
|
||||
}
|
||||
|
||||
private fun <K, T> warmUpPhase(
|
||||
warmUpIterations: Int,
|
||||
testName: String,
|
||||
setUp: (TestData<K, T>) -> Unit,
|
||||
test: (TestData<K, T>) -> Unit,
|
||||
tearDown: (TestData<K, T>) -> Unit
|
||||
) {
|
||||
val warmUpStatInfosArray = phase(testName, "warm-up", warmUpIterations, setUp, test, tearDown)
|
||||
private fun <SV, TV> phase(phaseData: PhaseData<SV, TV>, phaseName: String): Array<StatInfos> {
|
||||
val statInfosArray = Array<StatInfos>(phaseData.iterations) { null }
|
||||
val testData = TestData<SV, TV>(null, null)
|
||||
|
||||
printWarmUpTimings(testName, warmUpStatInfosArray)
|
||||
|
||||
warmUpStatInfosArray.filterNotNull().map { it[ERROR_KEY] as? Exception }.firstOrNull()?.let { throw it }
|
||||
}
|
||||
|
||||
private fun <K, T> phase(
|
||||
namePrefix: String,
|
||||
phaseName: String,
|
||||
iterations: Int,
|
||||
setUp: (TestData<K, T>) -> Unit,
|
||||
test: (TestData<K, T>) -> Unit,
|
||||
tearDown: (TestData<K, T>) -> Unit
|
||||
): Array<StatInfos> {
|
||||
val statInfosArray = Array<StatInfos>(iterations) { null }
|
||||
val testData = TestData<K, T>(null, null)
|
||||
val profilerPath = pathToResource("profile/${plainname()}/")
|
||||
check(with(File(profilerPath)) { exists() || mkdirs() }) { "unable to mkdirs $profilerPath for $namePrefix" }
|
||||
try {
|
||||
for (attempt in 0 until iterations) {
|
||||
for (attempt in 0 until phaseData.iterations) {
|
||||
testData.reset()
|
||||
triggerGC(attempt)
|
||||
|
||||
val setUpMillis = measureTimeMillis {
|
||||
setUp(testData)
|
||||
}
|
||||
val phaseProfiler = createPhaseProfiler(phaseData, phaseName, attempt)
|
||||
|
||||
val setUpMillis = measureTimeMillis { phaseData.setUp(testData) }
|
||||
logMessage { "setup took $setUpMillis ms" }
|
||||
|
||||
val valueMap = HashMap<String, Any>(2 * PerformanceCounter.numberOfCounters + 1)
|
||||
statInfosArray[attempt] = valueMap
|
||||
try {
|
||||
val activityName = "$namePrefix-${if (phaseName.isEmpty()) "" else "$phaseName-"}$attempt"
|
||||
profilerHandler.startProfiling(activityName)
|
||||
|
||||
phaseProfiler.start()
|
||||
valueMap[TEST_KEY] = measureNanoTime {
|
||||
test(testData)
|
||||
phaseData.test(testData)
|
||||
}
|
||||
profilerHandler.stopProfiling(profilerPath, activityName)
|
||||
phaseProfiler.stop()
|
||||
|
||||
PerformanceCounter.report { name, counter, nanos ->
|
||||
valueMap["counter \"$name\": count"] = counter.toLong()
|
||||
valueMap["counter \"$name\": time"] = nanos.nsToMs
|
||||
}
|
||||
|
||||
} catch (t: Throwable) {
|
||||
println("# error at $namePrefix #$attempt:")
|
||||
println("# error at ${phaseData.testName} #$attempt:")
|
||||
t.printStackTrace()
|
||||
valueMap[ERROR_KEY] = t
|
||||
} finally {
|
||||
try {
|
||||
val tearDownMillis = measureTimeMillis {
|
||||
tearDown(testData)
|
||||
phaseData.tearDown(testData)
|
||||
}
|
||||
logMessage { "tearDown took $tearDownMillis ms" }
|
||||
} finally {
|
||||
@@ -253,12 +261,30 @@ class Stats(val name: String = "", val header: Array<String> = arrayOf("Name", "
|
||||
}
|
||||
}
|
||||
} catch (t: Throwable) {
|
||||
println("error at $namePrefix:")
|
||||
tcPrintErrors(namePrefix, listOf(t))
|
||||
println("error at ${phaseData.testName}:")
|
||||
tcPrintErrors(phaseData.testName, listOf(t))
|
||||
}
|
||||
return statInfosArray
|
||||
}
|
||||
|
||||
private fun <K, T> createPhaseProfiler(
|
||||
phaseData: PhaseData<K, T>,
|
||||
phaseName: String,
|
||||
attempt: Int
|
||||
): PhaseProfiler {
|
||||
val profilerHandler = if (phaseData.profileEnabled) ProfilerHandler.getInstance() else DummyProfilerHandler
|
||||
|
||||
return if (profilerHandler != DummyProfilerHandler) {
|
||||
val profilerPath = pathToResource("profile/${plainname()}/")
|
||||
check(with(File(profilerPath)) { exists() || mkdirs() }) { "unable to mkdirs $profilerPath for ${phaseData.testName}" }
|
||||
val activityName = "${phaseData.testName}-${if (phaseName.isEmpty()) "" else "$phaseName-"}$attempt"
|
||||
|
||||
ActualPhaseProfiler(activityName, profilerPath, profilerHandler)
|
||||
} else {
|
||||
dummyPhaseProfiler
|
||||
}
|
||||
}
|
||||
|
||||
private fun triggerGC(attempt: Int) {
|
||||
if (attempt > 0) {
|
||||
val ref = WeakReference(IntArray(32 * 1024))
|
||||
@@ -287,6 +313,11 @@ class Stats(val name: String = "", val header: Array<String> = arrayOf("Name", "
|
||||
|
||||
const val WARM_UP = "warm-up"
|
||||
|
||||
private val dummyPhaseProfiler = object : PhaseProfiler {
|
||||
override fun start() {}
|
||||
override fun stop() {}
|
||||
}
|
||||
|
||||
inline fun runAndMeasure(note: String, block: () -> Unit) {
|
||||
val openProjectMillis = measureTimeMillis {
|
||||
block()
|
||||
@@ -354,8 +385,34 @@ class Stats(val name: String = "", val header: Array<String> = arrayOf("Name", "
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private interface PhaseProfiler {
|
||||
fun start()
|
||||
|
||||
fun stop()
|
||||
}
|
||||
|
||||
private class ActualPhaseProfiler(val activityName: String, val profilerPath: String, val profilerHandler: ProfilerHandler) :
|
||||
PhaseProfiler {
|
||||
override fun start() {
|
||||
profilerHandler.startProfiling(activityName)
|
||||
}
|
||||
|
||||
override fun stop() {
|
||||
profilerHandler.stopProfiling(profilerPath, activityName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class PhaseData<SV, TV>(
|
||||
val iterations: Int,
|
||||
val testName: String,
|
||||
val setUp: (TestData<SV, TV>) -> Unit,
|
||||
val test: (TestData<SV, TV>) -> Unit,
|
||||
val tearDown: (TestData<SV, TV>) -> Unit,
|
||||
val profileEnabled: Boolean = false
|
||||
)
|
||||
|
||||
data class TestData<SV, TV>(var setUpValue: SV?, var value: TV?) {
|
||||
fun reset() {
|
||||
setUpValue = null
|
||||
|
||||
Reference in New Issue
Block a user