Implemented Stopwatch
This commit is contained in:
parent
f4d8b09260
commit
7e11a77def
|
@ -16,6 +16,8 @@ expect class Date(millisSinceEpoch: Long) {
|
||||||
|
|
||||||
val today: Date
|
val today: Date
|
||||||
|
|
||||||
|
val nanoSecondsSinceEpoch: Long
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,170 @@
|
||||||
|
package net.dankito.utils.multiplatform
|
||||||
|
|
||||||
|
import net.dankito.utils.multiplatform.log.Logger
|
||||||
|
import net.dankito.utils.multiplatform.log.LoggerFactory
|
||||||
|
|
||||||
|
|
||||||
|
open class Stopwatch(createStarted: Boolean = true) {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val log = LoggerFactory.getLogger(Stopwatch::class)
|
||||||
|
|
||||||
|
fun measureDuration(task: () -> Unit): Long {
|
||||||
|
return measureDuration(Stopwatch(), task)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun measureDuration(stopwatch: Stopwatch, task: () -> Unit): Long {
|
||||||
|
task()
|
||||||
|
|
||||||
|
return stopwatch.stop()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> logDuration(loggedAction: String, task: () -> T): T {
|
||||||
|
return logDuration(loggedAction, log, task)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> logDuration(loggedAction: String, logger: Logger, task: () -> T): T {
|
||||||
|
val stopwatch = Stopwatch()
|
||||||
|
|
||||||
|
val result = task()
|
||||||
|
|
||||||
|
stopwatch.stopAndLog(loggedAction, logger)
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
suspend fun measureDurationSuspendable(task: suspend () -> Unit): Long {
|
||||||
|
val stopwatch = Stopwatch()
|
||||||
|
|
||||||
|
task()
|
||||||
|
|
||||||
|
return stopwatch.stop()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun <T> logDurationSuspendable(loggedAction: String, task: suspend () -> T): T {
|
||||||
|
return logDurationSuspendable(loggedAction, log, task)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun <T> logDurationSuspendable(loggedAction: String, logger: Logger, task: suspend () -> T): T {
|
||||||
|
val stopwatch = Stopwatch()
|
||||||
|
|
||||||
|
val result = task()
|
||||||
|
|
||||||
|
stopwatch.stopAndLog(loggedAction, logger)
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
constructor() : this(true)
|
||||||
|
|
||||||
|
|
||||||
|
var isRunning = false
|
||||||
|
protected set
|
||||||
|
|
||||||
|
var startedAt = 0L
|
||||||
|
protected set
|
||||||
|
|
||||||
|
var elapsedNanos = 0L
|
||||||
|
protected set
|
||||||
|
|
||||||
|
|
||||||
|
init {
|
||||||
|
if (createStarted) {
|
||||||
|
start()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
open fun getCurrentTimeNanoSeconds(): Long {
|
||||||
|
return Date.nanoSecondsSinceEpoch
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun start() {
|
||||||
|
if (isRunning == false) {
|
||||||
|
startedAt = getCurrentTimeNanoSeconds()
|
||||||
|
|
||||||
|
isRunning = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun stop(): Long {
|
||||||
|
if (isRunning) {
|
||||||
|
val stoppedAt = getCurrentTimeNanoSeconds()
|
||||||
|
|
||||||
|
isRunning = false
|
||||||
|
elapsedNanos = stoppedAt - startedAt
|
||||||
|
}
|
||||||
|
|
||||||
|
return elapsedNanos
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun stopAndPrint(): String {
|
||||||
|
stop()
|
||||||
|
|
||||||
|
return formatElapsedTime()
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun stopAndLog(loggedAction: String): Long {
|
||||||
|
return stopAndLog(loggedAction, log)
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun stopAndLog(loggedAction: String, logger: Logger): Long {
|
||||||
|
stop()
|
||||||
|
|
||||||
|
logElapsedTime(loggedAction, logger)
|
||||||
|
|
||||||
|
return elapsedNanos
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// open fun elapsed(desiredUnit: TimeUnit): Long {
|
||||||
|
// return desiredUnit.convert(elapsedNanos, TimeUnit.NANOSECONDS)
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
open fun formatElapsedTime(): String {
|
||||||
|
return formatElapsedTime(elapsedNanos)
|
||||||
|
}
|
||||||
|
|
||||||
|
protected open fun formatElapsedTime(elapsedNanos: Long): String {
|
||||||
|
val durationMicroseconds = elapsedNanos / 1000
|
||||||
|
|
||||||
|
val durationMillis = durationMicroseconds / 1000
|
||||||
|
val millis = durationMillis % 1000
|
||||||
|
|
||||||
|
val durationSeconds = durationMillis / 1000
|
||||||
|
val seconds = durationSeconds % 60
|
||||||
|
|
||||||
|
val minutes = durationSeconds / 60
|
||||||
|
|
||||||
|
return if (minutes > 0) {
|
||||||
|
StringHelper.format("%02d:%02d.%03d min", minutes, seconds, millis)
|
||||||
|
}
|
||||||
|
else if (seconds > 0) {
|
||||||
|
StringHelper.format("%02d.%03d s", seconds, millis)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
StringHelper.format("%02d.%03d ms", millis, (durationMicroseconds % 1000))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun logElapsedTime(loggedAction: String, logger: Logger) {
|
||||||
|
val formattedElapsedTime = formatElapsedTime()
|
||||||
|
|
||||||
|
logger.info("$loggedAction took $formattedElapsedTime")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
if (isRunning) {
|
||||||
|
val elapsedNanos = getCurrentTimeNanoSeconds() - startedAt
|
||||||
|
return "Running, ${formatElapsedTime(elapsedNanos)} elapsed"
|
||||||
|
}
|
||||||
|
|
||||||
|
return "Stopped, ${formatElapsedTime()} elapsed"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
package net.dankito.utils.multiplatform
|
||||||
|
|
||||||
|
import kotlin.String
|
||||||
|
|
||||||
|
|
||||||
|
expect class StringHelper {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
fun format(format: String, vararg args: Any?): String
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
package net.dankito.utils.multiplatform
|
package net.dankito.utils.multiplatform
|
||||||
|
|
||||||
|
import platform.CoreFoundation.*
|
||||||
import platform.Foundation.*
|
import platform.Foundation.*
|
||||||
|
|
||||||
|
|
||||||
|
@ -43,6 +44,9 @@ actual class Date(val date: NSDate) { // cannot subclass NSDate as it's a class
|
||||||
return Date(from(now.year(), now.monthInt(), now.day()))
|
return Date(from(now.year(), now.monthInt(), now.day()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
actual val nanoSecondsSinceEpoch: Long
|
||||||
|
get() = CFAbsoluteTimeGetCurrent().toLong() * 1000
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
package net.dankito.utils.multiplatform
|
||||||
|
|
||||||
|
import kotlin.String
|
||||||
|
import platform.Foundation.*
|
||||||
|
|
||||||
|
|
||||||
|
actual class StringHelper {
|
||||||
|
|
||||||
|
actual companion object {
|
||||||
|
|
||||||
|
actual fun format(format: String, vararg args: Any?): String {
|
||||||
|
val adjustedFormat = format.replace("%s", "%@") // Objective-C uses %@ for strings // TODO: also replace %$1s, ...
|
||||||
|
|
||||||
|
// return NSString.stringWithFormat("%@ %@ %d", "один" as NSString, "two" as NSString, 3)
|
||||||
|
//return NSString.stringWithFormat(adjustedFormat, args.firstOrNull()) // spread operator is not supported for varadic functions, seehttps://github.com/JetBrains/kotlin-native/issues/1834
|
||||||
|
|
||||||
|
// as spread operator is not supported for varadic functions tried to pass arguments one by one, but didn't work either
|
||||||
|
return when (args.size) {
|
||||||
|
0 -> format
|
||||||
|
1 -> format(adjustedFormat, args.first())
|
||||||
|
2 -> format(adjustedFormat, args.first(), args.get(2))
|
||||||
|
else -> format(adjustedFormat, args.first(), args.get(2), args.get(3))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun format(format: String, arg1: Any): String {
|
||||||
|
return NSString.stringWithFormat(format, arg1 as? NSString ?: arg1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun format(format: String, arg1: Any, arg2: Any): String {
|
||||||
|
return NSString.stringWithFormat(format, arg1 as? NSString ?: arg1, arg2 as? NSString ?: arg2)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun format(format: String, arg1: Any, arg2: Any, arg3: Any): String {
|
||||||
|
return NSString.stringWithFormat(format, arg1 as? NSString ?: arg1, arg2 as? NSString ?: arg2, arg3 as? NSString ?: arg3)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -23,6 +23,9 @@ actual class Date actual constructor(millisSinceEpoch: Long) : java.util.Date(mi
|
||||||
return Date(today.time.time)
|
return Date(today.time.time)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
actual val nanoSecondsSinceEpoch: Long
|
||||||
|
get() = System.nanoTime()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
package net.dankito.utils.multiplatform
|
||||||
|
|
||||||
|
import kotlin.String
|
||||||
|
|
||||||
|
|
||||||
|
actual class StringHelper {
|
||||||
|
|
||||||
|
actual companion object {
|
||||||
|
|
||||||
|
actual fun format(format: String, vararg args: Any?): String {
|
||||||
|
return String.format(format, *args)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue