How do I measure elapsed time for benchmarking in EK9?

← Date, Time, and Duration · Ref: Q544

Use SystemClock().millisecond() before and after the code section, then subtract to get elapsed Millisecond.

BASIC TIMING PATTERN

  startMs <- SystemClock().millisecond()
  // ... code to measure ...
  endMs <- SystemClock().millisecond()
  elapsed <- endMs - startMs
  stdout.println(`Elapsed: ${elapsed}`)

The result is a typed Millisecond value, not a raw integer. You can convert it to Duration with .duration() or get the raw value.

BUILT-IN PROFILING FLAGS

EK9 also has compiler-level profiling:

  ek9 -P program.ek9 runs with profiling enabled
  ek9 -Pf program.ek9 profiles with full detail

The compiler instruments the code automatically. For micro-benchmarks, manual SystemClock timing gives you control over exactly what is measured.

MILLISECOND ARITHMETIC

You can accumulate timing results:

  totalMs <- 0ms
  totalMs += elapsed

Or compute averages:

  averageMs <- totalMs / iterations

CONVERT TO DURATION

  elapsed.duration() converts to Duration for display in hours/minutes/seconds format.

See Q41 for Millisecond type details. See Q543 for Unix timestamps. See Q322 for the profiling system. See Q631 for benchmarking two approaches.

Example

defines module qa.elapsed.time.benchmarking

  defines program
    ElapsedTimeBenchmarkingDemo()
      stdout <- Stdout()

      // Basic timing pattern
      startMs <- SystemClock().millisecond()

      // Simulate work with a loop
      counter <- 0
      for i in 1 ... 1000
        counter += i

      endMs <- SystemClock().millisecond()
      elapsed <- endMs - startMs
      stdout.println(`Loop elapsed: ${elapsed}`)
      stdout.println(`Counter: ${counter}`)

      // Convert to Duration
      asDuration <- elapsed.duration()
      stdout.println(`As Duration: ${asDuration}`)

      // Accumulate multiple measurements
      totalMs <- 0ms
      for run in 1 ... 3
        runStart <- SystemClock().millisecond()
        sum <- 0
        for j in 1 ... 500
          sum += j
        runEnd <- SystemClock().millisecond()
        runElapsed <- runEnd - runStart
        totalMs += runElapsed
        stdout.println(`Run ${run}: ${runElapsed}`)

      stdout.println(`Total: ${totalMs}`)

      // Millisecond comparison for thresholds
      threshold <- 1000ms
      if totalMs < threshold
        stdout.println("Fast enough")
      else
        stdout.println("Too slow")

Common mistakes

E50001 — Renaming the variable means later references to 'elapsed' become unresolved, triggering E50001. See ek9 -h E50001 for details.

Incorrect:

elapsedXYZ <- endMs - startMs

Correct:

elapsed <- endMs - startMs

E50001 — EK9 uses SystemClock().millisecond(), not static Java-style methods. SystemClock is instantiated then millisecond() is called on it. Triggers E50001 — method not resolved. See ek9 -h SystemClock for the full API.

Incorrect:

startMs <- SystemClock.currentTimeMillis()

Correct:

startMs <- SystemClock().millisecond()
Other ways to ask this
  • How do I time how long something takes in EK9?
  • How do I use SystemClock for performance measurement?
  • How do I profile code execution time in EK9?

Coming from another language?

Java: System.nanoTime() for benchmarking (not currentTimeMillis which has clock adjustment issues). Python: time.perf_counter() or timeit module. JavaScript: performance.now() for high-resolution timing. Go: time.Now() with time.Since(). Rust: std::time::Instant::now() with elapsed(). EK9: SystemClock().millisecond() with typed subtraction, built-in -P profiling flag.

Keywords: benchmark, profile, performance, systemclock, date, time, elapsed, timing, timezone, millisecond, measure, duration