Objective c interop benchmarks migration (#3004)
This commit is contained in:
+7
-8
@@ -103,33 +103,32 @@ To update the blackbox compiler tests set TeamCity build number in `gradle.prope
|
||||
|
||||
To measure performance of Kotlin/Native compiler on existing benchmarks:
|
||||
|
||||
cd performance
|
||||
../gradlew konanRun
|
||||
./gradlew :performance:konanRun
|
||||
|
||||
**konanRun** task can be run separately for one/several benchmark applications:
|
||||
|
||||
../gradlew :cinterop:konanRun
|
||||
./gradlew :performance:cinterop:konanRun
|
||||
|
||||
**konanRun** task has parameter `filter` which allows to run only some subset of benchmarks:
|
||||
|
||||
../gradlew :cinterop:konanRun --filter=struct,macros
|
||||
./gradlew :performance:cinterop:konanRun --filter=struct,macros
|
||||
|
||||
Or you can use `filterRegex` if you want to specify the filter as regexes:
|
||||
|
||||
../gradlew :ring:konanRun --filterRegex=String.*,Loop.*
|
||||
./gradlew :performance:ring:konanRun --filterRegex=String.*,Loop.*
|
||||
|
||||
There are also tasks for running benchmarks on JVM (pay attention, some benchmarks e.g. cinterop benchmarks can't be run on JVM)
|
||||
|
||||
../gradlew jvmRun
|
||||
./gradlew :performance:jvmRun
|
||||
|
||||
Files with results of benchmarks run are saved in `performance/build/nativeReport.json` for konanRun and `jvmReport.json` for jvmRun.
|
||||
You can change the output filename by setting the `nativeJson` property for konanRun and `jvmJson` for jvmRun:
|
||||
|
||||
../gradlew :ring:konanRun --filter=String.*,Loop.* -PnativeJson=stringsAndLoops.json
|
||||
./gradlew :performance:ring:konanRun --filter=String.*,Loop.* -PnativeJson=stringsAndLoops.json
|
||||
|
||||
You can use the `compilerArgs` property to pass flags to the compiler used to compile the benchmarks:
|
||||
|
||||
../gradlew konanRun -PcompilerArgs="--time -g"
|
||||
./gradlew :performance:konanRun -PcompilerArgs="--time -g"
|
||||
|
||||
To compare different results run benchmarksAnalyzer tool:
|
||||
|
||||
|
||||
@@ -3098,7 +3098,7 @@ kotlinNativeInterop {
|
||||
defFile 'interop/basics/ccallbacksAndVarargs.def'
|
||||
}
|
||||
|
||||
if (isAppleTarget(project)) {
|
||||
if (PlatformInfo.isAppleTarget(project)) {
|
||||
objcSmoke {
|
||||
defFile 'interop/objc/objcSmoke.def'
|
||||
headers "$projectDir/interop/objc/smoke.h"
|
||||
@@ -3447,7 +3447,7 @@ task runKonanRegexTests(type: RunKonanTest) {
|
||||
|
||||
task coverage_basic_program(type: RunStandaloneKonanTest) {
|
||||
|
||||
disabled = getTarget(project).name != "ios_x64" && getTarget(project).name != "macos_x64"
|
||||
disabled = PlatformInfo.getTarget(project).name != "ios_x64" && PlatformInfo.getTarget(project).name != "macos_x64"
|
||||
|
||||
description = "Test that `-Xcoverage` generates correct __llvm_coverage information"
|
||||
|
||||
@@ -3476,7 +3476,7 @@ task coverage_basic_program(type: RunStandaloneKonanTest) {
|
||||
|
||||
task coverage_basic_library(type: RunStandaloneKonanTest) {
|
||||
|
||||
disabled = getTarget(project).name != "ios_x64" && getTarget(project).name != "macos_x64"
|
||||
disabled = PlatformInfo.getTarget(project).name != "ios_x64" && PlatformInfo.getTarget(project).name != "macos_x64"
|
||||
|
||||
description = "Test that `-Xlibrary-to-cover` generates correct __llvm_coverage information"
|
||||
|
||||
@@ -3486,7 +3486,7 @@ task coverage_basic_library(type: RunStandaloneKonanTest) {
|
||||
doFirst {
|
||||
def konancScript = isWindows() ? "konanc.bat" : "konanc"
|
||||
def konanc = "$dist/bin/$konancScript"
|
||||
"$konanc -target ${getTarget(project).name} $projectDir/coverage/basic/library/library.kt -p library -o $dir/lib_to_cover".execute().waitFor()
|
||||
"$konanc -target ${PlatformInfo.getTarget(project).name} $projectDir/coverage/basic/library/library.kt -p library -o $dir/lib_to_cover".execute().waitFor()
|
||||
}
|
||||
|
||||
flags = ["-Xcoverage-file=$dir/program.profraw", "-l", "$dir/lib_to_cover", "-Xlibrary-to-cover=$dir/lib_to_cover.klib", "-entry", "coverage.basic.library.main"]
|
||||
|
||||
+10
-46
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.konan.target.*
|
||||
import org.jetbrains.kotlin.konan.util.*
|
||||
import org.jetbrains.kotlin.CopySamples
|
||||
import org.jetbrains.kotlin.CopyCommonSources
|
||||
import org.jetbrains.kotlin.PlatformInfo
|
||||
import org.jetbrains.kotlin.konan.*
|
||||
|
||||
buildscript {
|
||||
@@ -41,7 +42,7 @@ wrapper.distributionType = Wrapper.DistributionType.ALL
|
||||
|
||||
defaultTasks 'clean', 'dist'
|
||||
|
||||
convention.plugins.platformInfo = new PlatformInfo()
|
||||
convention.plugins.platformInfo = PlatformInfo
|
||||
|
||||
ext {
|
||||
distDir = file('dist')
|
||||
@@ -161,43 +162,6 @@ void loadCommandLineProperties() {
|
||||
ext.testTarget = project.hasProperty("test_target") ? ext.test_target : null
|
||||
}
|
||||
|
||||
class PlatformInfo {
|
||||
boolean isMac() {
|
||||
return HostManager.hostIsMac
|
||||
}
|
||||
|
||||
boolean isWindows() {
|
||||
return HostManager.hostIsMingw
|
||||
}
|
||||
|
||||
boolean isLinux() {
|
||||
return HostManager.hostIsLinux
|
||||
}
|
||||
|
||||
boolean isAppleTarget(Project project) {
|
||||
def target = getTarget(project)
|
||||
return target.family == Family.IOS || target.family == Family.OSX
|
||||
}
|
||||
|
||||
boolean isWindowsTarget(Project project) {
|
||||
return getTarget(project).family == Family.MINGW
|
||||
}
|
||||
|
||||
boolean isWasmTarget(Project project) {
|
||||
return getTarget(project).family == Family.WASM
|
||||
}
|
||||
|
||||
KonanTarget getTarget(Project project) {
|
||||
def platformManager = project.rootProject.platformManager
|
||||
def targetName = project.project.testTarget ?: 'host'
|
||||
return platformManager.targetManager(targetName).target
|
||||
}
|
||||
|
||||
Throwable unsupportedPlatformException() {
|
||||
return new TargetSupportException()
|
||||
}
|
||||
}
|
||||
|
||||
configurations {
|
||||
ftpAntTask
|
||||
kotlinCommonSources
|
||||
@@ -343,7 +307,7 @@ task distCompiler(type: Copy) {
|
||||
from(file('cmd')) {
|
||||
fileMode(0755)
|
||||
into('bin')
|
||||
if (!isWindows()) {
|
||||
if (!PlatformInfo.isWindows()) {
|
||||
exclude('**/*.bat')
|
||||
}
|
||||
}
|
||||
@@ -501,6 +465,12 @@ task samples {
|
||||
dependsOn 'samplesZip', 'samplesTar'
|
||||
}
|
||||
|
||||
task performance {
|
||||
dependsOn 'dist'
|
||||
dependsOn ':performance:clean'
|
||||
dependsOn ':performance:konanRun'
|
||||
}
|
||||
|
||||
task samplesZip(type: Zip)
|
||||
task samplesTar(type: Tar) {
|
||||
extension = 'tar.gz'
|
||||
@@ -562,12 +532,6 @@ task uploadBundle {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO return when problems with HostManagers will be solved
|
||||
/*task performance {
|
||||
dependsOn 'dist'
|
||||
dependsOn ':performance:bench'
|
||||
}*/
|
||||
|
||||
task teamcityKonanVersion {
|
||||
doLast {
|
||||
println("##teamcity[setParameter name='kotlin.native.version.base' value='$konanVersion']")
|
||||
@@ -583,4 +547,4 @@ task clean {
|
||||
delete distDir
|
||||
delete bundle.outputs.files
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@ buildscript {
|
||||
apply from: "$rootBuildDirectory/gradle/kotlinGradlePlugin.gradle"
|
||||
dependencies{
|
||||
classpath "org.jetbrains.kotlin:kotlin-serialization:$buildKotlinVersion"
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
|
||||
}
|
||||
|
||||
}
|
||||
@@ -37,13 +38,15 @@ dependencies {
|
||||
compile localGroovy()
|
||||
compile "org.jetbrains.kotlin:kotlin-stdlib:$buildKotlinVersion"
|
||||
compile "org.jetbrains.kotlin:kotlin-reflect:$buildKotlinVersion"
|
||||
compile group: 'com.ullink.slack', name: 'simpleslackapi', version: '0.6.0'
|
||||
compile group: 'com.ullink.slack', name: 'simpleslackapi', version: '1.2.0'
|
||||
// An artifact from the included build 'shared' cannot be used here due to https://github.com/gradle/gradle/issues/3768
|
||||
// TODO: Remove this hack when the bug is fixed
|
||||
implementation "org.jetbrains.kotlin:kotlin-gradle-plugin"
|
||||
compile project(':shared')
|
||||
compile "org.jetbrains.kotlinx:kotlinx-serialization-runtime:0.10.0"
|
||||
}
|
||||
|
||||
sourceSets.main.kotlin.srcDirs = ["src", "$projectDir/../../tools/benchmarks/shared/src"]
|
||||
|
||||
rootProject.dependencies {
|
||||
runtime project(path)
|
||||
}
|
||||
|
||||
+2
@@ -3,6 +3,8 @@
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin
|
||||
|
||||
import groovy.lang.Closure
|
||||
import org.gradle.api.Action
|
||||
import org.gradle.api.DefaultTask
|
||||
@@ -78,7 +78,7 @@ open class FrameworkTest : DefaultTask() {
|
||||
listOf(provider.toString(), swiftMain)
|
||||
val options = listOf("-g", "-Xlinker", "-rpath", "-Xlinker", frameworkParentDirPath, "-F", frameworkParentDirPath)
|
||||
val testExecutable = Paths.get(testOutput, frameworkName, "swiftTestExecutable")
|
||||
swiftc(sources, options, testExecutable)
|
||||
compileSwift(project, project.testTarget(), sources, options, testExecutable, fullBitcode)
|
||||
|
||||
runTest(testExecutable)
|
||||
}
|
||||
@@ -117,36 +117,6 @@ open class FrameworkTest : DefaultTask() {
|
||||
check(exitCode == 0, { "Execution failed with exit code: $exitCode "})
|
||||
}
|
||||
|
||||
private fun swiftc(sources: List<String>, options: List<String>, output: Path) {
|
||||
val target = project.testTarget()
|
||||
val platform = project.platformManager().platform(target)
|
||||
assert(platform.configurables is AppleConfigurables)
|
||||
val configs = platform.configurables as AppleConfigurables
|
||||
val compiler = configs.absoluteTargetToolchain + "/usr/bin/swiftc"
|
||||
|
||||
val swiftTarget = when (target) {
|
||||
KonanTarget.IOS_X64 -> "x86_64-apple-ios" + configs.osVersionMin
|
||||
KonanTarget.IOS_ARM64 -> "arm64_64-apple-ios" + configs.osVersionMin
|
||||
KonanTarget.MACOS_X64 -> "x86_64-apple-macosx" + configs.osVersionMin
|
||||
else -> throw IllegalStateException("Test target $target is not supported")
|
||||
}
|
||||
|
||||
val args = listOf("-sdk", configs.absoluteTargetSysRoot, "-target", swiftTarget) +
|
||||
options + "-o" + output.toString() + sources +
|
||||
if (fullBitcode) listOf("-embed-bitcode", "-Xlinker", "-bitcode_verify") else listOf("-embed-bitcode-marker")
|
||||
|
||||
val (stdOut, stdErr, exitCode) = runProcess(executor = localExecutor(project), executable = compiler, args = args)
|
||||
|
||||
println("""
|
||||
|$compiler finished with exit code: $exitCode
|
||||
|options: ${args.joinToString(separator = " ")}
|
||||
|stdout: $stdOut
|
||||
|stderr: $stdErr
|
||||
""".trimMargin())
|
||||
check(exitCode == 0, { "Compilation failed" })
|
||||
check(output.toFile().exists(), { "Compiler swiftc hasn't produced an output file: $output" })
|
||||
}
|
||||
|
||||
private fun validateBitcodeEmbedding(frameworkBinary: String) {
|
||||
// Check only the full bitcode embedding for now.
|
||||
if (!fullBitcode) {
|
||||
|
||||
+2
@@ -3,6 +3,8 @@
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin
|
||||
|
||||
import org.gradle.api.NamedDomainObjectCollection
|
||||
import org.gradle.api.NamedDomainObjectContainer
|
||||
import org.gradle.api.Project
|
||||
+24
-20
@@ -5,11 +5,14 @@
|
||||
|
||||
@file:JvmName("MPPTools")
|
||||
|
||||
package org.jetbrains.kotlin
|
||||
|
||||
import groovy.lang.Closure
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.Task
|
||||
import org.gradle.api.tasks.TaskState
|
||||
import org.gradle.api.execution.TaskExecutionListener
|
||||
import org.gradle.api.tasks.AbstractExecTask
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinTargetPreset
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
|
||||
import org.jetbrains.report.*
|
||||
@@ -27,16 +30,6 @@ import java.util.Base64
|
||||
* This file includes short-cuts that may potentially be implemented in Kotlin MPP Gradle plugin in the future.
|
||||
*/
|
||||
|
||||
// Short-cuts for detecting the host OS.
|
||||
@get:JvmName("isMacos")
|
||||
val isMacos by lazy { hostOs == "Mac OS X" }
|
||||
|
||||
@get:JvmName("isWindows")
|
||||
val isWindows by lazy { hostOs.startsWith("Windows") }
|
||||
|
||||
@get:JvmName("isLinux")
|
||||
val isLinux by lazy { hostOs == "Linux" }
|
||||
|
||||
// Short-cuts for mostly used paths.
|
||||
@get:JvmName("mingwPath")
|
||||
val mingwPath by lazy { System.getenv("MINGW64_DIR") ?: "c:/msys64/mingw64" }
|
||||
@@ -57,9 +50,9 @@ fun defaultHostPreset(
|
||||
throw Exception("Preset whitelist must not be empty in Kotlin/Native ${subproject.displayName}.")
|
||||
|
||||
val presetCandidate = when {
|
||||
isMacos -> subproject.kotlin.presets.macosX64
|
||||
isLinux -> subproject.kotlin.presets.linuxX64
|
||||
isWindows -> subproject.kotlin.presets.mingwX64
|
||||
PlatformInfo.isMac() -> subproject.kotlin.presets.macosX64
|
||||
PlatformInfo.isLinux() -> subproject.kotlin.presets.linuxX64
|
||||
PlatformInfo.isWindows() -> subproject.kotlin.presets.mingwX64
|
||||
else -> null
|
||||
}
|
||||
|
||||
@@ -70,9 +63,9 @@ fun defaultHostPreset(
|
||||
}
|
||||
|
||||
fun getNativeProgramExtension(): String = when {
|
||||
isMacos -> ".kexe"
|
||||
isLinux -> ".kexe"
|
||||
isWindows -> ".exe"
|
||||
PlatformInfo.isMac() -> ".kexe"
|
||||
PlatformInfo.isLinux() -> ".kexe"
|
||||
PlatformInfo.isWindows() -> ".exe"
|
||||
else -> error("Unknown host")
|
||||
}
|
||||
|
||||
@@ -161,10 +154,21 @@ fun sendUploadRequest(url: String, fileName: String, username: String? = null, p
|
||||
fun createRunTask(
|
||||
subproject: Project,
|
||||
name: String,
|
||||
target: KotlinNativeTarget,
|
||||
runTask: AbstractExecTask<*>,
|
||||
configureClosure: Closure<Any>? = null
|
||||
): Task {
|
||||
val task = subproject.tasks.create(name, RunKotlinNativeTask::class.java, target)
|
||||
val task = subproject.tasks.create(name, RunKotlinNativeTask::class.java, runTask)
|
||||
task.configure(configureClosure ?: task.emptyConfigureClosure())
|
||||
return task
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
fun createBenchmarksRunTask(
|
||||
subproject: Project,
|
||||
name: String,
|
||||
configureClosure: Closure<Any>? = null
|
||||
): Task {
|
||||
val task = subproject.tasks.create(name, RunBenchmarksExecutableTask::class.java)
|
||||
task.configure(configureClosure ?: task.emptyConfigureClosure())
|
||||
return task
|
||||
}
|
||||
@@ -174,7 +178,7 @@ fun getJvmCompileTime(programName: String): BenchmarkResult =
|
||||
|
||||
@JvmOverloads
|
||||
fun getNativeCompileTime(programName: String,
|
||||
tasks: List<String> = listOf("compileKotlinNative", "linkBenchmarkReleaseExecutableNative")): BenchmarkResult =
|
||||
tasks: List<String> = listOf("linkBenchmarkReleaseExecutableNative")): BenchmarkResult =
|
||||
TaskTimerListener.getBenchmarkResult(programName, tasks)
|
||||
|
||||
fun getCompileBenchmarkTime(programName: String, tasksNames: Iterable<String>, repeats: Int, exitCodes: Map<String, Int>) =
|
||||
@@ -207,7 +211,7 @@ class TaskTimerListener: TaskExecutionListener {
|
||||
fun getTime(taskName: String) = tasksTimes[taskName] ?: 0.0
|
||||
}
|
||||
|
||||
private var startTime = System.currentTimeMillis()
|
||||
private var startTime = System.nanoTime()
|
||||
|
||||
override fun beforeExecute(task: Task) {
|
||||
startTime = System.nanoTime()
|
||||
@@ -0,0 +1,41 @@
|
||||
package org.jetbrains.kotlin
|
||||
|
||||
import org.jetbrains.kotlin.konan.target.*
|
||||
import org.jetbrains.kotlin.konan.util.*
|
||||
import org.gradle.api.Project
|
||||
|
||||
object PlatformInfo {
|
||||
@JvmStatic
|
||||
fun isMac() = HostManager.hostIsMac
|
||||
@JvmStatic
|
||||
fun isWindows() = HostManager.hostIsMingw
|
||||
@JvmStatic
|
||||
fun isLinux() = HostManager.hostIsLinux
|
||||
|
||||
@JvmStatic
|
||||
fun isAppleTarget(project: Project): Boolean {
|
||||
val target = getTarget(project)
|
||||
return target.family == Family.IOS || target.family == Family.OSX
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun isAppleTarget(target: KonanTarget): Boolean {
|
||||
return target.family == Family.IOS || target.family == Family.OSX
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun isWindowsTarget(project: Project) = getTarget(project).family == Family.MINGW
|
||||
|
||||
@JvmStatic
|
||||
fun isWasmTarget(project: Project) =
|
||||
getTarget(project).family == Family.WASM
|
||||
|
||||
@JvmStatic
|
||||
fun getTarget(project: Project): KonanTarget {
|
||||
val platformManager = project.rootProject.platformManager()
|
||||
val targetName = project.project.testTarget().name
|
||||
return platformManager.targetManager(targetName).target
|
||||
}
|
||||
|
||||
fun unsupportedPlatformException() = TargetSupportException()
|
||||
}
|
||||
+1
-1
@@ -2,6 +2,7 @@
|
||||
* Copyright 2010-2018 JetBrains s.r.o. 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
|
||||
|
||||
import groovy.lang.Closure
|
||||
import org.gradle.api.Action
|
||||
@@ -37,7 +38,6 @@ import java.util.Properties
|
||||
*/
|
||||
open class RegressionsReporter : DefaultTask() {
|
||||
|
||||
|
||||
val slackUsers = mapOf(
|
||||
"olonho" to "nikolay.igotti",
|
||||
"nikolay.igotti" to "nikolay.igotti",
|
||||
+2
@@ -3,6 +3,8 @@
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin
|
||||
|
||||
import groovy.lang.Closure
|
||||
import org.gradle.api.Action
|
||||
import org.gradle.api.DefaultTask
|
||||
+8
-11
@@ -3,23 +3,21 @@
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin
|
||||
|
||||
import groovy.lang.Closure
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.Task
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
import org.gradle.api.tasks.options.Option
|
||||
import org.gradle.api.tasks.Input
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
|
||||
import javax.inject.Inject
|
||||
import java.io.File
|
||||
|
||||
open class RunKotlinNativeTask @Inject constructor(
|
||||
private val curTarget: KotlinNativeTarget
|
||||
) : DefaultTask() {
|
||||
|
||||
var buildType = "RELEASE"
|
||||
open class RunBenchmarksExecutableTask @Inject constructor() : DefaultTask() {
|
||||
var workingDir: Any = project.projectDir
|
||||
var outputFileName: String? = null
|
||||
var executable: String? = null
|
||||
@Input
|
||||
@Option(option = "filter", description = "Benchmarks to run (comma-separated)")
|
||||
var filter: String = ""
|
||||
@@ -40,7 +38,6 @@ open class RunKotlinNativeTask @Inject constructor(
|
||||
|
||||
override fun configure(configureClosure: Closure<Any>): Task {
|
||||
val task = super.configure(configureClosure)
|
||||
this.dependsOn += curTarget.binaries.getExecutable("benchmark", buildType).linkTaskName
|
||||
return task
|
||||
}
|
||||
|
||||
@@ -52,7 +49,7 @@ open class RunKotlinNativeTask @Inject constructor(
|
||||
val filterArgs = filter.splitCommaSeparatedOption("-f")
|
||||
val filterRegexArgs = filterRegex.splitCommaSeparatedOption("-fr")
|
||||
project.exec {
|
||||
it.executable = curTarget.binaries.getExecutable("benchmark", buildType).outputFile.getAbsolutePath()
|
||||
it.executable = executable
|
||||
it.args = curArgs + filterArgs + filterRegexArgs
|
||||
it.environment = curEnvironment
|
||||
it.workingDir(workingDir)
|
||||
@@ -70,8 +67,8 @@ open class RunKotlinNativeTask @Inject constructor(
|
||||
}
|
||||
|
||||
internal fun emptyConfigureClosure() = object : Closure<Any>(this) {
|
||||
override fun call(): RunKotlinNativeTask {
|
||||
return this@RunKotlinNativeTask
|
||||
override fun call(): RunBenchmarksExecutableTask {
|
||||
return this@RunBenchmarksExecutableTask
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
@@ -3,6 +3,8 @@
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin
|
||||
|
||||
import groovy.lang.Closure
|
||||
import org.gradle.api.tasks.JavaExec
|
||||
import org.gradle.api.Task
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. 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
|
||||
|
||||
import groovy.lang.Closure
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.Task
|
||||
import org.gradle.api.tasks.AbstractExecTask
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
import org.gradle.api.tasks.options.Option
|
||||
import org.gradle.api.tasks.Input
|
||||
import javax.inject.Inject
|
||||
|
||||
open class RunKotlinNativeTask @Inject constructor(
|
||||
private val runTask: AbstractExecTask<*>
|
||||
) : DefaultTask() {
|
||||
@Input
|
||||
var buildType = "RELEASE"
|
||||
@Input
|
||||
@Option(option = "filter", description = "Benchmarks to run (comma-separated)")
|
||||
var filter: String = ""
|
||||
@Input
|
||||
@Option(option = "filterRegex", description = "Benchmarks to run, described by regular expressions (comma-separated)")
|
||||
var filterRegex: String = ""
|
||||
|
||||
override fun configure(configureClosure: Closure<Any>): Task {
|
||||
val task = super.configure(configureClosure)
|
||||
this.finalizedBy(runTask.name)
|
||||
runTask.finalizedBy("konanJsonReport")
|
||||
return task
|
||||
}
|
||||
|
||||
fun depends(taskName: String) {
|
||||
this.dependsOn += taskName
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
fun run() {
|
||||
runTask.run {
|
||||
val filterArgs = filter.splitCommaSeparatedOption("-f")
|
||||
val filterRegexArgs = filterRegex.splitCommaSeparatedOption("-fr")
|
||||
runTask.args(filterArgs)
|
||||
runTask.args(filterRegexArgs)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun emptyConfigureClosure() = object : Closure<Any>(this) {
|
||||
override fun call(): RunKotlinNativeTask {
|
||||
return this@RunKotlinNativeTask
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,21 @@
|
||||
package org.jetbrains.kotlin
|
||||
|
||||
import org.gradle.api.Project
|
||||
import org.jetbrains.kotlin.konan.target.AppleConfigurables
|
||||
import org.jetbrains.kotlin.konan.target.HostManager
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
import org.jetbrains.kotlin.konan.target.PlatformManager
|
||||
|
||||
import java.io.FileInputStream
|
||||
import java.io.IOException
|
||||
import java.io.File
|
||||
import java.util.concurrent.TimeUnit
|
||||
import java.net.HttpURLConnection
|
||||
import java.net.URL
|
||||
import java.util.Base64
|
||||
import org.jetbrains.report.json.*
|
||||
import java.nio.file.Path
|
||||
|
||||
fun Project.platformManager() = findProperty("platformManager") as PlatformManager
|
||||
fun Project.testTarget() = findProperty("target") as KonanTarget
|
||||
|
||||
@@ -12,13 +23,126 @@ fun Project.testTarget() = findProperty("target") as KonanTarget
|
||||
* Ad-hoc signing of the specified path
|
||||
*/
|
||||
fun codesign(project: Project, path: String) {
|
||||
check(HostManager.hostIsMac, { "Apple specific code signing" } )
|
||||
check(HostManager.hostIsMac, { "Apple specific code signing" })
|
||||
val (stdOut, stdErr, exitCode) = runProcess(executor = localExecutor(project), executable = "/usr/bin/codesign",
|
||||
args = listOf("--verbose", "-s", "-", path))
|
||||
check(exitCode == 0, { """
|
||||
check(exitCode == 0, {
|
||||
"""
|
||||
|Codesign failed with exitCode: $exitCode
|
||||
|stdout: $stdOut
|
||||
|stderr: $stdErr
|
||||
""".trimMargin()
|
||||
})
|
||||
}
|
||||
|
||||
// Run command line from string.
|
||||
fun Array<String>.runCommand(workingDir: File = File("."),
|
||||
timeoutAmount: Long = 60,
|
||||
timeoutUnit: TimeUnit = TimeUnit.SECONDS): String {
|
||||
return try {
|
||||
ProcessBuilder(*this)
|
||||
.directory(workingDir)
|
||||
.redirectOutput(ProcessBuilder.Redirect.PIPE)
|
||||
.redirectError(ProcessBuilder.Redirect.PIPE)
|
||||
.start().apply {
|
||||
waitFor(timeoutAmount, timeoutUnit)
|
||||
}.inputStream.bufferedReader().readText()
|
||||
} catch (e: IOException) {
|
||||
error("Couldn't run command $this")
|
||||
}
|
||||
}
|
||||
|
||||
fun String.splitCommaSeparatedOption(optionName: String) =
|
||||
split("\\s*,\\s*".toRegex()).map {
|
||||
if (it.isNotEmpty()) listOf(optionName, it) else listOf(null)
|
||||
}.flatten().filterNotNull()
|
||||
|
||||
data class Commit(val revision: String, val developer: String, val webUrlWithDescription: String)
|
||||
|
||||
val teamCityUrl = "http://buildserver.labs.intellij.net"
|
||||
|
||||
// List of commits.
|
||||
class CommitsList(data: JsonElement): ConvertedFromJson {
|
||||
|
||||
val commits: List<Commit>
|
||||
|
||||
init {
|
||||
if (data !is JsonObject) {
|
||||
error("Commits description is expected to be a json object!")
|
||||
}
|
||||
val changesElement = data.getOptionalField("change")
|
||||
commits = changesElement?.let {
|
||||
if (changesElement !is JsonArray) {
|
||||
error("Change field is expected to be an array. Please, check source.")
|
||||
}
|
||||
changesElement.jsonArray.map {
|
||||
with(it as JsonObject) {
|
||||
Commit(elementToString(getRequiredField("version"), "version"),
|
||||
elementToString(getRequiredField("username"), "username"),
|
||||
elementToString(getRequiredField("webUrl"), "webUrl")
|
||||
)
|
||||
}
|
||||
}
|
||||
} ?: listOf<Commit>()
|
||||
}
|
||||
}
|
||||
|
||||
fun buildsUrl(buildLocator: String) =
|
||||
"$teamCityUrl/app/rest/builds/?locator=$buildLocator"
|
||||
|
||||
fun getBuild(buildLocator: String, user: String, password: String) =
|
||||
try {
|
||||
sendGetRequest(buildsUrl(buildLocator), user, password)
|
||||
} catch (t: Throwable) {
|
||||
error("Try to get build! TeamCity is unreachable!")
|
||||
}
|
||||
|
||||
fun sendGetRequest(url: String, username: String? = null, password: String? = null) : String {
|
||||
val connection = URL(url).openConnection() as HttpURLConnection
|
||||
if (username != null && password != null) {
|
||||
val auth = Base64.getEncoder().encode((username + ":" + password).toByteArray()).toString(Charsets.UTF_8)
|
||||
connection.addRequestProperty("Authorization", "Basic $auth")
|
||||
}
|
||||
connection.setRequestProperty("Accept", "application/json");
|
||||
connection.connect()
|
||||
return connection.inputStream.use { it.reader().use { reader -> reader.readText() } }
|
||||
}
|
||||
|
||||
fun getBuildProperty(buildJsonDescription: String, property: String) =
|
||||
with(JsonTreeParser.parse(buildJsonDescription) as JsonObject) {
|
||||
if (getPrimitive("count").int == 0) {
|
||||
error("No build information on TeamCity for $buildJsonDescription!")
|
||||
}
|
||||
(getArray("build").getObject(0).getPrimitive(property) as JsonLiteral).unquoted()
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
fun compileSwift(project: Project, target: KonanTarget, sources: List<String>, options: List<String>,
|
||||
output: Path, fullBitcode: Boolean = false) {
|
||||
val platform = project.platformManager().platform(target)
|
||||
assert(platform.configurables is AppleConfigurables)
|
||||
val configs = platform.configurables as AppleConfigurables
|
||||
val compiler = configs.absoluteTargetToolchain + "/usr/bin/swiftc"
|
||||
|
||||
val swiftTarget = when (target) {
|
||||
KonanTarget.IOS_X64 -> "x86_64-apple-ios" + configs.osVersionMin
|
||||
KonanTarget.IOS_ARM64 -> "arm64_64-apple-ios" + configs.osVersionMin
|
||||
KonanTarget.MACOS_X64 -> "x86_64-apple-macosx" + configs.osVersionMin
|
||||
else -> throw IllegalStateException("Test target $target is not supported")
|
||||
}
|
||||
|
||||
val args = listOf("-sdk", configs.absoluteTargetSysRoot, "-target", swiftTarget) +
|
||||
options + "-o" + output.toString() + sources +
|
||||
if (fullBitcode) listOf("-embed-bitcode", "-Xlinker", "-bitcode_verify") else listOf("-embed-bitcode-marker")
|
||||
|
||||
val (stdOut, stdErr, exitCode) = runProcess(executor = localExecutor(project), executable = compiler, args = args)
|
||||
|
||||
println("""
|
||||
|$compiler finished with exit code: $exitCode
|
||||
|options: ${args.joinToString(separator = " ")}
|
||||
|stdout: $stdOut
|
||||
|stderr: $stdErr
|
||||
""".trimMargin())
|
||||
check(exitCode == 0, { "Compilation failed" })
|
||||
check(output.toFile().exists(), { "Compiler swiftc hasn't produced an output file: $output" })
|
||||
}
|
||||
@@ -27,7 +27,8 @@ buildscript {
|
||||
}
|
||||
}
|
||||
import org.jetbrains.kotlin.konan.target.ClangArgs
|
||||
ext.isEnabled = isMac()
|
||||
import org.jetbrains.kotlin.PlatformInfo
|
||||
ext.isEnabled = PlatformInfo.isMac()
|
||||
|
||||
model {
|
||||
components {
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
import org.jetbrains.kotlin.RegressionsReporter
|
||||
import org.jetbrains.kotlin.RegressionsSummaryReporter
|
||||
import org.jetbrains.kotlin.BuildRegister
|
||||
import org.jetbrains.kotlin.MPPTools
|
||||
|
||||
buildscript {
|
||||
ext.rootBuildDirectory = file('..')
|
||||
|
||||
@@ -42,16 +47,17 @@ defaultTasks 'konanRun'
|
||||
|
||||
// Produce and send slack report.
|
||||
task slackReport(type: RegressionsReporter) {
|
||||
def analyzerBinary = MPPTools.findFile("${analyzerTool}${MPPTools.getNativeProgramExtension()}",
|
||||
"${rootBuildDirectory}/${analyzerToolDirectory}")
|
||||
def teamcityConfig = System.getenv("TEAMCITY_BUILD_PROPERTIES_FILE")
|
||||
if (teamcityConfig) {
|
||||
if (teamcityConfig && analyzerBinary != null) {
|
||||
// Create folder for report (root Kotlin project settings make create report in separate folder).
|
||||
def reportDirectory = new File(outputReport).parentFile
|
||||
mkdir reportDirectory
|
||||
def targetsResults = new File(new File("${rootBuildDirectory}"), "targetsResults").toString()
|
||||
mkdir targetsResults
|
||||
currentBenchmarksReportFile = "${buildDir.absolutePath}/${nativeJson}"
|
||||
analyzer = MPPTools.findFile("${analyzerTool}${MPPTools.getNativeProgramExtension()}",
|
||||
"${rootBuildDirectory}/${analyzerToolDirectory}")
|
||||
analyzer = analyzerBinary
|
||||
htmlReport = outputReport
|
||||
defaultBranch = project.findProperty('kotlin.native.default.branch') ?: "master"
|
||||
def target = System.getProperty("os.name")
|
||||
@@ -138,4 +144,39 @@ task teamCityStat(type:Exec) {
|
||||
} else {
|
||||
println("No analyzer $analyzerTool found in subdirectories of ${rootBuildDirectory}/${analyzerToolDirectory}")
|
||||
}
|
||||
}
|
||||
|
||||
task сinterop {
|
||||
dependsOn 'clean'
|
||||
dependsOn 'сinterop:konanRun'
|
||||
}
|
||||
|
||||
task framework {
|
||||
dependsOn 'clean'
|
||||
dependsOn 'framework:konanRun'
|
||||
}
|
||||
|
||||
task helloworld {
|
||||
dependsOn 'clean'
|
||||
dependsOn 'helloworld:konanRun'
|
||||
}
|
||||
|
||||
task objcinterop {
|
||||
dependsOn 'clean'
|
||||
dependsOn 'objcinterop:konanRun'
|
||||
}
|
||||
|
||||
task ring {
|
||||
dependsOn 'clean'
|
||||
dependsOn 'ring:konanRun'
|
||||
}
|
||||
|
||||
task swiftinterop {
|
||||
dependsOn 'clean'
|
||||
dependsOn 'swiftinterop:konanRun'
|
||||
}
|
||||
|
||||
task videoplayer {
|
||||
dependsOn 'clean'
|
||||
dependsOn 'swiftinterop:konanRun'
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
buildscript {
|
||||
repositories {
|
||||
maven {
|
||||
url 'https://cache-redirector.jetbrains.com/maven-central'
|
||||
}
|
||||
maven {
|
||||
url kotlinCompilerRepo
|
||||
}
|
||||
jcenter()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'kotlin'
|
||||
|
||||
repositories {
|
||||
maven {
|
||||
url kotlinCompilerRepo
|
||||
}
|
||||
maven {
|
||||
url buildKotlinCompilerRepo
|
||||
}
|
||||
jcenter()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly gradleApi()
|
||||
implementation "org.jetbrains.kotlin:kotlin-gradle-plugin"
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-common:$kotlinVersion"
|
||||
compile group: 'com.ullink.slack', name: 'simpleslackapi', version: '1.2.0'
|
||||
}
|
||||
|
||||
sourceSets.main.kotlin.srcDirs = ["src", "$projectDir/../../tools/benchmarks/shared/src"]
|
||||
@@ -1,21 +0,0 @@
|
||||
// Reuse Kotlin version from the root project.
|
||||
File rootProjectGradlePropertiesFile = file("${rootProject.projectDir}/../../gradle.properties")
|
||||
if (!rootProjectGradlePropertiesFile.isFile()) {
|
||||
throw new Exception("File $rootProjectGradlePropertiesFile does not exist or is not a file")
|
||||
}
|
||||
|
||||
Properties rootProjectProperties = new Properties()
|
||||
rootProjectGradlePropertiesFile.withInputStream { inputStream ->
|
||||
rootProjectProperties.load(inputStream)
|
||||
if (!rootProjectProperties.containsKey('kotlinVersion')) {
|
||||
throw new Exception("No 'kotlinVersion' property in $rootProjectGradlePropertiesFile file")
|
||||
}
|
||||
}
|
||||
|
||||
gradle.beforeProject { project ->
|
||||
rootProjectProperties.forEach { String key, value ->
|
||||
if (!project.hasProperty(key))
|
||||
project.ext[key] = value
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
import java.io.FileInputStream
|
||||
import java.io.IOException
|
||||
import java.io.File
|
||||
import java.util.concurrent.TimeUnit
|
||||
import java.net.HttpURLConnection
|
||||
import java.net.URL
|
||||
import java.util.Base64
|
||||
import org.jetbrains.report.json.*
|
||||
|
||||
// Run command line from string.
|
||||
fun Array<String>.runCommand(workingDir: File = File("."),
|
||||
timeoutAmount: Long = 60,
|
||||
timeoutUnit: TimeUnit = TimeUnit.SECONDS): String {
|
||||
return try {
|
||||
ProcessBuilder(*this)
|
||||
.directory(workingDir)
|
||||
.redirectOutput(ProcessBuilder.Redirect.PIPE)
|
||||
.redirectError(ProcessBuilder.Redirect.PIPE)
|
||||
.start().apply {
|
||||
waitFor(timeoutAmount, timeoutUnit)
|
||||
}.inputStream.bufferedReader().readText()
|
||||
} catch (e: IOException) {
|
||||
error("Couldn't run command $this")
|
||||
}
|
||||
}
|
||||
|
||||
fun String.splitCommaSeparatedOption(optionName: String) =
|
||||
split("\\s*,\\s*".toRegex()).map {
|
||||
if (it.isNotEmpty()) listOf(optionName, it) else listOf(null)
|
||||
}.flatten().filterNotNull()
|
||||
|
||||
data class Commit(val revision: String, val developer: String, val webUrlWithDescription: String)
|
||||
|
||||
val teamCityUrl = "http://buildserver.labs.intellij.net"
|
||||
|
||||
// List of commits.
|
||||
class CommitsList(data: JsonElement): ConvertedFromJson {
|
||||
|
||||
val commits: List<Commit>
|
||||
|
||||
init {
|
||||
if (data !is JsonObject) {
|
||||
error("Commits description is expected to be a json object!")
|
||||
}
|
||||
val changesElement = data.getOptionalField("change")
|
||||
commits = changesElement?.let {
|
||||
if (changesElement !is JsonArray) {
|
||||
error("Change field is expected to be an array. Please, check source.")
|
||||
}
|
||||
changesElement.jsonArray.map {
|
||||
with(it as JsonObject) {
|
||||
Commit(elementToString(getRequiredField("version"), "version"),
|
||||
elementToString(getRequiredField("username"), "username"),
|
||||
elementToString(getRequiredField("webUrl"), "webUrl")
|
||||
)
|
||||
}
|
||||
}
|
||||
} ?: listOf<Commit>()
|
||||
}
|
||||
}
|
||||
|
||||
fun buildsUrl(buildLocator: String) =
|
||||
"$teamCityUrl/app/rest/builds/?locator=$buildLocator"
|
||||
|
||||
fun getBuild(buildLocator: String, user: String, password: String) =
|
||||
try {
|
||||
sendGetRequest(buildsUrl(buildLocator), user, password)
|
||||
} catch (t: Throwable) {
|
||||
error("Try to get build! TeamCity is unreachable!")
|
||||
}
|
||||
|
||||
fun sendGetRequest(url: String, username: String? = null, password: String? = null) : String {
|
||||
val connection = URL(url).openConnection() as HttpURLConnection
|
||||
if (username != null && password != null) {
|
||||
val auth = Base64.getEncoder().encode((username + ":" + password).toByteArray()).toString(Charsets.UTF_8)
|
||||
connection.addRequestProperty("Authorization", "Basic $auth")
|
||||
}
|
||||
connection.setRequestProperty("Accept", "application/json");
|
||||
connection.connect()
|
||||
return connection.inputStream.use { it.reader().use { reader -> reader.readText() } }
|
||||
}
|
||||
|
||||
fun getBuildProperty(buildJsonDescription: String, property: String) =
|
||||
with(JsonTreeParser.parse(buildJsonDescription) as JsonObject) {
|
||||
if (getPrimitive("count").int == 0) {
|
||||
error("No build information on TeamCity for $buildJsonDescription!")
|
||||
}
|
||||
(getArray("build").getObject(0).getPrimitive(property) as JsonLiteral).unquoted()
|
||||
}
|
||||
@@ -3,9 +3,8 @@ project.ext {
|
||||
commonSrcDirs = ['../../tools/benchmarks/shared/src', 'src/main/kotlin', '../shared/src/main/kotlin', '../../tools/kliopt']
|
||||
jvmSrcDirs = ['src/main/kotlin-jvm', '../shared/src/main/kotlin-jvm']
|
||||
nativeSrcDirs = ['src/main/kotlin-native', '../shared/src/main/kotlin-native']
|
||||
|
||||
}
|
||||
apply from: rootProject.file("${rootProject.rootDir}/gradle/benchmark.gradle")
|
||||
apply from: rootProject.file("${rootProject.rootDir}/performance/gradle/benchmark.gradle")
|
||||
kotlin.targets.native.compilations.main.cinterops {
|
||||
macros
|
||||
struct
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
import org.jetbrains.kotlin.MPPTools
|
||||
import org.jetbrains.kotlin.PlatformInfo
|
||||
import org.jetbrains.kotlin.RunJvmTask
|
||||
|
||||
buildscript {
|
||||
ext.rootBuildDirectory = file('../..')
|
||||
|
||||
@@ -64,7 +68,7 @@ kotlin {
|
||||
MPPTools.addTimeListener(project)
|
||||
|
||||
task konanRun {
|
||||
if (MPPTools.isMacos()) {
|
||||
if (PlatformInfo.isMac()) {
|
||||
dependsOn 'build'
|
||||
}
|
||||
}
|
||||
@@ -77,7 +81,7 @@ task jvmRun(type: RunJvmTask) {
|
||||
|
||||
task konanJsonReport {
|
||||
doLast {
|
||||
if (MPPTools.isMacos()) {
|
||||
if (PlatformInfo.isMac()) {
|
||||
def applicationName = "FrameworkBenchmarksAnalyzer"
|
||||
def frameworkPath = kotlin.macosX64("macos").binaries.
|
||||
getFramework(frameworkName, kotlin.macosX64("macos").binaries.RELEASE).outputFile.absolutePath
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
import org.jetbrains.kotlin.MPPTools
|
||||
import org.jetbrains.kotlin.RunJvmTask
|
||||
|
||||
apply plugin: 'kotlin-multiplatform'
|
||||
|
||||
repositories {
|
||||
@@ -54,6 +57,7 @@ kotlin {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
jvm() {
|
||||
compilations.all {
|
||||
tasks[compileKotlinTaskName].kotlinOptions {
|
||||
@@ -68,23 +72,20 @@ kotlin {
|
||||
compilations.main.extraOpts = (project.hasProperty('compilerArgs') ? compilerArgs.split() : []) + '-opt'
|
||||
binaries {
|
||||
executable('benchmark', [RELEASE]) {
|
||||
if (org.gradle.internal.os.OperatingSystem.current().isWindows()) {
|
||||
linkerOpts = ["-L${getMingwPath()}/lib".toString()]
|
||||
if (project.hasProperty("linkerOpts")) {
|
||||
linkerOpts = project.ext.linkerOpts
|
||||
}
|
||||
if (org.gradle.internal.os.OperatingSystem.current().isWindows()) {
|
||||
linkerOpts += ["-L${getMingwPath()}/lib".toString()]
|
||||
}
|
||||
runTask.args("-w", "$nativeWarmup", "-r", "$attempts", "-o", "${buildDir.absolutePath}/${nativeBenchResults}", "-p", "${project.ext.applicationName}::")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MPPTools.addTimeListener(project)
|
||||
|
||||
MPPTools.createRunTask(project, 'konanRun', kotlin.targets.native) {
|
||||
workingDir = project.provider {
|
||||
kotlin.targets.native.binaries.getExecutable("benchmark", buildType).outputDirectory
|
||||
}
|
||||
depends("build")
|
||||
args("-w", "$nativeWarmup", "-r", "$attempts", "-o", "${buildDir.absolutePath}/${nativeBenchResults}", "-p", "${project.ext.applicationName}::")
|
||||
}
|
||||
MPPTools.createRunTask(project, 'konanRun', kotlin.targets.native.binaries.getExecutable("benchmark", "RELEASE").runTask)
|
||||
|
||||
task jvmRun(type: RunJvmTask) {
|
||||
dependsOn 'build'
|
||||
@@ -129,7 +130,6 @@ task jvmJsonReport {
|
||||
}
|
||||
|
||||
jvmRun.finalizedBy jvmJsonReport
|
||||
konanRun.finalizedBy konanJsonReport
|
||||
|
||||
private def getCommonProperties() {
|
||||
return ['cpu': System.getProperty("os.arch"),
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import org.jetbrains.kotlin.MPPTools
|
||||
|
||||
def exitCodes = [:]
|
||||
|
||||
MPPTools.addTimeListener(project)
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import org.jetbrains.kotlin.MPPTools
|
||||
|
||||
def dist = findProperty('org.jetbrains.kotlin.native.home') ?: 'dist'
|
||||
dist = (new File(dist)).isAbsolute() ? dist : "${project.getProjectDir()}/$dist"
|
||||
def toolExtension = System.getProperty("os.name").startsWith('Windows') ? ".bat" : ""
|
||||
@@ -7,4 +9,4 @@ project.ext {
|
||||
buildSteps = ["runKonanc": ["$dist/bin/konanc$toolExtension", "${project.getProjectDir()}/src/main/kotlin/main.kt", "-o",
|
||||
"${buildDir.absolutePath}/program${MPPTools.getNativeProgramExtension()}"]]
|
||||
}
|
||||
apply from: rootProject.file("${rootProject.rootDir}/gradle/compileBenchmark.gradle")
|
||||
apply from: rootProject.file("${rootProject.rootDir}/performance/gradle/compileBenchmark.gradle")
|
||||
@@ -0,0 +1,29 @@
|
||||
import org.jetbrains.kotlin.konan.target.HostManager
|
||||
|
||||
project.ext {
|
||||
applicationName = 'ObjCInterop'
|
||||
commonSrcDirs = ['../../tools/benchmarks/shared/src', 'src/main/kotlin', '../shared/src/main/kotlin', '../../tools/kliopt']
|
||||
jvmSrcDirs = ['src/main/kotlin-jvm', '../shared/src/main/kotlin-jvm']
|
||||
nativeSrcDirs = ['src/main/kotlin-native', '../shared/src/main/kotlin-native']
|
||||
linkerOpts = ["-L$buildDir".toString(), "-lcomplexnumbers".toString()]
|
||||
}
|
||||
|
||||
task compileLibrary {
|
||||
doFirst {
|
||||
mkdir buildDir.absolutePath
|
||||
execKonanClang(HostManager.host) {
|
||||
args "$projectDir/src/nativeInterop/cinterop/complexNumbers.m"
|
||||
args "-lobjc", '-fobjc-arc'
|
||||
args '-fPIC', '-shared', '-o', "$buildDir/libcomplexnumbers.dylib"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
apply from: rootProject.file("${rootProject.rootDir}/performance/gradle/benchmark.gradle")
|
||||
kotlin.targets.native.compilations.main.cinterops {
|
||||
classes {
|
||||
headers "$projectDir/src/nativeInterop/cinterop/complexNumbers.h"
|
||||
}
|
||||
}
|
||||
|
||||
kotlin.targets.native.binaries.getExecutable("benchmark", "RELEASE").linkTask.dependsOn 'compileLibrary'
|
||||
@@ -0,0 +1 @@
|
||||
org.jetbrains.kotlin.native.home=../../dist
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the LICENSE file.
|
||||
*/
|
||||
package org.jetbrains.complexNumbers
|
||||
|
||||
actual class ComplexNumber() {}
|
||||
|
||||
actual class ComplexNumbersBenchmark actual constructor() {
|
||||
actual fun generateNumbersSequence(): List<ComplexNumber> {
|
||||
error("Benchmark generateNumbersSequence is unsupported on JVM!")
|
||||
}
|
||||
|
||||
actual fun sumComplex() {
|
||||
error("Benchmark sumComplex is unsupported on JVM!")
|
||||
}
|
||||
|
||||
actual fun subComplex() {
|
||||
error("Benchmark subComplex is unsupported on JVM!")
|
||||
}
|
||||
actual fun classInheritance() {
|
||||
error("Benchmark classInheritance is unsupported on JVM!")
|
||||
}
|
||||
actual fun categoryMethods() {
|
||||
error("Benchmark categoryMethods is unsupported on JVM!")
|
||||
}
|
||||
actual fun stringToObjC() {
|
||||
error("Benchmark stringToObjC is unsupported on JVM!")
|
||||
}
|
||||
actual fun stringFromObjC() {
|
||||
error("Benchmark stringToObjC is unsupported on JVM!")
|
||||
}
|
||||
actual fun fft() {
|
||||
error("Benchmark fft is unsupported on JVM!")
|
||||
}
|
||||
actual fun invertFft() {
|
||||
error("Benchmark invertFft is unsupported on JVM!")
|
||||
}
|
||||
}
|
||||
+134
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.complexNumbers
|
||||
import kotlinx.cinterop.*
|
||||
import platform.posix.*
|
||||
import kotlin.math.sqrt
|
||||
import kotlin.math.PI
|
||||
import kotlin.math.cos
|
||||
import kotlin.math.sin
|
||||
import kotlin.random.Random
|
||||
import platform.Foundation.*
|
||||
import platform.darwin.*
|
||||
|
||||
actual typealias ComplexNumber = Complex
|
||||
|
||||
actual class ComplexNumbersBenchmark actual constructor() {
|
||||
val complexNumbersSequence = generateNumbersSequence()
|
||||
|
||||
fun randomNumber() = Random.nextDouble(0.0, benchmarkSize.toDouble())
|
||||
|
||||
actual fun generateNumbersSequence(): List<Complex> {
|
||||
val result = mutableListOf<Complex>()
|
||||
for (i in 1..benchmarkSize) {
|
||||
result.add(Complex(randomNumber(), randomNumber()))
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
actual fun sumComplex() {
|
||||
complexNumbersSequence.map { it.add(it) }.reduce { acc, it -> acc.add(it) }
|
||||
}
|
||||
|
||||
actual fun subComplex() {
|
||||
complexNumbersSequence.map { it.sub(it) }.reduce { acc, it -> acc.sub(it) }
|
||||
}
|
||||
|
||||
actual fun classInheritance() {
|
||||
class InvertedNumber(val value: Double) : CustomNumberProtocol, NSObject() {
|
||||
override fun add(other: CustomNumberProtocol) : CustomNumberProtocol =
|
||||
if (other is InvertedNumber)
|
||||
InvertedNumber(-value + sqrt(other.value))
|
||||
else
|
||||
error("Expected object of InvertedNumber class")
|
||||
|
||||
|
||||
override fun sub(other: CustomNumberProtocol) : CustomNumberProtocol =
|
||||
if (other is InvertedNumber)
|
||||
InvertedNumber(-value - sqrt(other.value))
|
||||
else
|
||||
error("Expected object of InvertedNumber class")
|
||||
}
|
||||
|
||||
val result = InvertedNumber(0.0)
|
||||
|
||||
for (i in 1..benchmarkSize) {
|
||||
result.add(InvertedNumber(randomNumber()))
|
||||
result.sub(InvertedNumber(randomNumber()))
|
||||
}
|
||||
}
|
||||
|
||||
actual fun categoryMethods() {
|
||||
complexNumbersSequence.map { it.mul(it) }.reduce { acc, it -> acc.mul(it) }
|
||||
complexNumbersSequence.map { it.div(it) }.reduce { acc, it -> acc.mul(it) }
|
||||
}
|
||||
|
||||
actual fun stringToObjC() {
|
||||
complexNumbersSequence.forEach {
|
||||
it.setFormat("%.1lf|%.1lf")
|
||||
}
|
||||
}
|
||||
|
||||
actual fun stringFromObjC() {
|
||||
complexNumbersSequence.forEach {
|
||||
it.description()?.split(" ")
|
||||
}
|
||||
}
|
||||
|
||||
private fun revert(number: Int, lg: Int): Int {
|
||||
var result = 0
|
||||
for (i in 0 until lg) {
|
||||
if (number and (1 shl i) != 0) {
|
||||
result = result or 1 shl (lg - i - 1)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
inline private fun fftRoutine(invert:Boolean = false): Array<Complex> {
|
||||
var lg = 0
|
||||
while ((1 shl lg) < complexNumbersSequence.size) {
|
||||
lg++
|
||||
}
|
||||
val sequence = complexNumbersSequence.toTypedArray()
|
||||
|
||||
sequence.forEachIndexed { index, number ->
|
||||
if (index < revert(index, lg) && revert(index, lg) < complexNumbersSequence.size) {
|
||||
sequence[index] = sequence[revert(index, lg)].also { sequence[revert(index, lg)] = sequence[index] }
|
||||
}
|
||||
}
|
||||
|
||||
var length = 2
|
||||
while (length < complexNumbersSequence.size) {
|
||||
val angle = 2 * PI / length * if (invert) -1 else 1
|
||||
val base = Complex(cos(angle), sin(angle))
|
||||
for (i in 0 until complexNumbersSequence.size / 2 step length) {
|
||||
var value = Complex(1.0, 1.0)
|
||||
for (j in 0 until length/2) {
|
||||
val first = sequence[i + j]
|
||||
val second = sequence[i + j + length/2].mul(value)
|
||||
sequence[i + j] = (first.add(second) as Complex)!!
|
||||
sequence[i + j + length/2] = (first.sub(second) as Complex)!!
|
||||
value = value.mul(base)!!
|
||||
}
|
||||
}
|
||||
length = length shl 1
|
||||
}
|
||||
return sequence
|
||||
}
|
||||
|
||||
actual fun fft() {
|
||||
fftRoutine()
|
||||
}
|
||||
|
||||
actual fun invertFft() {
|
||||
val sequence = fftRoutine(true)
|
||||
|
||||
sequence.forEachIndexed { index, number ->
|
||||
sequence[index] = number.div(Complex(sequence.size.toDouble(), 0.0)) ?: Complex(0.0, 0.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
|
||||
import org.jetbrains.benchmarksLauncher.*
|
||||
import org.jetbrains.complexNumbers.*
|
||||
import org.jetbrains.kliopt.*
|
||||
|
||||
class ObjCInteropLauncher(numWarmIterations: Int, numberOfAttempts: Int, prefix: String): Launcher(numWarmIterations, numberOfAttempts, prefix) {
|
||||
val complexNumbersBecnhmark = ComplexNumbersBenchmark()
|
||||
override val benchmarks = BenchmarksCollection(
|
||||
mutableMapOf(
|
||||
"generateNumbersSequence" to complexNumbersBecnhmark::generateNumbersSequence,
|
||||
"sumComplex" to complexNumbersBecnhmark::sumComplex,
|
||||
"subComplex" to complexNumbersBecnhmark::subComplex,
|
||||
"classInheritance" to complexNumbersBecnhmark::classInheritance,
|
||||
"categoryMethods" to complexNumbersBecnhmark::categoryMethods,
|
||||
"stringToObjC" to complexNumbersBecnhmark::stringToObjC,
|
||||
"stringFromObjC" to complexNumbersBecnhmark::stringFromObjC,
|
||||
"fft" to complexNumbersBecnhmark::fft,
|
||||
"invertFft" to complexNumbersBecnhmark::invertFft
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
BenchmarksRunner.runBenchmarks(args, { parser: ArgParser ->
|
||||
ObjCInteropLauncher(parser.get<Int>("warmup")!!, parser.get<Int>("repeat")!!, parser.get<String>("prefix")!!).launch(parser.getAll<String>("filter"))
|
||||
})
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.complexNumbers
|
||||
|
||||
const val benchmarkSize = 10000
|
||||
|
||||
expect class ComplexNumber
|
||||
|
||||
expect class ComplexNumbersBenchmark() {
|
||||
fun generateNumbersSequence(): List<ComplexNumber>
|
||||
fun sumComplex()
|
||||
fun subComplex()
|
||||
fun classInheritance()
|
||||
fun categoryMethods()
|
||||
fun stringToObjC()
|
||||
fun stringFromObjC()
|
||||
fun fft()
|
||||
fun invertFft()
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
package = org.jetbrains.complexNumbers
|
||||
language = Objective-C
|
||||
@@ -0,0 +1,22 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@protocol CustomNumber
|
||||
@required
|
||||
- (id<CustomNumber> _Nonnull)add: (id<CustomNumber> _Nonnull)other;
|
||||
- (id<CustomNumber> _Nonnull)sub: (id<CustomNumber> _Nonnull)other;
|
||||
@end
|
||||
|
||||
@interface Complex : NSObject<CustomNumber>
|
||||
|
||||
@property (nonatomic, readonly) double re;
|
||||
@property (nonatomic, readonly) double im;
|
||||
@property (nonatomic, readwrite) NSString *format;
|
||||
|
||||
- (id)initWithRe: (double)re andIm: (double)im;
|
||||
+ (Complex *)complexWithRe: (double)re im: (double)im;
|
||||
@end
|
||||
|
||||
@interface Complex (CategorizedComplex)
|
||||
- (Complex * _Nonnull)mul: (Complex * _Nonnull)other;
|
||||
- (Complex * _Nonnull)div: (Complex * _Nonnull)other;
|
||||
@end
|
||||
@@ -0,0 +1,62 @@
|
||||
#import <stdio.h>
|
||||
#import "complexNumbers.h"
|
||||
|
||||
@implementation Complex
|
||||
{
|
||||
double re;
|
||||
double im;
|
||||
NSString *format;
|
||||
}
|
||||
- (id)init {
|
||||
return [self initWithRe: 0.0 andIm: 0.0];
|
||||
}
|
||||
|
||||
- (id)initWithRe: (double)_re andIm: (double)_im {
|
||||
if (self = [super init]) {
|
||||
re = _re;
|
||||
im = _im;
|
||||
format = @"re: %.1lf im: %.1lf";
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (Complex *)complexWithRe: (double)re im: (double)im {
|
||||
return [[Complex alloc] initWithRe: re andIm: im];
|
||||
}
|
||||
- (id<CustomNumber> _Nonnull)add: (id<CustomNumber> _Nonnull)other {
|
||||
if ([self isKindOfClass:[Complex class]]) {
|
||||
Complex * otherComplex = (Complex *)other;
|
||||
return [[Complex alloc] initWithRe: re + otherComplex->re andIm: im + otherComplex->im];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
- (id<CustomNumber> _Nonnull)sub: (id<CustomNumber> _Nonnull)other {
|
||||
if ([self isKindOfClass:[Complex class]]) {
|
||||
Complex * otherComplex = (Complex *)other;
|
||||
return [[Complex alloc] initWithRe: re - otherComplex->re andIm: im - otherComplex->im];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
- (NSString *)description {
|
||||
return [NSString stringWithFormat: format, re, im];
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation Complex (CategorizedComplex)
|
||||
- (Complex * _Nonnull)mul: (Complex * _Nonnull)other {
|
||||
return [Complex complexWithRe: re * other.re - im * other.im im: re * other.im + im * other.re];
|
||||
}
|
||||
- (Complex * _Nonnull)div: (Complex * _Nonnull)other {
|
||||
double retRe;
|
||||
double retIm;
|
||||
double denominator;
|
||||
denominator = other.re * other.re + other.im * other.im;
|
||||
if (!denominator)
|
||||
return nil;
|
||||
retRe = (re * other.re + im * other.im) / denominator;
|
||||
retIm = (im * other.re - re * other.im) / denominator;
|
||||
return [Complex complexWithRe: retRe im: retIm];
|
||||
}
|
||||
@end
|
||||
@@ -5,4 +5,4 @@ project.ext {
|
||||
nativeSrcDirs = ['src/main/kotlin-native', '../shared/src/main/kotlin-native']
|
||||
|
||||
}
|
||||
apply from: rootProject.file("${rootProject.rootDir}/gradle/benchmark.gradle")
|
||||
apply from: rootProject.file("${rootProject.rootDir}/performance/gradle/benchmark.gradle")
|
||||
@@ -1,5 +0,0 @@
|
||||
include ':ring'
|
||||
include ':cinterop'
|
||||
include ':helloworld'
|
||||
include ':videoplayer'
|
||||
include ':framework'
|
||||
@@ -19,12 +19,20 @@ package org.jetbrains.benchmarksLauncher
|
||||
import kotlin.math.sqrt
|
||||
import org.jetbrains.report.BenchmarkResult
|
||||
import org.jetbrains.kliopt.*
|
||||
import kotlin.reflect.KFunction0
|
||||
|
||||
abstract class Launcher(val numWarmIterations: Int, val numberOfAttempts: Int, val prefix: String = "") {
|
||||
class Results(val mean: Double, val variance: Double)
|
||||
|
||||
abstract val benchmarks: BenchmarksCollection
|
||||
|
||||
fun add(name: String, benchmark:() -> Any?) {
|
||||
fun benchmarkWrapper() {
|
||||
benchmark()
|
||||
}
|
||||
benchmarks[name] = ::benchmarkWrapper
|
||||
}
|
||||
|
||||
fun launch(filters: Collection<String>? = null,
|
||||
filterRegexes: Collection<String>? = null): List<BenchmarkResult> {
|
||||
val regexes = filterRegexes?.map { it.toRegex() } ?: listOf()
|
||||
|
||||
@@ -0,0 +1,153 @@
|
||||
import org.jetbrains.kotlin.MPPTools
|
||||
import org.jetbrains.kotlin.PlatformInfo
|
||||
import org.jetbrains.kotlin.RunJvmTask
|
||||
import org.jetbrains.kotlin.konan.target.HostManager
|
||||
import org.jetbrains.kotlin.UtilsKt
|
||||
import java.nio.file.Paths
|
||||
|
||||
buildscript {
|
||||
ext.rootBuildDirectory = file('../..')
|
||||
|
||||
apply from: "$rootBuildDirectory/gradle/loadRootProperties.gradle"
|
||||
apply from: "$rootBuildDirectory/gradle/kotlinGradlePlugin.gradle"
|
||||
|
||||
repositories {
|
||||
maven {
|
||||
url 'https://cache-redirector.jetbrains.com/jcenter'
|
||||
}
|
||||
maven {
|
||||
url kotlinCompilerRepo
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'kotlin-multiplatform'
|
||||
|
||||
repositories {
|
||||
maven {
|
||||
url 'https://cache-redirector.jetbrains.com/jcenter'
|
||||
}
|
||||
maven {
|
||||
url kotlinCompilerRepo
|
||||
}
|
||||
maven {
|
||||
url buildKotlinCompilerRepo
|
||||
}
|
||||
}
|
||||
|
||||
def toolsPath = '../../tools'
|
||||
def frameworkName = 'CityMap'
|
||||
|
||||
kotlin {
|
||||
sourceSets {
|
||||
commonMain {
|
||||
dependencies {
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-common:$kotlinVersion"
|
||||
}
|
||||
kotlin.srcDir "src"
|
||||
kotlin.srcDir "../shared/src/main/kotlin"
|
||||
kotlin.srcDir "$toolsPath/kliopt"
|
||||
kotlin.srcDir "$toolsPath/benchmarks/shared/src"
|
||||
}
|
||||
macosMain {
|
||||
dependsOn commonMain
|
||||
kotlin.srcDir "../shared/src/main/kotlin-native"
|
||||
}
|
||||
}
|
||||
|
||||
macosX64("macos") {
|
||||
compilations.main.extraOpts = (project.hasProperty('compilerArgs') ? compilerArgs.split() : []) + '-opt'
|
||||
binaries {
|
||||
framework(frameworkName, [RELEASE])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MPPTools.addTimeListener(project)
|
||||
|
||||
build.finalizedBy 'buildSwift'
|
||||
|
||||
defaultTasks 'konanRun'
|
||||
|
||||
def applicationName = "swiftInterop"
|
||||
def swiftExecutable = Paths.get(buildDir.absolutePath, applicationName)
|
||||
|
||||
if (PlatformInfo.isAppleTarget(HostManager.host)) {
|
||||
MPPTools.createBenchmarksRunTask(project, 'konanRun') {
|
||||
workingDir = project.provider { buildDir }
|
||||
executable = swiftExecutable
|
||||
depends("build")
|
||||
args("-w", "$nativeWarmup", "-r", "$attempts", "-o", "${buildDir.absolutePath}/${nativeBenchResults}", "-p", "${applicationName}::")
|
||||
}
|
||||
}
|
||||
|
||||
def framework = null
|
||||
if (PlatformInfo.isMac()) {
|
||||
framework = kotlin.targets.macos.binaries.getFramework(frameworkName, 'RELEASE')
|
||||
} else {
|
||||
framework = kotlin.targets.ios.binaries.getFramework(frameworkName, 'RELEASE')
|
||||
}
|
||||
|
||||
task buildSwift {
|
||||
doLast {
|
||||
def frameworkParentDirPath = framework.outputDirectory
|
||||
def sources = ["$projectDir/swiftSrc/benchmarks.swift".toString(), "$projectDir/swiftSrc/main.swift".toString()]
|
||||
def options = ['-g', '-Xlinker', '-rpath', '-Xlinker', frameworkParentDirPath, '-F', frameworkParentDirPath]
|
||||
UtilsKt.compileSwift(project, HostManager.host, sources, options, swiftExecutable, false)
|
||||
}
|
||||
}
|
||||
|
||||
task jvmRun(type: RunJvmTask) {
|
||||
doLast {
|
||||
println("JVM run is unsupported")
|
||||
}
|
||||
}
|
||||
|
||||
private def getCommonProperties() {
|
||||
return ['cpu': System.getProperty("os.arch"),
|
||||
'os': System.getProperty("os.name"), // OperatingSystem.current().getName()
|
||||
'jdkVersion': System.getProperty("java.version"), // org.gradle.internal.jvm.Jvm.current().javaVersion
|
||||
'jdkVendor': System.getProperty("java.vendor"),
|
||||
'kotlinVersion': "${kotlinVersion}".toString()]
|
||||
}
|
||||
|
||||
task konanJsonReport {
|
||||
doLast {
|
||||
if (PlatformInfo.isAppleTarget(HostManager.host)) {
|
||||
def targetExtension = ""
|
||||
if (PlatformInfo.isMac()) {
|
||||
targetExtension = "Macos"
|
||||
} else {
|
||||
targetExtension = "Ios"
|
||||
}
|
||||
|
||||
def frameworkPath = framework.outputFile.absolutePath
|
||||
def nativeFramework = new File("$frameworkPath/$frameworkName").canonicalPath
|
||||
def nativeCompileTime = MPPTools.getNativeCompileTime(applicationName, ["compileKotlin${targetExtension}".toString(),
|
||||
"link${frameworkName}ReleaseFramework${targetExtension}".toString()])
|
||||
|
||||
String benchContents = new File("${buildDir.absolutePath}/${nativeBenchResults}").text
|
||||
def properties = getCommonProperties() + ['type' : 'native',
|
||||
'compilerVersion': "${konanVersion}".toString(),
|
||||
'flags' : kotlin.targets.macos.compilations.main.extraOpts.collect{ "\"$it\"" },
|
||||
'benchmarks' : benchContents,
|
||||
'compileTime' : [nativeCompileTime],
|
||||
'codeSize' : MPPTools.getCodeSizeBenchmark(applicationName, nativeFramework)]
|
||||
def output = MPPTools.createJsonReport(properties)
|
||||
new File("${buildDir.absolutePath}/${nativeJson}").write(output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
task jvmJsonReport {
|
||||
doLast {
|
||||
println("JVM run is unsupported")
|
||||
}
|
||||
}
|
||||
|
||||
konanRun.finalizedBy 'konanJsonReport'
|
||||
jvmRun.finalizedBy 'jvmJsonReport'
|
||||
@@ -0,0 +1 @@
|
||||
org.jetbrains.kotlin.native.home=../../dist
|
||||
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
import org.jetbrains.benchmarksLauncher.*
|
||||
import org.jetbrains.kliopt.*
|
||||
|
||||
class SwiftLauncher(numWarmIterations: Int, numberOfAttempts: Int, prefix: String): Launcher(numWarmIterations, numberOfAttempts, prefix) {
|
||||
override val benchmarks = BenchmarksCollection(
|
||||
mutableMapOf(
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.model
|
||||
|
||||
import org.jetbrains.multigraph.*
|
||||
import kotlin.comparisons.compareBy
|
||||
|
||||
enum class Transport { CAR, UNDERGROUND, BUS, TROLLEYBUS, TRAM, TAXI, FOOT }
|
||||
enum class Interest { SIGHT, CULTURE, PARK, ENTERTAINMENT }
|
||||
|
||||
class PlaceAbsenceException(message: String): Exception(message) {}
|
||||
|
||||
data class RouteCost(val moneyCost: Double, val timeCost: Double, val interests: Set<Interest>, val transport: Set<Transport>): Cost {
|
||||
private val comparator = compareBy<RouteCost>({ it.moneyCost }, { it.timeCost }, { it.interests.size }, { it.transport.size })
|
||||
|
||||
override operator fun plus(other: Cost) =
|
||||
if (other is RouteCost) {
|
||||
RouteCost(moneyCost + other.moneyCost, timeCost + other.timeCost,
|
||||
interests.union(other.interests), transport.union(other.transport))
|
||||
} else {
|
||||
error("Expected type is RouteCost")
|
||||
}
|
||||
|
||||
override operator fun minus(other: Cost) =
|
||||
if (other is RouteCost) {
|
||||
RouteCost(if (moneyCost > other.moneyCost) moneyCost - other.moneyCost else 0.0,
|
||||
if (timeCost > other.timeCost) timeCost - other.timeCost else 0.0,
|
||||
interests.subtract(other.interests), transport.subtract(other.transport))
|
||||
} else {
|
||||
error("Expected type is RouteCost")
|
||||
}
|
||||
|
||||
override operator fun compareTo(other: Cost) =
|
||||
if (other is RouteCost) {
|
||||
comparator.compare(this, other)
|
||||
} else {
|
||||
error("Expected type is RouteCost")
|
||||
}
|
||||
}
|
||||
|
||||
internal var placeCounter = 0u
|
||||
|
||||
data class Place(val geoCoordinateX: Double, val geoCoordinateY: Double, val name: String, val interestCategory: Interest) {
|
||||
private val comparator = compareBy<Place>({ it.geoCoordinateX }, { it.geoCoordinateY })
|
||||
|
||||
val id: UInt
|
||||
init {
|
||||
id = placeCounter
|
||||
placeCounter++
|
||||
}
|
||||
|
||||
val fullDescription: String
|
||||
get() = "Place $name($geoCoordinateX;$geoCoordinateY)"
|
||||
|
||||
fun compareTo(other: Place) =
|
||||
comparator.compare(this, other)
|
||||
}
|
||||
|
||||
data class Path(val from: Place, val to: Place, val cost: RouteCost)
|
||||
|
||||
class CityMap {
|
||||
data class RouteId(val id: UInt, val from: UInt, val to: UInt)
|
||||
private val graph = Multigraph<Place>()
|
||||
|
||||
val allPlaces: Set<Place>
|
||||
get() = graph.allVertexes
|
||||
val allRoutes: List<RouteId>
|
||||
get() {
|
||||
val edges = graph.allEdges
|
||||
val result = mutableListOf<RouteId>()
|
||||
edges.forEach {
|
||||
result.add(RouteId(it, graph.getFrom(it).id, graph.getTo(it).id))
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
fun addRoute(from: Place, to: Place, cost: RouteCost): UInt {
|
||||
return graph.addEdge(from, to, cost)
|
||||
}
|
||||
|
||||
fun getPlaceById(id: UInt): Place {
|
||||
graph.allVertexes.forEach {
|
||||
if (it.id == id) {
|
||||
return it
|
||||
}
|
||||
}
|
||||
throw PlaceAbsenceException("Place with id $id wasn't found.")
|
||||
}
|
||||
|
||||
fun removePlaceById(id: UInt) {
|
||||
graph.allVertexes.forEach {
|
||||
if (it.id == id) {
|
||||
graph.removeVertex(it)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun removeRouteById(id: UInt) {
|
||||
graph.removeEdge(id)
|
||||
}
|
||||
|
||||
fun getRoutes(start: Place, finish: Place, limits: RouteCost): List<List<Path>> {
|
||||
val result = graph.searchRoutesWithLimits(start, finish, limits)
|
||||
return result.map {
|
||||
it.map {
|
||||
Path(graph.getFrom(it), graph.getTo(it), graph.getCost(it) as RouteCost)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getRouteById(id: UInt) =
|
||||
graph.getEdgeById(id)
|
||||
|
||||
fun getAllStraightRoutesFrom(place: Place) =
|
||||
graph.getEdgesFrom(place).map { Path(graph.getFrom(it.id), graph.getTo(it.id), graph.getCost(it.id) as RouteCost) }
|
||||
|
||||
fun isEmpty() = graph.isEmpty()
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.multigraph
|
||||
|
||||
import kotlin.math.pow
|
||||
|
||||
interface Cost {
|
||||
operator fun plus(other: Cost): Cost
|
||||
operator fun minus(other: Cost): Cost
|
||||
override operator fun equals(other: Any?): Boolean
|
||||
operator fun compareTo(other: Cost): Int
|
||||
}
|
||||
|
||||
data class Edge<T>(val id: UInt, val from: T, val to: T, val cost: Cost) {
|
||||
override operator fun equals(other: Any?): Boolean {
|
||||
return if (other is Edge<*>) (from == other.from && to == other.to && cost == other.cost) else false
|
||||
}
|
||||
|
||||
override fun hashCode(): Int =
|
||||
from.hashCode() * 31.0.pow(2.0).toInt() + to.hashCode() * 31 + cost.hashCode()
|
||||
}
|
||||
|
||||
class EdgeAbsenceMultigraphException(message: String): Exception(message) {}
|
||||
class VertexAbsenceMultigraphException(message: String): Exception(message) {}
|
||||
|
||||
class Multigraph<T>() {
|
||||
private var edges = mutableMapOf<T, MutableList<Edge<T>>>()
|
||||
private var idCounter = 0u
|
||||
|
||||
val allVertexes: Set<T>
|
||||
get() {
|
||||
val outerVertexes = edges.keys
|
||||
val innerVertexes = edges.map { (_, values) ->
|
||||
values.map { it.to }.filter { it !in outerVertexes }
|
||||
}.flatten()
|
||||
return outerVertexes.union(innerVertexes)
|
||||
}
|
||||
|
||||
val allEdges: List<UInt>
|
||||
get() = edges.values.flatten().map { it.id }
|
||||
|
||||
fun getEdgeById(id: UInt): Edge<T> {
|
||||
edges.forEach { (_, value) ->
|
||||
value.forEach {
|
||||
if (it.id == id)
|
||||
return it
|
||||
}
|
||||
}
|
||||
throw EdgeAbsenceMultigraphException("Edge with id $id wasn't found.")
|
||||
}
|
||||
|
||||
fun copyMultigraph(): Multigraph<T> {
|
||||
val newInstance = Multigraph<T>()
|
||||
edges.forEach { (vertex, edges) ->
|
||||
edges.forEach { edge ->
|
||||
newInstance.addEdge(vertex, edge.to, edge.cost)
|
||||
}
|
||||
}
|
||||
return newInstance
|
||||
}
|
||||
|
||||
fun addEdge(from: T, to: T, cost: Cost): UInt {
|
||||
val edge = Edge(idCounter, from, to, cost)
|
||||
edges.getOrPut(from) { mutableListOf() }.add(edge)
|
||||
idCounter++
|
||||
return edge.id
|
||||
}
|
||||
|
||||
fun removeEdge(id: UInt) {
|
||||
try {
|
||||
val edge = getEdgeById(id)
|
||||
edges[edge.from]?.remove(edge)
|
||||
} catch (exception: EdgeAbsenceMultigraphException) {
|
||||
println("WARNING: no edge with id $id was found.")
|
||||
}
|
||||
}
|
||||
|
||||
fun removeVertex(vertex: T) {
|
||||
edges.remove(vertex)
|
||||
val edgesToRemove = edges.map { (_, values) ->
|
||||
values.filter {
|
||||
it.to == vertex
|
||||
}
|
||||
}.flatten()
|
||||
edgesToRemove.forEach {
|
||||
removeEdge(it.id)
|
||||
}
|
||||
}
|
||||
|
||||
fun checkVertexExistance(vertex: T): Boolean {
|
||||
return vertex in allVertexes
|
||||
}
|
||||
|
||||
fun getTo(edgeId: UInt) =
|
||||
getEdgeById(edgeId).to
|
||||
|
||||
fun getFrom(edgeId: UInt) =
|
||||
getEdgeById(edgeId).from
|
||||
|
||||
fun getCost(edgeId: UInt) =
|
||||
getEdgeById(edgeId).cost
|
||||
|
||||
fun getEdgesFrom(vertex: T) =
|
||||
edges[vertex] ?: listOf<Edge<T>>()
|
||||
|
||||
fun isEmpty() = edges.isEmpty()
|
||||
|
||||
fun searchRoutesWithLimits(start: T, finish: T, limits: Cost): List<List<UInt>> {
|
||||
data class WaveStep(val costs: MutableList<Cost> = mutableListOf(),
|
||||
val routes: MutableList<MutableList<UInt>> = mutableListOf(),
|
||||
val vertexes: MutableList<MutableList<T>> = mutableListOf())
|
||||
|
||||
val currentStepsState = mutableMapOf<T, WaveStep>()
|
||||
var oldFront = mutableSetOf<T>(start)
|
||||
val newFront = mutableSetOf<T>()
|
||||
|
||||
if (!checkVertexExistance(start)) {
|
||||
throw(VertexAbsenceMultigraphException("Start vertex wasn't found in graph."))
|
||||
}
|
||||
if (!checkVertexExistance(finish)) {
|
||||
throw(VertexAbsenceMultigraphException("Finish vertex wasn't found in graph."))
|
||||
}
|
||||
|
||||
allVertexes.forEach {
|
||||
currentStepsState[it] = WaveStep()
|
||||
}
|
||||
while (!oldFront.isEmpty()) {
|
||||
oldFront.forEach {
|
||||
val currentStepState = currentStepsState[it] ?: WaveStep()
|
||||
// Lookup all edges from vertex.
|
||||
val values = edges.get(it) ?: mutableListOf<Edge<T>>()
|
||||
values.forEach { edge ->
|
||||
val newRoutes = mutableListOf<UInt>()
|
||||
val toStep = currentStepsState[edge.to] ?: WaveStep()
|
||||
|
||||
// Create new pathes and count their costs.
|
||||
if (currentStepState.routes.isEmpty()) {
|
||||
val newVertexes = mutableListOf(edge.from, edge.to)
|
||||
val newCost = edge.cost
|
||||
if (newCost <= limits && edge.from != edge.to) {
|
||||
newRoutes.add(edge.id)
|
||||
toStep.routes.add(newRoutes)
|
||||
toStep.costs.add(edge.cost)
|
||||
toStep.vertexes.add(newVertexes)
|
||||
currentStepsState[edge.to] = toStep
|
||||
// Add new wave front.
|
||||
if (edge.to != finish && edge.to !in oldFront) {
|
||||
newFront.add(edge.to)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
currentStepState.routes.forEachIndexed { index, it ->
|
||||
val newRoutes = it.toMutableList()
|
||||
val oldCost = currentStepState.costs.get(index)
|
||||
val newCost = edge.cost + oldCost
|
||||
val newVertexes = currentStepState.vertexes.get(index).toMutableList()
|
||||
if (newCost <= limits && edge.to !in currentStepState.vertexes.get(index)) {
|
||||
newRoutes.add(edge.id)
|
||||
newVertexes.add(edge.to)
|
||||
var addNewSequence = true
|
||||
|
||||
if (newRoutes !in toStep.routes) {
|
||||
toStep.routes.add(newRoutes)
|
||||
toStep.costs.add(newCost)
|
||||
toStep.vertexes.add(newVertexes)
|
||||
currentStepsState[edge.to] = toStep
|
||||
if (edge.to != finish && edge.to !in oldFront) {
|
||||
newFront.add(edge.to)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
oldFront = newFront.toMutableSet()
|
||||
newFront.clear()
|
||||
}
|
||||
return currentStepsState[finish]?.routes ?: listOf<List<UInt>>()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,225 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
import Foundation
|
||||
import CityMap
|
||||
|
||||
class SimpleCost: Cost {
|
||||
let value: Int
|
||||
|
||||
init(cost: Int) {
|
||||
value = cost
|
||||
}
|
||||
|
||||
func plus(other: Cost) -> Cost {
|
||||
let otherInstance = other as! SimpleCost
|
||||
return SimpleCost(cost: value + otherInstance.value)
|
||||
}
|
||||
|
||||
func minus(other: Cost) -> Cost {
|
||||
let otherInstance = other as! SimpleCost
|
||||
return SimpleCost(cost: value - otherInstance.value)
|
||||
}
|
||||
|
||||
func compareTo(other: Cost) -> Int32 {
|
||||
let otherInstance = other as! SimpleCost
|
||||
if (value < otherInstance.value) {
|
||||
return -1
|
||||
}
|
||||
if (value == otherInstance.value) {
|
||||
return 0
|
||||
}
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
class SwiftInteropBenchmarks {
|
||||
|
||||
let BENCHMARK_SIZE = 10000
|
||||
let SMALL_BENCHMARK_SIZE = 50
|
||||
let MEDIUM_BENCHMARK_SIZE = 100
|
||||
var multigraph = Multigraph()
|
||||
var cityMap = CityMap()
|
||||
|
||||
func randomInt(border: Int) -> Int {
|
||||
return Int.random(in: 1 ..< border)
|
||||
}
|
||||
|
||||
func randomDouble(border: Double) -> Double {
|
||||
return Double.random(in: 0 ..< border)
|
||||
}
|
||||
|
||||
func randomString(length: Int) -> String {
|
||||
let letters = "abcdefghijklmnopqrst"
|
||||
return String((0..<length).map{ _ in letters.randomElement()! })
|
||||
}
|
||||
|
||||
func randomTransport() -> Transport {
|
||||
let allValues = [Transport.car, Transport.underground, Transport.bus, Transport.trolleybus, Transport.tram, Transport.taxi, Transport.foot]
|
||||
return allValues.randomElement()!
|
||||
}
|
||||
|
||||
func randomInterest() -> Interest {
|
||||
let allValues = [Interest.sight, Interest.culture, Interest.park, Interest.entertainment]
|
||||
return allValues.randomElement()!
|
||||
}
|
||||
|
||||
func randomPlace() -> Place {
|
||||
return Place(geoCoordinateX: randomDouble(border: 180), geoCoordinateY: randomDouble(border: 90), name: randomString(length: 5), interestCategory: randomInterest())
|
||||
}
|
||||
|
||||
func randomRouteCost() -> RouteCost {
|
||||
let transportCount = randomInt(border: 7)
|
||||
let interestCount = randomInt(border: 4)
|
||||
var transports = Set<Transport>()
|
||||
var interests = Set<Interest>()
|
||||
|
||||
for _ in 0...transportCount {
|
||||
transports.insert(randomTransport())
|
||||
}
|
||||
|
||||
for _ in 0...interestCount {
|
||||
interests.insert(randomInterest())
|
||||
}
|
||||
|
||||
return RouteCost(moneyCost: randomDouble(border: 10000), timeCost: randomDouble(border: 24), interests: interests, transport: transports)
|
||||
}
|
||||
|
||||
func initMultigraph(size: Int) {
|
||||
multigraph = Multigraph()
|
||||
for i in 1...size {
|
||||
multigraph.addEdge(from: i, to: i + 1, cost: SimpleCost(cost: (i + 1) % i ))
|
||||
multigraph.addEdge(from: i, to: i * 2, cost: SimpleCost(cost: (i * 2) % i))
|
||||
multigraph.addEdge(from: i + 5, to: i, cost: SimpleCost(cost: (i + 5) % i))
|
||||
}
|
||||
}
|
||||
|
||||
func createMultigraphOfInt() {
|
||||
initMultigraph(size: BENCHMARK_SIZE)
|
||||
}
|
||||
|
||||
func fillCityMap() {
|
||||
cityMap = CityMap()
|
||||
for _ in 0...BENCHMARK_SIZE {
|
||||
cityMap.addRoute(from: randomPlace(), to: randomPlace(), cost: randomRouteCost())
|
||||
}
|
||||
}
|
||||
|
||||
func initCityMap(size: Int) {
|
||||
cityMap = CityMap()
|
||||
let allValuesInterests = [Interest.sight, Interest.culture, Interest.park, Interest.entertainment]
|
||||
let allValuesTransport = [Transport.car, Transport.underground, Transport.bus, Transport.trolleybus, Transport.tram, Transport.taxi, Transport.foot]
|
||||
for i in 1...size {
|
||||
let from = Place(geoCoordinateX: Double(i % 180), geoCoordinateY: Double(i % 90 + 90 % i),
|
||||
name: randomString(length: 5), interestCategory: allValuesInterests[i % allValuesInterests.count])
|
||||
let to = Place(geoCoordinateX: Double(i % 180 + 180 % i), geoCoordinateY: Double(i % 90),
|
||||
name: randomString(length: 5), interestCategory: allValuesInterests[(i + 5) % allValuesInterests.count])
|
||||
var transports = Set<Transport>()
|
||||
var interests = Set<Interest>()
|
||||
for j in 0...i % 2 + 1 {
|
||||
interests.insert(allValuesInterests[(i + j) % allValuesInterests.count])
|
||||
}
|
||||
for j in 0...i % 2 + 1 {
|
||||
transports.insert(allValuesTransport[i % allValuesTransport.count])
|
||||
}
|
||||
let cost = RouteCost(moneyCost: Double((i * 2) % 10000), timeCost: Double((i + 3) % 24), interests: interests, transport: transports)
|
||||
cityMap.addRoute(from: from, to: to, cost: cost)
|
||||
}
|
||||
}
|
||||
|
||||
func searchRoutesInSwiftMultigraph() {
|
||||
initMultigraph(size: SMALL_BENCHMARK_SIZE)
|
||||
for _ in 0...SMALL_BENCHMARK_SIZE {
|
||||
var vertexes = Array(multigraph.allVertexes)
|
||||
var result = multigraph.searchRoutesWithLimits(start: 1,
|
||||
finish: SMALL_BENCHMARK_SIZE / 2 + SMALL_BENCHMARK_SIZE / 4,
|
||||
limits: SimpleCost(cost: SMALL_BENCHMARK_SIZE / 5))
|
||||
var count = result.map{ $0.count }.reduce(0, +)
|
||||
}
|
||||
}
|
||||
|
||||
func searchTravelRoutes() {
|
||||
cityMap = CityMap()
|
||||
initCityMap(size: BENCHMARK_SIZE)
|
||||
let transports: Set = [Transport.car, Transport.underground]
|
||||
let interests: Set = [Interest.sight, Interest.culture]
|
||||
let cost = RouteCost(moneyCost: 500, timeCost: 6, interests: interests, transport: transports)
|
||||
for _ in 0...SMALL_BENCHMARK_SIZE {
|
||||
var result = cityMap.getRoutes(start: Array(cityMap.allPlaces).first!, finish: Array(cityMap.allPlaces).last!, limits: cost)
|
||||
var totalCost = result.flatMap{ $0 }.map { $0.cost.moneyCost }.reduce(0, +)
|
||||
}
|
||||
}
|
||||
|
||||
func availableTransportOnMap() {
|
||||
cityMap = CityMap()
|
||||
initCityMap(size: MEDIUM_BENCHMARK_SIZE)
|
||||
Set(cityMap.allRoutes.map { (cityMap.getRouteById(id: $0.id).cost as! RouteCost).transport })
|
||||
}
|
||||
|
||||
func allPlacesMapedByInterests() {
|
||||
cityMap = CityMap()
|
||||
initCityMap(size: MEDIUM_BENCHMARK_SIZE)
|
||||
let placesByInterests = cityMap.allPlaces.reduce([Interest: Array<Place>]()) { (dict, place) -> [Interest: Array<Place>] in
|
||||
var dict = dict
|
||||
if (dict[place.interestCategory] != nil) {
|
||||
dict[place.interestCategory]?.append(place)
|
||||
} else {
|
||||
dict[place.interestCategory] = [place]
|
||||
}
|
||||
return dict
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func getAllPlacesWithStraightRoutesTo() {
|
||||
cityMap = CityMap()
|
||||
initCityMap(size: MEDIUM_BENCHMARK_SIZE)
|
||||
for _ in 0...SMALL_BENCHMARK_SIZE {
|
||||
let start = cityMap.allPlaces.randomElement()!
|
||||
let availableRoutes = cityMap.getAllStraightRoutesFrom(place: start)
|
||||
var _ = availableRoutes.map { $0.to }
|
||||
}
|
||||
}
|
||||
|
||||
func goToAllAvailablePlaces() {
|
||||
cityMap = CityMap()
|
||||
initCityMap(size: MEDIUM_BENCHMARK_SIZE)
|
||||
for _ in 0...SMALL_BENCHMARK_SIZE {
|
||||
let start = cityMap.allPlaces.randomElement()!
|
||||
let availableRoutes = cityMap.getAllStraightRoutesFrom(place: start)
|
||||
availableRoutes.map { 2 * $0.cost.moneyCost }
|
||||
}
|
||||
}
|
||||
|
||||
func removeVertexAndEdgesSwiftMultigraph() {
|
||||
initMultigraph(size: SMALL_BENCHMARK_SIZE)
|
||||
let multigraphCopy = multigraph.doCopyMultigraph()
|
||||
var edges = multigraphCopy.allEdges
|
||||
while (!edges.isEmpty) {
|
||||
multigraphCopy.removeEdge(id: UInt32(edges.randomElement()!))
|
||||
let vertexes = multigraphCopy.allVertexes
|
||||
multigraphCopy.removeVertex(vertex: vertexes.randomElement()!)
|
||||
edges = multigraphCopy.allEdges
|
||||
}
|
||||
}
|
||||
|
||||
func stringInterop() {
|
||||
cityMap = CityMap()
|
||||
fillCityMap()
|
||||
let place = cityMap.allPlaces.first!
|
||||
for _ in 0...BENCHMARK_SIZE {
|
||||
let _ = place.fullDescription
|
||||
}
|
||||
}
|
||||
|
||||
func simpleFunction() {
|
||||
cityMap = CityMap()
|
||||
fillCityMap()
|
||||
let place = cityMap.allPlaces.first!
|
||||
for _ in 0...BENCHMARK_SIZE {
|
||||
let _ = place.compareTo(other:place)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
import Foundation
|
||||
import CityMap
|
||||
|
||||
var runner = BenchmarksRunner()
|
||||
let args = KotlinArray(size: Int32(CommandLine.arguments.count - 1), init: {index in
|
||||
CommandLine.arguments[Int(truncating: index) + 1]
|
||||
})
|
||||
runner.runBenchmarks(args: args, run: { (parser: ArgParser) -> [BenchmarkResult] in
|
||||
var swiftBenchmarks = SwiftInteropBenchmarks()
|
||||
var swiftLauncher = SwiftLauncher(numWarmIterations: parser.get(name: "warmup") as! Int32,
|
||||
numberOfAttempts: parser.get(name: "repeat") as! Int32, prefix: parser.get(name: "prefix") as! String)
|
||||
swiftLauncher.add(name: "createMultigraphOfInt", benchmark: swiftBenchmarks.createMultigraphOfInt)
|
||||
swiftLauncher.add(name: "fillCityMap", benchmark: swiftBenchmarks.fillCityMap)
|
||||
swiftLauncher.add(name: "searchRoutesInSwiftMultigraph", benchmark: swiftBenchmarks.searchRoutesInSwiftMultigraph)
|
||||
swiftLauncher.add(name: "searchTravelRoutes", benchmark: swiftBenchmarks.searchTravelRoutes)
|
||||
swiftLauncher.add(name: "availableTransportOnMap", benchmark: swiftBenchmarks.availableTransportOnMap)
|
||||
swiftLauncher.add(name: "allPlacesMapedByInterests", benchmark: swiftBenchmarks.allPlacesMapedByInterests)
|
||||
swiftLauncher.add(name: "getAllPlacesWithStraightRoutesTo", benchmark: swiftBenchmarks.getAllPlacesWithStraightRoutesTo)
|
||||
swiftLauncher.add(name: "goToAllAvailablePlaces", benchmark: swiftBenchmarks.goToAllAvailablePlaces)
|
||||
swiftLauncher.add(name: "removeVertexAndEdgesSwiftMultigraph", benchmark: swiftBenchmarks.removeVertexAndEdgesSwiftMultigraph)
|
||||
swiftLauncher.add(name: "stringInterop", benchmark: swiftBenchmarks.stringInterop)
|
||||
swiftLauncher.add(name: "simpleFunction", benchmark: swiftBenchmarks.simpleFunction)
|
||||
return swiftLauncher.launch(filters: parser.getAll(name: "filter"), filterRegexes: parser.getAll(name: "filterRegex"))
|
||||
}, parseArgs: runner.parse, collect: { (benchmarks: [BenchmarkResult], parser: ArgParser) -> Void in
|
||||
runner.collect(results: benchmarks, parser: parser)
|
||||
})
|
||||
@@ -1,36 +1,39 @@
|
||||
import org.jetbrains.kotlin.PlatformInfo
|
||||
import org.jetbrains.kotlin.MPPTools
|
||||
|
||||
def dist = findProperty('org.jetbrains.kotlin.native.home') ?: 'dist'
|
||||
dist = (new File(dist)).isAbsolute() ? dist : "${project.getProjectDir()}/$dist"
|
||||
def toolExtension = System.getProperty("os.name").startsWith('Windows') ? ".bat" : ""
|
||||
|
||||
def linkerOpts = []
|
||||
if (MPPTools.isMacos()) {
|
||||
if (PlatformInfo.isMac()) {
|
||||
linkerOpts += ['-linker-options','-L/opt/local/lib', '-linker-options', '-L/usr/local/lib']
|
||||
} else if (MPPTools.isLinux()) {
|
||||
} else if (PlatformInfo.isLinux()) {
|
||||
linkerOpts += ['-linker-options', '-L/usr/lib/x86_64-linux-gnu', '-linker-options', '-L/usr/lib64']
|
||||
} else if (MPPTools.isWindows()) {
|
||||
} else if (PlatformInfo.isWindows()) {
|
||||
linkerOpts += ['-linker-options', "-L${MPPTools.mingwPath()}/lib"]
|
||||
}
|
||||
|
||||
def includeDirsFfmpeg = []
|
||||
def filterDirsFfmpeg = []
|
||||
if (MPPTools.isMacos()) {
|
||||
if (PlatformInfo.isMac()) {
|
||||
filterDirsFfmpeg += ['-headerFilterAdditionalSearchPrefix', '/opt/local/include',
|
||||
'-headerFilterAdditionalSearchPrefix', '/usr/local/include']
|
||||
} else if (MPPTools.isLinux()) {
|
||||
} else if (PlatformInfo.isLinux()) {
|
||||
filterDirsFfmpeg += ['-headerFilterAdditionalSearchPrefix', '/usr/include',
|
||||
'-headerFilterAdditionalSearchPrefix', '/usr/include/x86_64-linux-gnu',
|
||||
'-headerFilterAdditionalSearchPrefix', '/usr/include/ffmpeg']
|
||||
} else if (MPPTools.isWindows()) {
|
||||
} else if (PlatformInfo.isWindows()) {
|
||||
includeDirsFfmpeg += ['-compiler-option', "-I${MPPTools.mingwPath()}/include"]
|
||||
}
|
||||
|
||||
def includeDirsSdl = []
|
||||
if (MPPTools.isMacos()) {
|
||||
if (PlatformInfo.isMac()) {
|
||||
includeDirsSdl += ['-compiler-option', '-I/opt/local/include/SDL2',
|
||||
'-compiler-option', '-I/usr/local/include/SDL2']
|
||||
} else if (MPPTools.isLinux()) {
|
||||
} else if (PlatformInfo.isLinux()) {
|
||||
includeDirsSdl += ['-compiler-option', '-I/usr/include/SDL2']
|
||||
} else if (MPPTools.isWindows()) {
|
||||
} else if (PlatformInfo.isWindows()) {
|
||||
includeDirsSdl += ['-compiler-option', "-I${MPPTools.mingwPath()}/include/SDL2"]
|
||||
}
|
||||
|
||||
@@ -47,4 +50,4 @@ project.ext {
|
||||
"-Xmulti-platform", "$dist/../samples/videoplayer/src/videoPlayerMain/kotlin",
|
||||
"-entry", "sample.videoplayer.main"] + linkerOpts]
|
||||
}
|
||||
apply from: rootProject.file("${rootProject.rootDir}/gradle/compileBenchmark.gradle")
|
||||
apply from: rootProject.file("${rootProject.rootDir}/performance/gradle/compileBenchmark.gradle")
|
||||
+13
-3
@@ -1,3 +1,6 @@
|
||||
import org.jetbrains.kotlin.PlatformInfo
|
||||
import org.jetbrains.kotlin.konan.target.HostManager
|
||||
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
@@ -29,8 +32,16 @@ include ':common'
|
||||
include ':backend.native:tests'
|
||||
include ':backend.native:debugger-tests'
|
||||
include ':utilities'
|
||||
//include ':performance' TODO: return when there is one HostManager class version
|
||||
//include ':tools:benchmarksAnalyzer'
|
||||
include ':performance'
|
||||
include ':performance:ring'
|
||||
include ':performance:cinterop'
|
||||
include ':performance:helloworld'
|
||||
include ':performance:videoplayer'
|
||||
include ':performance:framework'
|
||||
if (PlatformInfo.isAppleTarget(HostManager.host)) {
|
||||
include ':performance:objcinterop'
|
||||
include ':performance:swiftinterop'
|
||||
}
|
||||
include ':platformLibs'
|
||||
|
||||
includeBuild 'shared'
|
||||
@@ -38,7 +49,6 @@ includeBuild 'extracted/konan.metadata'
|
||||
includeBuild 'extracted/konan.serializer'
|
||||
includeBuild 'tools/kotlin-native-gradle-plugin'
|
||||
|
||||
|
||||
if (hasProperty("kotlinProjectPath")) {
|
||||
include ':runtime:generator'
|
||||
includeBuild(kotlinProjectPath) {
|
||||
|
||||
Reference in New Issue
Block a user