Nim 语言测量程序运行时间

298 阅读1分钟

Nim编程早茶

这一节,我们介绍如何使用 Nim 语言测量程序运行时间,也可以 nimble install timeit 来测试。

定义对象

我们使用 std/monotimes 中的 getMonoTime 来获取当前时间。用程序结束时间减去程序开始时间,得到程序运行时间。

import std/monotimes
import times, strformat


type
  TimeInt* = int
  Moment* = ref object
    minutes*: TimeInt
    seconds*: TimeInt
    milliSeconds*: TimeInt
    microSeconds*: TimeInt
    nanoSeconds*: float
  Monit* = ref object
    name*: string
    begin*: MonoTime
    stop*: MonoTime

格式化测量时间

getMonoTime 函数返回给我们的时间单位为纳秒,我们要将纳秒表示为分-秒-毫秒-微秒-纳秒的形式,然后转化为字符串形式。类似这样,[19ms 952μs 700.00ns]。

proc `$`*(moment: Moment): string =
  result &= "["
  if moment.minutes != 0:
    result &= fmt"{moment.minutes}m "
  if moment.seconds != 0:
    result &= fmt"{moment.seconds}s "
  if moment.milliSeconds != 0:
    result &= fmt"{moment.milliSeconds}ms "
  if moment.microSeconds != 0:
    result &= fmt"{moment.microSeconds}μs "
  result &= fmt"{moment.nanoSeconds:.2f}ns"
  result &= "]"

proc toTime(time: int64): Moment =
  var moment = new Moment
  let nanoTime = TimeInt(time)
  moment.nanoSeconds = float(nanoTime mod 1_000)
  moment.microSeconds = (nanoTime div 1_000) mod 1_000
  moment.milliSeconds = (nanoTime div 1_000_000) mod 1_000
  moment.seconds = (nanoTime div 1_000_000_000) mod 1_000
  moment.minutes = (nanoTime div 1_000_000_000 div 60) mod 1_000
  moment

主程序

程序结束时间减去程序开始时间。

proc monit*(name = "monit"): Monit =
  Monit(name: name)

proc start*(self: Monit) =
  self.begin = getMonoTime()

proc finish*(self: Monit) =
  self.stop = getMonoTime()
  let lasting = self.stop - self.begin
  echo self.name & " -> " & $lasting.inNanoseconds.toTime

template timeOnce*(name: string = "monit-once", code: untyped) =
  var m = monit(name)
  m.start()
  code
  m.finish()

测试程序

timeOnce("test"):
  import os
  var
    a = 12
    b = 7
  sleep(a + b)
  for i in 1 .. 100:
    discard

输出

test -> [19ms 952μs 700.00ns]