Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid using ExperimentalTime API #1330

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
39 changes: 22 additions & 17 deletions core/koin-core/src/commonMain/kotlin/org/koin/core/time/Measure.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,28 +15,33 @@
*/
package org.koin.core.time

import kotlin.time.DurationUnit
import kotlin.time.ExperimentalTime
import kotlin.time.measureTime
import kotlin.time.measureTimedValue


/**
* Measure functions
*
* @author Arnaud Giuliani
* Executes the [code] and returns the duration of execution in milliseconds.
*/
// TODO: Use kotlin.time API when it becomes stable
internal fun measureDuration(code: () -> Unit): Double {
val timeSource = getTimeSource()

val start = timeSource.mark()
code()
val end = timeSource.mark()

@OptIn(ExperimentalTime::class)
fun measureDuration(code: () -> Unit): Double {
return measureTime(code).toDouble(DurationUnit.MILLISECONDS)
return (end - start) / 1_000_000.0
}

/**
* Measure code execution and get result
* Executes the [code] and returns a pair of values - the result of the function execution
* and the duration of execution in milliseconds.
*/
@OptIn(ExperimentalTime::class)
fun <T> measureDurationForResult(code: () -> T): Pair<T, Double> {
val result = measureTimedValue(code)
return Pair(result.value, result.duration.toDouble(DurationUnit.MILLISECONDS))
// TODO: Use kotlin.time API when it becomes stable
internal fun <T> measureDurationForResult(code: () -> T): Pair<T, Double> {
val timeSource = getTimeSource()

val start = timeSource.mark()
val result = code()
val end = timeSource.mark()

val duration = (end - start) / 1_000_000.0

return Pair(result, duration)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.koin.core.time

internal abstract class TimeSource {
/**
* Marks a point in time on this time source in nanoseconds.
*/
abstract fun mark(): Long
}

internal expect fun getTimeSource(): TimeSource
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.koin.core.time

import kotlin.system.getTimeNanos

internal actual fun getTimeSource() = object: TimeSource() {
override fun mark(): Long {
return getTimeNanos()
}
}
45 changes: 45 additions & 0 deletions core/koin-core/src/jsMain/kotlin/org/koin/core/time/TimeSource.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package org.koin.core.time

import kotlin.js.Date
import kotlin.math.roundToLong

internal actual fun getTimeSource(): TimeSource {
val isNode = js(
"typeof process !== 'undefined' " +
"&& process.versions " +
"&& !!process.versions.node"
) as Boolean

return if (isNode) {
NodeJsHrTimeSource()
} else {
val isPerformanceNowSupported = js("self.performance && !!self.performance.now") as Boolean
if (isPerformanceNowSupported) {
PerformanceNowTimeSource()
} else {
DateNowTimeSource()
}
}
}

// https://nodejs.org/api/process.html#processhrtimetime
private class NodeJsHrTimeSource : TimeSource() {
override fun mark(): Long {
val (seconds, nanos) = js("process.hrtime()") as Array<Double>
return (seconds * 1_000_000_000 + nanos).roundToLong()
}
}

// https://developer.mozilla.org/en-US/docs/Web/API/Performance/now
private class PerformanceNowTimeSource : TimeSource() {
override fun mark(): Long {
return (js("self.performance.now()") as Double * 1_000_000).roundToLong()
}
}

// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now
private class DateNowTimeSource : TimeSource() {
override fun mark(): Long {
return (Date.now() * 1_000_000).roundToLong()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package org.koin.core.time

internal actual fun getTimeSource() = object: TimeSource() {
override fun mark(): Long {
return System.nanoTime()
}
}
4 changes: 4 additions & 0 deletions examples/android-perfs/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}

kotlinOptions {
freeCompilerArgs += "-Xopt-in=kotlin.time.ExperimentalTime"
}
}

dependencies {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.async
import kotlinx.coroutines.runBlocking
import org.koin.core.time.measureDurationForResult
import org.koin.dsl.koinApplication
import org.koin.perfs.Perfs
import org.koin.perfs.perfModule400
//import org.koin.perfs.perfModule400
import org.koin.perfs.perfModule400Ext
//import org.koin.perfs.perfModule400Ext
import org.koin.sample.android.R
import kotlin.time.DurationUnit
import kotlin.time.measureTime
import kotlin.time.measureTimedValue

class MainActivity : AppCompatActivity() {

Expand All @@ -38,23 +39,27 @@ class MainActivity : AppCompatActivity() {
}

fun runPerf(count: Int): Pair<Double, Double> {
val (app, duration) = measureDurationForResult {
val (app, duration) = measureTimedValue {
koinApplication {
modules(perfModule400())
}
}
println("[$count] started in $duration ms")

val durationInMillis = duration.toDouble(DurationUnit.MILLISECONDS)
println("[$count] started in $durationInMillis ms")

val koin = app.koin

val (_, executionDuration) = measureDurationForResult {
val executionDuration = measureTime {
koin.get<Perfs.A27>()
koin.get<Perfs.A31>()
koin.get<Perfs.A12>()
koin.get<Perfs.A42>()
}
println("[$count] measured executed in $executionDuration ms")
val executionDurationInMillis = executionDuration.toDouble(DurationUnit.MILLISECONDS)

println("[$count] measured executed in $executionDurationInMillis ms")
app.close()
return Pair(duration, executionDuration)
return Pair(durationInMillis, executionDurationInMillis)
}
}
4 changes: 4 additions & 0 deletions examples/coffee-maker/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ buildscript {
apply plugin: 'kotlin'
//apply plugin: 'koin'

compileKotlin {
kotlinOptions.freeCompilerArgs += "-Xopt-in=kotlin.time.ExperimentalTime"
}

archivesBaseName = 'example-coffee-maker'

dependencies {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
import org.koin.core.context.startKoin
import org.koin.core.logger.Level
import org.koin.core.time.measureDuration
import kotlin.time.DurationUnit
import kotlin.time.measureTime

class CoffeeApp : KoinComponent {
val maker: CoffeeMaker by inject()
Expand All @@ -22,8 +23,9 @@ fun main() {
}
}

fun measureDuration(msg : String, code: () -> Unit): Double {
val duration = measureDuration(code)
println("$msg in $duration ms")
return duration
fun measureDuration(msg : String, code: () -> Unit) {
val duration = measureTime(code)
val durationInMillis = duration.toDouble(DurationUnit.MILLISECONDS)

println("$msg in $durationInMillis ms")
}