Objective c interop benchmarks migration (#3004)

This commit is contained in:
LepilkinaElena
2019-06-03 16:32:14 +03:00
committed by GitHub
parent 285bfc11f8
commit 69fd55656d
46 changed files with 1467 additions and 315 deletions
+7 -8
View File
@@ -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:
+4 -4
View File
@@ -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
View File
@@ -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
}
}
}
+5 -2
View File
@@ -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)
}
@@ -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) {
@@ -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
@@ -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()
}
@@ -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",
@@ -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
@@ -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
}
}
}
}
@@ -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" })
}
+2 -1
View File
@@ -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 {
+44 -3
View File
@@ -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'
}
-36
View File
@@ -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"]
-21
View File
@@ -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()
}
+1 -2
View File
@@ -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
+6 -2
View File
@@ -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
+11 -11
View File
@@ -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)
+3 -1
View File
@@ -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")
+29
View File
@@ -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
@@ -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!")
}
}
@@ -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"))
})
}
@@ -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
+1 -1
View File
@@ -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")
-5
View File
@@ -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()
+153
View File
@@ -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)
})
+13 -10
View File
@@ -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
View File
@@ -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) {