You want to time many small operations and aggregate their durations (e.g., total and average per call). Show how measureTimedValue and Duration arithmetic support this, and what pitfalls to avoid.
answer
- measureTimedValue keeps value + duration per call
- Duration supports +, /Int, /Double, comparison, ratio
- total / n -> average Duration; Duration.ZERO as fold seed
- Stay in Duration; convert to ms only at the end
- Hot loops: time a batch or use JMH; clock reads cost
basics
~20 sWrap each operation in measureTimedValue to get its result and time, then add the durations together. Duration supports +, division by a number, and comparison, so totals and averages are easy. Avoid calling these in extremely hot inner loops where even small overhead matters.
solid answer
~50 smeasureTimedValue { } returns a TimedValue<T>, so you keep each result while accumulating its duration. Duration is a value type with operators: you can sum durations (d1 + d2, or sum the list), divide a Duration by an Int/Double to get an average (total / n), multiply, and compare them, plus format with toString(unit) or inWholeMilliseconds. A common pattern: collect each TimedValue, fold the durations into a total, divide by count for the mean. Pitfalls: (1) accumulating Duration is fine and precise, but converting to Long ms too early loses sub-ms precision; (2) in extremely hot loops the monotonic clock read has nonzero cost and can dominate the measured work — measure at a coarser granularity or use JMH; (3) measureTimedValue retains every value, so don't hold large results if you only need timing — use measureTime there; (4) Duration can be negative in arithmetic, so guard if you subtract.
code
kotlin · 9 linesimport kotlin.time.measureTimedValue
import kotlin.time.Duration
import kotlin.time.Duration.Companion.ZERO
val samples = (1..100).map { measureTimedValue { work(it) } }
val total: Duration = samples.fold(ZERO) { acc, tv -> acc + tv.duration }
val avg: Duration = total / samples.size
val slowest: Duration = samples.maxOf { it.duration }
println("total=$total avg=$avg slowest=$slowest")go deeper
Can wrap a call and read its duration, but may not aggregate.
Sums durations with + and computes an average via division.
Uses the full Duration operator set, keeps precision, and batches in hot loops to avoid clock overhead.
Decides when these helpers suffice vs JMH, and sets conventions on precision and where to convert to display units.
## Goal Time N operations, keep their results, and report total + average duration. ## measureTimedValue keeps both ```kotlin import kotlin.time.measureTimedValue import kotlin.time.Duration import kotlin.time.Duration.Companion.ZERO val timed = items.map { item -> measureTimedValue { process(item) } // TimedValue<Result> } val results: List<Result> = timed.map { it.value } val total: Duration = timed.fold(ZERO) { acc, tv -> acc + tv.duration } val average: Duration = total / timed.size // Duration / Int -> Duration ``` ## Duration arithmetic (the enabling APIs) `Duration` is a value class supporting: - **addition/subtraction**: `d1 + d2`, `d1 - d2` - **scaling**: `d * 3`, `d / 4`, `d / count` (Int or Double) -> `Duration` - **ratio**: `d1 / d2` -> `Double` (how many times longer) - **comparison**: `d1 < d2`, `maxOf(a, b)` - **conversion/formatting**: `inWholeMilliseconds`, `inWholeMicroseconds`, `toString(DurationUnit.MILLISECONDS)` - constants: `Duration.ZERO` So averages, percentiles-ish maxima, and thresholds are natural: ```kotlin val slowest = timed.maxOf { it.duration } val overBudget = timed.count { it.duration > 50.milliseconds } ``` ## Pitfalls ### 1. Precision Keep accumulating as `Duration` (it holds high precision internally). Converting each sample to `Long` milliseconds before summing **truncates** sub-millisecond work to zero. Convert only at the end for display. ### 2. Clock-read overhead in hot loops Each `measureTimedValue` reads the monotonic clock twice. For nanosecond-scale operations in a tight loop, this overhead can rival the work itself, skewing results. Time a **batch** (`measureTime { repeat(1_000) { op() } }` then divide) or use **kotlinx-benchmark/JMH**. ### 3. Don't retain values you don't need `measureTimedValue` keeps every `value`. If you only need timing, use `measureTime` to avoid holding large results in memory. ### 4. Signed arithmetic `Duration` can be negative; if you subtract durations, guard against negatives where it would be nonsensical. ## Summary `measureTimedValue` + `Duration`'s operator-rich API make per-call timing aggregation clean. Mind precision (stay in Duration), clock-read overhead in hot paths, memory retention, and signedness.
- How do you compute an average Duration?Divide the summed Duration by the count: total / n, where n is an Int or Double. The result is a Duration, preserving sub-millisecond precision.
- Why prefer measureTime over measureTimedValue when aggregating only timings?measureTimedValue retains every result value; if you only need durations, measureTime avoids holding those values in memory.
saying these in an interview costs you the question
- Converting to Long ms per sample before summing (loses precision)
- Timing nanosecond ops one-by-one and ignoring clock-read overhead
- Thinking Duration can't be divided to get an average
- Holding large result objects via measureTimedValue when only timing is needed