[K/N] Benchmarks on weak references

Merge-request: KT-MR-7575
Merged-by: Alexander Shabalin <Alexander.Shabalin@jetbrains.com>
This commit is contained in:
Alexander Shabalin
2022-11-15 13:22:15 +00:00
committed by Space Team
parent ab590e1279
commit a31c3f979b
18 changed files with 253 additions and 7 deletions
@@ -17,7 +17,11 @@ swiftBenchmark {
applicationName = "swiftInterop"
commonSrcDirs = listOf("$toolsPath/benchmarks/shared/src/main/kotlin/report", "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")
swiftSources = listOf(
"$projectDir/swiftSrc/benchmarks.swift",
"$projectDir/swiftSrc/main.swift",
"$projectDir/swiftSrc/weakRefBenchmarks.swift",
)
compileTasks = listOf("compileKotlinNative", "linkBenchmark${buildType.name.toLowerCase().capitalize()}FrameworkNative")
cleanBeforeRunTask = "compileKotlinNative"
}
}
@@ -0,0 +1,11 @@
/*
* Copyright 2010-2022 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.gc
import kotlin.native.internal.GC
fun collect() = GC.collect()
fun schedule() = GC.schedule()
@@ -0,0 +1,10 @@
/*
* Copyright 2010-2022 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.benchmarksLauncher.Random
class KotlinData(var x: Int = Random.nextInt())
@@ -36,6 +36,28 @@ swiftLauncher.addBase(name: "createMultigraphOfInt", benchmark: companion.create
lambda: { ($0 as! SwiftInteropBenchmarks).stringInterop() }))
swiftLauncher.addBase(name: "simpleFunction", benchmark: companion.create(ctor: { return SwiftInteropBenchmarks() },
lambda: { ($0 as! SwiftInteropBenchmarks).simpleFunction() }))
swiftLauncher.addBase(
name: "WeakRefBenchmark.aliveReference",
benchmark: BenchmarkEntryWithInit.companion.create(
ctor: { return WeakRefBenchmark() },
lambda: { ($0 as! WeakRefBenchmark).aliveReference() }
)
)
swiftLauncher.addBase(
name: "WeakRefBenchmark.deadReference",
benchmark: BenchmarkEntryWithInit.companion.create(
ctor: { return WeakRefBenchmark() },
lambda: { ($0 as! WeakRefBenchmark).deadReference() }
)
)
swiftLauncher.addBase(
name: "WeakRefBenchmark.dyingReference",
benchmark: BenchmarkEntryWithInit.companion.create(
ctor: { return WeakRefBenchmark() },
lambda: { ($0 as! WeakRefBenchmark).dyingReference() }
)
)
runner.runBenchmarks(args: args, run: { (arguments: BenchmarkArguments) -> [BenchmarkResult] in
if arguments is BaseBenchmarkArguments {
let argumentsList: BaseBenchmarkArguments = arguments as! BaseBenchmarkArguments
@@ -50,4 +72,4 @@ runner.runBenchmarks(args: args, run: { (arguments: BenchmarkArguments) -> [Benc
return runner.parse(args: args, benchmarksListAction: { (baseOnly: KotlinBoolean) in swiftLauncher.benchmarksListAction(baseOnly: baseOnly.boolValue) }) },
collect: { (benchmarks: [BenchmarkResult], arguments: BenchmarkArguments) -> Void in
runner.collect(results: benchmarks, arguments: arguments)
}, benchmarksListAction: { (baseOnly: KotlinBoolean) in swiftLauncher.benchmarksListAction(baseOnly: baseOnly.boolValue) })
}, benchmarksListAction: { (baseOnly: KotlinBoolean) in swiftLauncher.benchmarksListAction(baseOnly: baseOnly.boolValue) })
@@ -0,0 +1,81 @@
/*
* Copyright 2010-2022 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 benchmark
private let REPEAT_COUNT = 10000
private let REFERENCES_COUNT = 3
private class ReferenceWrapper {
private weak var weakRef: KotlinData?
private var strongRef: KotlinData?
init() {
let data = KotlinData(x: Int32.random(in: 1 ... 1000))
self.strongRef = data
self.weakRef = data
}
// This function must not be inlined. We must ensure `weakRef` is accessed at each loop iteration.
@inline(never) func value() -> Int32 {
let ref: KotlinData? = self.weakRef
if ref == nil {
return 0
}
return ref!.x
}
func dispose() {
self.strongRef = nil
}
func stress() -> Int32 {
var counter: Int32 = 0
for _ in 1...REPEAT_COUNT {
counter += self.value()
}
return counter
}
}
private func deadReferenceWrapper() -> ReferenceWrapper {
let ref = ReferenceWrapper()
ref.dispose()
GCKt.collect()
return ref
}
class WeakRefBenchmark {
private let aliveRef = ReferenceWrapper()
private let deadRef = deadReferenceWrapper()
// Access alive reference.
func aliveReference() {
let counter = aliveRef.stress()
if counter == 0 {
fatalError()
}
}
// Access dead reference.
func deadReference() {
let counter = deadRef.stress()
if counter != 0 {
fatalError()
}
}
// Access reference that is nulled out in the middle.
func dyingReference() {
let ref = ReferenceWrapper()
ref.dispose()
GCKt.schedule()
let counter = ref.stress()
Blackhole.companion.consume(value: counter)
}
}