Gradle plugin for swift benchmarks (#3361)

This commit is contained in:
LepilkinaElena
2019-09-30 14:37:06 +03:00
committed by GitHub
parent 8408a04a1a
commit 9d8c49d763
12 changed files with 371 additions and 392 deletions
+5 -1
View File
@@ -63,12 +63,16 @@ gradlePlugin {
plugins {
create("benchmarkPlugin") {
id = "benchmarking"
implementationClass = "org.jetbrains.kotlin.benchmark.BenchmarkingPlugin"
implementationClass = "org.jetbrains.kotlin.benchmark.KotlinNativeBenchmarkingPlugin"
}
create("compileBenchmarking") {
id = "compile-benchmarking"
implementationClass = "org.jetbrains.kotlin.benchmark.CompileBenchmarkingPlugin"
}
create("swiftBenchmarking") {
id = "swift-benchmarking"
implementationClass = "org.jetbrains.kotlin.benchmark.SwiftBenchmarkingPlugin"
}
}
}
@@ -159,21 +159,11 @@ fun sendUploadRequest(url: String, fileName: String, username: String? = null, p
fun createRunTask(
subproject: Project,
name: String,
linkTask: KotlinNativeLink,
linkTask: Task,
executable: String,
outputFileName: String
): Task {
return subproject.tasks.create(name, RunKotlinNativeTask::class.java, linkTask, outputFileName)
}
@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
return subproject.tasks.create(name, RunKotlinNativeTask::class.java, linkTask, executable, outputFileName)
}
fun getJvmCompileTime(programName: String): BenchmarkResult =
@@ -1,80 +0,0 @@
/*
* 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.TaskAction
import org.gradle.api.tasks.options.Option
import org.gradle.api.tasks.Input
import javax.inject.Inject
import java.io.File
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 = ""
@Input
@Option(option = "filterRegex", description = "Benchmarks to run, described by regular expressions (comma-separated)")
var filterRegex: String = ""
@Input
@Option(option = "verbose", description = "Verbose mode of running benchmarks")
var verbose: Boolean = false
private var curArgs: List<String> = emptyList()
private val curEnvironment: MutableMap<String, Any> = mutableMapOf()
fun args(vararg args: Any) {
curArgs = args.map { it.toString() }
}
fun environment(map: Map<String, Any>) {
curEnvironment += map
}
override fun configure(configureClosure: Closure<Any>): Task {
val task = super.configure(configureClosure)
return task
}
fun depends(taskName: String) {
this.dependsOn += taskName
}
private fun executeTask(output: java.io.OutputStream? = null) {
val filterArgs = filter.splitCommaSeparatedOption("-f")
val filterRegexArgs = filterRegex.splitCommaSeparatedOption("-fr")
project.exec {
it.executable = executable
it.args = curArgs + filterArgs + filterRegexArgs
it.environment = curEnvironment
it.workingDir(workingDir)
if (verbose) {
it.args("-v")
}
if (output != null)
it.standardOutput = output
}
}
@TaskAction
fun run() {
if (outputFileName != null)
File(outputFileName).outputStream().use { output -> executeTask(output) }
else
executeTask()
}
internal fun emptyConfigureClosure() = object : Closure<Any>(this) {
override fun call(): RunBenchmarksExecutableTask {
return this@RunBenchmarksExecutableTask
}
}
}
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin
import org.gradle.api.DefaultTask
import org.gradle.api.Task
import org.jetbrains.kotlin.gradle.tasks.KotlinNativeLink
import org.gradle.api.tasks.TaskAction
import org.gradle.api.tasks.options.Option
@@ -14,7 +15,8 @@ import java.io.ByteArrayOutputStream
import java.io.File
import javax.inject.Inject
open class RunKotlinNativeTask @Inject constructor(private val linkTask: KotlinNativeLink,
open class RunKotlinNativeTask @Inject constructor(private val linkTask: Task,
private val executable: String,
private val outputFileName: String
) : DefaultTask() {
@Input
@@ -48,7 +50,7 @@ open class RunKotlinNativeTask @Inject constructor(private val linkTask: KotlinN
fun run() {
var output = ByteArrayOutputStream()
project.exec {
it.executable = linkTask.binary.outputFile.absolutePath
it.executable = executable
it.args("list")
it.standardOutput = output
}
@@ -63,7 +65,7 @@ open class RunKotlinNativeTask @Inject constructor(private val linkTask: KotlinN
val results = benchmarksToRun.map { benchmark ->
output = ByteArrayOutputStream()
project.exec {
it.executable = linkTask.binary.outputFile.absolutePath
it.executable = executable
it.args(argumentsList)
it.args("-f", benchmark)
if (verbose) {
@@ -4,45 +4,33 @@ import groovy.lang.Closure
import org.gradle.api.NamedDomainObjectContainer
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.artifacts.Dependency
import org.gradle.jvm.tasks.Jar
import org.gradle.util.ConfigureUtil
import org.jetbrains.kotlin.*
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTargetPreset
import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType
import org.jetbrains.kotlin.konan.target.HostManager
import javax.inject.Inject
import kotlin.reflect.KClass
private val NamedDomainObjectContainer<KotlinSourceSet>.commonMain
internal val NamedDomainObjectContainer<KotlinSourceSet>.commonMain
get() = maybeCreate("commonMain")
private val NamedDomainObjectContainer<KotlinSourceSet>.nativeMain
internal val NamedDomainObjectContainer<KotlinSourceSet>.nativeMain
get() = maybeCreate("nativeMain")
private val NamedDomainObjectContainer<KotlinSourceSet>.jvmMain
get() = maybeCreate("jvmMain")
private val Project.benchmark: BenchmarkExtension
get() = extensions.getByName(BenchmarkingPlugin.BENCHMARK_EXTENSION_NAME) as BenchmarkExtension
private val Project.nativeWarmup: Int
internal val Project.nativeWarmup: Int
get() = (property("nativeWarmup") as String).toInt()
private val Project.jvmWarmup: Int
get() = (property("jvmWarmup") as String).toInt()
private val Project.attempts: Int
internal val Project.attempts: Int
get() = (property("attempts") as String).toInt()
private val Project.nativeBenchResults: String
internal val Project.nativeBenchResults: String
get() = property("nativeBenchResults") as String
private val Project.jvmBenchResults: String
get() = property("jvmBenchResults") as String
private val Project.compilerArgs: List<String>
internal val Project.compilerArgs: List<String>
get() = (findProperty("compilerArgs") as String?)?.split("\\s").orEmpty()
internal val Project.kotlinVersion: String
@@ -75,10 +63,8 @@ internal val Project.commonBenchmarkProperties: Map<String, Any>
open class BenchmarkExtension @Inject constructor(val project: Project) {
var applicationName: String = project.name
var commonSrcDirs: Collection<Any> = emptyList()
var jvmSrcDirs: Collection<Any> = emptyList()
var nativeSrcDirs: Collection<Any> = emptyList()
var mingwSrcDirs: Collection<Any> = emptyList()
var posixSrcDirs: Collection<Any> = emptyList()
var compileTasks: List<String> = emptyList()
var linkerOpts: Collection<String> = emptyList()
val dependencies: BenchmarkDependencies = BenchmarkDependencies()
@@ -91,7 +77,7 @@ open class BenchmarkExtension @Inject constructor(val project: Project) {
}
inner class BenchmarkDependencies {
private val sourceSets: NamedDomainObjectContainer<KotlinSourceSet>
public val sourceSets: NamedDomainObjectContainer<KotlinSourceSet>
get() = project.kotlin.sourceSets
fun project(path: String): Dependency = project.dependencies.project(mapOf("path" to path))
@@ -103,10 +89,6 @@ open class BenchmarkExtension @Inject constructor(val project: Project) {
implementation(notation)
}
fun jvm(notation: Any) = sourceSets.jvmMain.dependencies {
implementation(notation)
}
fun native(notation: Any) = sourceSets.nativeMain.dependencies {
implementation(notation)
}
@@ -116,25 +98,30 @@ open class BenchmarkExtension @Inject constructor(val project: Project) {
/**
* A plugin configuring a benchmark Kotlin/Native project.
*/
open class BenchmarkingPlugin: Plugin<Project> {
abstract class BenchmarkingPlugin: Plugin<Project> {
protected abstract val Project.nativeExecutable: String
protected abstract val Project.nativeLinkTask: Task
protected abstract val Project.benchmark: BenchmarkExtension
protected abstract val benchmarkExtensionName: String
protected abstract val benchmarkExtensionClass: KClass<*>
private val mingwPath: String = System.getenv("MINGW64_DIR") ?: "c:/msys64/mingw64"
protected val mingwPath: String = System.getenv("MINGW64_DIR") ?: "c:/msys64/mingw64"
private fun Project.determinePreset(): KotlinNativeTargetPreset =
protected open fun Project.determinePreset(): KotlinNativeTargetPreset =
defaultHostPreset(this).also { preset ->
logger.quiet("$project has been configured for ${preset.name} platform.")
} as KotlinNativeTargetPreset
private fun Project.configureSourceSets(kotlinVersion: String) {
protected abstract fun NamedDomainObjectContainer<KotlinSourceSet>.configureSources(project: Project)
protected open fun NamedDomainObjectContainer<KotlinSourceSet>.additionalConfigurations(project: Project) {}
protected open fun Project.configureSourceSets(kotlinVersion: String) {
with(kotlin.sourceSets) {
commonMain.dependencies {
implementation("org.jetbrains.kotlin:kotlin-stdlib-common:$kotlinStdlibVersion")
}
jvmMain.dependencies {
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinStdlibVersion")
}
project.configurations.getByName(nativeMain.implementationConfigurationName).apply {
// Exclude dependencies already included into K/N distribution (aka endorsed libraries).
exclude(mapOf("module" to "kotlinx.cli"))
@@ -144,69 +131,49 @@ open class BenchmarkingPlugin: Plugin<Project> {
it.setUrl(kotlinStdlibRepo)
}
additionalConfigurations(this@configureSourceSets)
// Add sources specified by a user in the benchmark DSL.
afterEvaluate {
benchmark.let {
commonMain.kotlin.srcDirs(*it.commonSrcDirs.toTypedArray())
if (HostManager.hostIsMingw) {
nativeMain.kotlin.srcDirs(*(it.nativeSrcDirs + it.mingwSrcDirs).toTypedArray())
} else {
nativeMain.kotlin.srcDirs(*(it.nativeSrcDirs + it.posixSrcDirs).toTypedArray())
}
jvmMain.kotlin.srcDirs(*it.jvmSrcDirs.toTypedArray())
}
configureSources(project)
}
}
}
private fun Project.configureJVMTarget() {
kotlin.jvm {
compilations.all {
it.compileKotlinTask.kotlinOptions {
jvmTarget = "1.8"
suppressWarnings = true
freeCompilerArgs = project.compilerArgs
}
protected open fun KotlinNativeTarget.configureNativeOutput(project: Project) {
binaries.executable(NATIVE_EXECUTABLE_NAME, listOf(RELEASE)) {
if (HostManager.hostIsMingw) {
linkerOpts.add("-L${mingwPath}/lib")
}
runTask!!.apply {
group = ""
enabled = false
}
// Specify settings configured by a user in the benchmark extension.
project.afterEvaluate {
linkerOpts.addAll(project.benchmark.linkerOpts)
}
}
}
private fun Project.configureNativeTarget(hostPreset: KotlinNativeTargetPreset) {
protected open fun Project.configureNativeTarget(hostPreset: KotlinNativeTargetPreset) {
kotlin.targetFromPreset(hostPreset, NATIVE_TARGET_NAME) {
compilations.getByName("main").kotlinOptions.freeCompilerArgs = project.compilerArgs
compilations.getByName("main").enableEndorsedLibs = true
binaries.executable(NATIVE_EXECUTABLE_NAME, listOf(RELEASE)) {
if (HostManager.hostIsMingw) {
linkerOpts.add("-L${mingwPath}/lib")
}
runTask!!.apply {
group = ""
enabled = false
}
// Specify settings configured by a user in the benchmark extension.
afterEvaluate {
linkerOpts.addAll(benchmark.linkerOpts)
}
}
configureNativeOutput(this@configureNativeTarget)
}
}
private fun Project.configureMPPExtension() {
configureSourceSets(kotlinVersion)
configureJVMTarget()
configureNativeTarget(determinePreset())
protected open fun configureMPPExtension(project: Project) {
project.configureSourceSets(project.kotlinVersion)
project.configureNativeTarget(project.determinePreset())
}
private fun Project.configureTasks() {
// Native run task.
val nativeTarget = kotlin.targets.getByName(NATIVE_TARGET_NAME) as KotlinNativeTarget
val nativeExecutable = nativeTarget.binaries.getExecutable(NATIVE_EXECUTABLE_NAME, NativeBuildType.RELEASE)
val konanRun = createRunTask(this, "konanRun", nativeExecutable.linkTask,
buildDir.resolve(nativeBenchResults).absolutePath).apply {
protected open fun Project.configureNativeTask(nativeTarget: KotlinNativeTarget): Task {
val konanRun = createRunTask(this, "konanRun", nativeLinkTask,
nativeExecutable, buildDir.resolve(nativeBenchResults).absolutePath).apply {
group = BENCHMARKING_GROUP
description = "Runs the benchmark for Kotlin/Native."
}
@@ -217,80 +184,61 @@ open class BenchmarkingPlugin: Plugin<Project> {
"-p", "${benchmark.applicationName}::"
)
}
return konanRun
}
// JVM run task.
val jvmRun = tasks.create("jvmRun", RunJvmTask::class.java) { task ->
task.dependsOn("build")
val mainCompilation = kotlin.jvm().compilations.getByName("main")
val runtimeDependencies = configurations.getByName(mainCompilation.runtimeDependencyConfigurationName)
task.classpath(files(mainCompilation.output.allOutputs, runtimeDependencies))
task.main = "MainKt"
protected abstract fun Project.configureJvmTask(): Task
task.group = BENCHMARKING_GROUP
task.description = "Runs the benchmark for Kotlin/JVM."
protected open fun Project.getCompilerFlags(nativeTarget: KotlinNativeTarget) =
nativeTarget.compilations.main.kotlinOptions.freeCompilerArgs.map { "\"$it\"" }
// Specify settings configured by a user in the benchmark extension.
afterEvaluate {
task.args(
"-w", jvmWarmup,
"-r", attempts,
"-o", buildDir.resolve(jvmBenchResults),
"-p", "${benchmark.applicationName}::"
)
}
}
// Native report task.
val konanJsonReport = tasks.create("konanJsonReport") {
protected open fun Project.collectCodeSize(applicationName: String) =
getCodeSizeBenchmark(applicationName, nativeExecutable)
protected open fun Project.configureKonanJsonTask(nativeTarget: KotlinNativeTarget): Task {
return tasks.create("konanJsonReport") {
it.group = BENCHMARKING_GROUP
it.description = "Builds the benchmarking report for Kotlin/Native."
it.doLast {
val applicationName = benchmark.applicationName
val nativeCompileTime = getNativeCompileTime(applicationName)
val benchContents = buildDir.resolve(nativeBenchResults).readText()
val nativeCompileTime = if (benchmark.compileTasks.isEmpty()) getNativeCompileTime(applicationName)
else getNativeCompileTime(applicationName, benchmark.compileTasks)
val properties = commonBenchmarkProperties + mapOf(
"type" to "native",
"compilerVersion" to konanVersion,
"flags" to nativeTarget.compilations.main.kotlinOptions.freeCompilerArgs.map { "\"$it\"" },
"benchmarks" to benchContents,
"compileTime" to listOf(nativeCompileTime),
"codeSize" to getCodeSizeBenchmark(applicationName, nativeExecutable.outputFile.absolutePath)
"type" to "native",
"compilerVersion" to konanVersion,
"flags" to getCompilerFlags(nativeTarget),
"benchmarks" to benchContents,
"compileTime" to listOf(nativeCompileTime),
"codeSize" to collectCodeSize(applicationName)
)
val output = createJsonReport(properties)
buildDir.resolve(nativeJson).writeText(output)
}
}
}
protected abstract fun Project.configureJvmJsonTask(jvmRun: Task): Task
protected open fun Project.configureExtraTasks() {}
private fun Project.configureTasks() {
val nativeTarget = kotlin.targets.getByName(NATIVE_TARGET_NAME) as KotlinNativeTarget
configureExtraTasks()
// Native run task.
configureNativeTask(nativeTarget)
// JVM run task.
val jvmRun = configureJvmTask()
// Native report task.
configureKonanJsonTask(nativeTarget)
// JVM report task.
val jvmJsonReport = tasks.create("jvmJsonReport") {
it.group = BENCHMARKING_GROUP
it.description = "Builds the benchmarking report for Kotlin/JVM."
it.doLast {
val applicationName = benchmark.applicationName
val jarPath = (tasks.getByName("jvmJar") as Jar).archiveFile.get().asFile
val jvmCompileTime = getJvmCompileTime(applicationName)
val benchContents = buildDir.resolve(jvmBenchResults).readText()
val properties: Map<String, Any> = commonBenchmarkProperties + mapOf(
"type" to "jvm",
"compilerVersion" to kotlinVersion,
"benchmarks" to benchContents,
"compileTime" to listOf(jvmCompileTime),
"codeSize" to getCodeSizeBenchmark(applicationName, jarPath.absolutePath)
)
val output = createJsonReport(properties)
buildDir.resolve(jvmJson).writeText(output)
}
jvmRun.finalizedBy(it)
}
configureJvmJsonTask(jvmRun)
}
override fun apply(target: Project) = with(target) {
@@ -298,18 +246,16 @@ open class BenchmarkingPlugin: Plugin<Project> {
// Use Kotlin compiler version specified by the project property.
dependencies.add("kotlinCompilerClasspath", "org.jetbrains.kotlin:kotlin-compiler-embeddable:$kotlinVersion")
extensions.create(BENCHMARK_EXTENSION_NAME, BenchmarkExtension::class.java, this)
configureMPPExtension()
addTimeListener(this)
extensions.create(benchmarkExtensionName, benchmarkExtensionClass.java, this)
configureMPPExtension(this)
configureTasks()
}
companion object {
const val NATIVE_TARGET_NAME = "native"
const val NATIVE_EXECUTABLE_NAME = "benchmark"
const val BENCHMARK_EXTENSION_NAME = "benchmark"
const val BENCHMARKING_GROUP = "benchmarking"
}
}
@@ -0,0 +1,145 @@
package org.jetbrains.kotlin.benchmark
import org.gradle.jvm.tasks.Jar
import org.gradle.api.NamedDomainObjectContainer
import org.gradle.api.Project
import org.gradle.api.Task
import org.jetbrains.kotlin.*
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.mpp.Executable
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType
import org.jetbrains.kotlin.konan.target.HostManager
import javax.inject.Inject
import kotlin.reflect.KClass
private val NamedDomainObjectContainer<KotlinSourceSet>.jvmMain
get() = maybeCreate("jvmMain")
private val Project.jvmWarmup: Int
get() = (property("jvmWarmup") as String).toInt()
private val Project.jvmBenchResults: String
get() = property("jvmBenchResults") as String
open class KotlinNativeBenchmarkExtension @Inject constructor(project: Project) : BenchmarkExtension(project) {
var jvmSrcDirs: Collection<Any> = emptyList()
var mingwSrcDirs: Collection<Any> = emptyList()
var posixSrcDirs: Collection<Any> = emptyList()
fun BenchmarkExtension.BenchmarkDependencies.jvm(notation: Any) = sourceSets.jvmMain.dependencies {
implementation(notation)
}
}
/**
* A plugin configuring a benchmark Kotlin/Native project.
*/
open class KotlinNativeBenchmarkingPlugin: BenchmarkingPlugin() {
override fun Project.configureJvmJsonTask(jvmRun: Task): Task {
return tasks.create("jvmJsonReport") {
it.group = BENCHMARKING_GROUP
it.description = "Builds the benchmarking report for Kotlin/JVM."
it.doLast {
val applicationName = benchmark.applicationName
val jarPath = (tasks.getByName("jvmJar") as Jar).archiveFile.get().asFile
val jvmCompileTime = getJvmCompileTime(applicationName)
val benchContents = buildDir.resolve(jvmBenchResults).readText()
val properties: Map<String, Any> = commonBenchmarkProperties + mapOf(
"type" to "jvm",
"compilerVersion" to kotlinVersion,
"benchmarks" to benchContents,
"compileTime" to listOf(jvmCompileTime),
"codeSize" to getCodeSizeBenchmark(applicationName, jarPath.absolutePath)
)
val output = createJsonReport(properties)
buildDir.resolve(jvmJson).writeText(output)
}
jvmRun.finalizedBy(it)
}
}
override fun Project.configureJvmTask(): Task {
return tasks.create("jvmRun", RunJvmTask::class.java) { task ->
task.dependsOn("build")
val mainCompilation = kotlin.jvm().compilations.getByName("main")
val runtimeDependencies = configurations.getByName(mainCompilation.runtimeDependencyConfigurationName)
task.classpath(files(mainCompilation.output.allOutputs, runtimeDependencies))
task.main = "MainKt"
task.group = BENCHMARKING_GROUP
task.description = "Runs the benchmark for Kotlin/JVM."
// Specify settings configured by a user in the benchmark extension.
afterEvaluate {
task.args(
"-w", jvmWarmup,
"-r", attempts,
"-o", buildDir.resolve(jvmBenchResults),
"-p", "${benchmark.applicationName}::"
)
}
}
}
override val benchmarkExtensionClass: KClass<*>
get() = KotlinNativeBenchmarkExtension::class
override val Project.benchmark: KotlinNativeBenchmarkExtension
get() = extensions.getByName(benchmarkExtensionName) as KotlinNativeBenchmarkExtension
override val benchmarkExtensionName: String = "benchmark"
private val Project.nativeBinary: Executable
get() = (kotlin.targets.getByName(NATIVE_TARGET_NAME) as KotlinNativeTarget)
.binaries.getExecutable(NATIVE_EXECUTABLE_NAME, NativeBuildType.RELEASE)
override val Project.nativeExecutable: String
get() = nativeBinary.outputFile.absolutePath
override val Project.nativeLinkTask: Task
get() = nativeBinary.linkTask
override fun configureMPPExtension(project: Project) {
super.configureMPPExtension(project)
project.configureJVMTarget()
}
override fun NamedDomainObjectContainer<KotlinSourceSet>.configureSources(project: Project) {
project.benchmark.let {
commonMain.kotlin.srcDirs(*it.commonSrcDirs.toTypedArray())
if (HostManager.hostIsMingw) {
nativeMain.kotlin.srcDirs(*(it.nativeSrcDirs + it.mingwSrcDirs).toTypedArray())
} else {
nativeMain.kotlin.srcDirs(*(it.nativeSrcDirs + it.posixSrcDirs).toTypedArray())
}
jvmMain.kotlin.srcDirs(*it.jvmSrcDirs.toTypedArray())
}
}
override fun NamedDomainObjectContainer<KotlinSourceSet>.additionalConfigurations(project: Project) {
jvmMain.dependencies {
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:${project.kotlinStdlibVersion}")
}
}
private fun Project.configureJVMTarget() {
kotlin.jvm {
compilations.all {
it.compileKotlinTask.kotlinOptions {
jvmTarget = "1.8"
suppressWarnings = true
freeCompilerArgs = project.compilerArgs
}
}
}
}
companion object {
const val BENCHMARK_EXTENSION_NAME = "benchmark"
}
}
@@ -0,0 +1,103 @@
package org.jetbrains.kotlin.benchmark
import org.gradle.api.NamedDomainObjectContainer
import org.gradle.api.Project
import org.gradle.api.Task
import org.jetbrains.kotlin.*
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.mpp.Framework
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTargetPreset
import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType
import java.io.File
import javax.inject.Inject
import java.nio.file.Paths
import kotlin.reflect.KClass
enum class CodeSizeEntity { FRAMEWORK, EXECUTABLE }
open class SwiftBenchmarkExtension @Inject constructor(project: Project) : BenchmarkExtension(project) {
var swiftSources: List<String> = emptyList()
var useCodeSize: CodeSizeEntity = CodeSizeEntity.FRAMEWORK // use as code size metric framework size or executable
}
/**
* A plugin configuring a benchmark Kotlin/Native project.
*/
open class SwiftBenchmarkingPlugin : BenchmarkingPlugin() {
override fun Project.configureJvmJsonTask(jvmRun: Task): Task {
return tasks.create("jvmJsonReport") {
logger.info("JVM run is unsupported")
jvmRun.finalizedBy(it)
}
}
override fun Project.configureJvmTask(): Task {
return tasks.create("jvmRun") { task ->
task.doLast {
logger.info("JVM run is unsupported")
}
}
}
override val benchmarkExtensionClass: KClass<*>
get() = SwiftBenchmarkExtension::class
override val Project.benchmark: SwiftBenchmarkExtension
get() = extensions.getByName(benchmarkExtensionName) as SwiftBenchmarkExtension
override val benchmarkExtensionName: String = "swiftBenchmark"
override val Project.nativeExecutable: String
get() = Paths.get(buildDir.absolutePath, benchmark.applicationName).toString()
override val Project.nativeLinkTask: Task
get() = tasks.getByName("buildSwift")
private lateinit var framework: Framework
val nativeFrameworkName = "benchmark"
override fun NamedDomainObjectContainer<KotlinSourceSet>.configureSources(project: Project) {
project.benchmark.let {
commonMain.kotlin.srcDirs(*it.commonSrcDirs.toTypedArray())
nativeMain.kotlin.srcDirs(*(it.nativeSrcDirs).toTypedArray())
}
}
override fun Project.determinePreset(): KotlinNativeTargetPreset = kotlin.presets.macosX64 as KotlinNativeTargetPreset
override fun KotlinNativeTarget.configureNativeOutput(project: Project) {
binaries.framework(nativeFrameworkName, listOf(RELEASE)) {
// Specify settings configured by a user in the benchmark extension.
project.afterEvaluate {
linkerOpts.addAll(project.benchmark.linkerOpts)
}
}
}
override fun Project.configureExtraTasks() {
val nativeTarget = kotlin.targets.getByName(NATIVE_TARGET_NAME) as KotlinNativeTarget
// Build executable from swift code.
framework = nativeTarget.binaries.getFramework(nativeFrameworkName, NativeBuildType.RELEASE)
val buildSwift = tasks.create("buildSwift") { task ->
task.dependsOn(framework.linkTaskName)
task.doLast {
val frameworkParentDirPath = framework.outputDirectory.absolutePath
val options = listOf("-Xlinker", "-rpath", "-Xlinker", frameworkParentDirPath, "-F", frameworkParentDirPath)
compileSwift(project, nativeTarget.konanTarget, benchmark.swiftSources, options,
Paths.get(buildDir.absolutePath, benchmark.applicationName), false)
}
}
}
override fun Project.collectCodeSize(applicationName: String) =
getCodeSizeBenchmark(applicationName,
if (benchmark.useCodeSize == CodeSizeEntity.FRAMEWORK)
File("${framework.outputFile.absolutePath}/$nativeFrameworkName").canonicalPath
else
nativeExecutable
)
override fun Project.getCompilerFlags(nativeTarget: KotlinNativeTarget) =
listOf<String>()
}
@@ -56,7 +56,6 @@ abstract class Launcher {
} else {
printStderr("$message")
}
}
}
}
-149
View File
@@ -1,149 +0,0 @@
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 {
apply from: "$rootProject.projectDir/gradle/kotlinGradlePlugin.gradle"
repositories {
maven {
url 'https://cache-redirector.jetbrains.com/jcenter'
}
}
}
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"
implementation project(":endorsedLibraries:kotlinx.cli")
}
kotlin.srcDir "src"
kotlin.srcDir "../shared/src/main/kotlin"
kotlin.srcDir "$toolsPath/benchmarks/shared/src/main/kotlin"
}
macosMain {
dependsOn commonMain
kotlin.srcDir "../shared/src/main/kotlin-native/common"
kotlin.srcDir "../shared/src/main/kotlin-native/posix"
// Exclude kotlinx.cli added in commonMain dependencies and inherited by macosMain.
configurations.getByName(implementationConfigurationName) {
exclude module: "kotlinx.cli"
}
}
}
macosX64("macos") {
compilations.main.kotlinOptions.freeCompilerArgs = (project.hasProperty('compilerArgs') ? compilerArgs.split() : [])
compilations.main.enableEndorsedLibs = true
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'
+20
View File
@@ -0,0 +1,20 @@
/*
* 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.
*/
plugins {
id("swift-benchmarking")
}
val toolsPath = "../../tools"
swiftBenchmark {
applicationName = "swiftInterop"
commonSrcDirs = listOf("$toolsPath/benchmarks/shared/src/main/kotlin", "src", "../shared/src/main/kotlin")
nativeSrcDirs = listOf("../shared/src/main/kotlin-native/common", "../shared/src/main/kotlin-native/posix")
swiftSources = listOf("$projectDir/swiftSrc/benchmarks.swift", "$projectDir/swiftSrc/main.swift")
compileTasks = listOf("compileKotlinNative", "linkBenchmarkReleaseFrameworkNative")
dependencies.common(project(":endorsedLibraries:kotlinx.cli"))
}
@@ -4,7 +4,7 @@
*/
import Foundation
import CityMap
import benchmark
class SimpleCost: Cost {
let value: Int
+3 -4
View File
@@ -4,7 +4,7 @@
*/
import Foundation
import CityMap
import benchmark
var runner = BenchmarksRunner()
let args = KotlinArray(size: Int32(CommandLine.arguments.count - 1), init: {index in
@@ -14,9 +14,7 @@ let args = KotlinArray(size: Int32(CommandLine.arguments.count - 1), init: {inde
let companion = BenchmarkEntryWithInit.Companion()
var swiftLauncher = SwiftLauncher()
runner.runBenchmarks(args: args, run: { (arguments: BenchmarkArguments) -> [BenchmarkResult] in
swiftLauncher.add(name: "createMultigraphOfInt", benchmark: companion.create(ctor: { return SwiftInteropBenchmarks() },
swiftLauncher.add(name: "createMultigraphOfInt", benchmark: companion.create(ctor: { return SwiftInteropBenchmarks() },
lambda: { ($0 as! SwiftInteropBenchmarks).createMultigraphOfInt() }))
swiftLauncher.add(name: "fillCityMap", benchmark: companion.create(ctor: { return SwiftInteropBenchmarks() },
lambda: { ($0 as! SwiftInteropBenchmarks).fillCityMap() }))
@@ -38,6 +36,7 @@ runner.runBenchmarks(args: args, run: { (arguments: BenchmarkArguments) -> [Benc
lambda: { ($0 as! SwiftInteropBenchmarks).stringInterop() }))
swiftLauncher.add(name: "simpleFunction", benchmark: companion.create(ctor: { return SwiftInteropBenchmarks() },
lambda: { ($0 as! SwiftInteropBenchmarks).simpleFunction() }))
runner.runBenchmarks(args: args, run: { (arguments: BenchmarkArguments) -> [BenchmarkResult] in
if arguments is BaseBenchmarkArguments {
let argumentsList: BaseBenchmarkArguments = arguments as! BaseBenchmarkArguments
return swiftLauncher.launch(numWarmIterations: argumentsList.warmup,