All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.dankito.utils.Stopwatch.kt Maven / Gradle / Ivy

There is a newer version: 1.0.20
Show newest version
package net.dankito.utils

import org.slf4j.Logger
import org.slf4j.LoggerFactory
import java.util.concurrent.TimeUnit


open class Stopwatch @JvmOverloads constructor(createStarted: Boolean = true) {

	companion object {
		private val log = LoggerFactory.getLogger(Stopwatch::class.java)

		fun measureDuration(task: () -> Unit): Long {
			return measureDuration(Stopwatch(), task)
		}

		private fun measureDuration(stopwatch: Stopwatch, task: () -> Unit): Long {
			task()

			return stopwatch.stop()
		}

		fun  logDuration(loggedAction: String, task: () -> T): T {
			return logDuration(loggedAction, log, task)
		}

		fun  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  logDurationSuspendable(loggedAction: String, task: suspend () -> T): T {
			return logDurationSuspendable(loggedAction, log, task)
		}

		suspend fun  logDurationSuspendable(loggedAction: String, logger: Logger, task: suspend () -> T): T {
			val stopwatch = Stopwatch()

			val result = task()

			stopwatch.stopAndLog(loggedAction, logger)

			return result
		}
	}


	var isRunning = false
		protected set

	var startedAt = 0L
		protected set

	var elapsedNanos = 0L
		protected set


	init {
		if (createStarted) {
			start()
		}
	}


	open fun start() {
		if (isRunning == false) {
			startedAt = System.nanoTime()

			isRunning = true
		}
	}

	open fun stop(): Long {
		if (isRunning) {
			val stoppedAt = System.nanoTime()

			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) {
			String.format("%02d:%02d.%03d min", minutes, seconds, millis)
		}
		else if (seconds > 0) {
			String.format("%02d.%03d s", seconds, millis)
		}
		else {
			String.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 = System.nanoTime() - startedAt
			return "Running, ${formatElapsedTime(elapsedNanos)} elapsed"
		}

		return "Stopped, ${formatElapsedTime()} elapsed"
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy