如何记录clojure中函数调用的时间

How can I record time for function call in clojure

我是 Clojure 的新手。我正在使用 java 调用 Clojure 函数,我想记录特定行的 clojure 代码执行所花费的时间:

假设我的 clojure 函数是:

     (defn sampleFunction [sampleInput]
         (fun1 (fun2 sampleInput))

我正在从 java 调用上面的函数,其中 returns 一些字符串值,我想记录执行 fun2 所花费的时间。

我有另一个函数 logTime,它将传递给它的参数写入某个数据库:

      (defn logTime [time]
            .....
      )

我的问题是:如何修改我的 sampleFunction(..) 以调用 logTime 来记录执行 fun2 所花费的时间。

提前致谢。

我不完全确定你的代码的不同部分如何组合在一起并与 Java 互操作,但这里有一些可以按照你描述的方式工作。

要获取一段代码的执行时间,有一个核心函数叫做time。但是,这个函数不会 return 执行时间,它只是 prints 它...所以假设你想记录将那个时间存入数据库,我们需要编写一个宏来捕获 fun2 的 return 值以及执行所花费的时间:

(defmacro time-execution
  [& body]
  `(let [s# (new java.io.StringWriter)]
     (binding [*out* s#]
       (hash-map :return (time ~@body)
                 :time   (.replaceAll (str s#) "[^0-9\.]" "")))))

这个宏的作用是将标准输出绑定到 Java StringWriter,这样我们就可以用它来存储 time 函数打印的任何内容。为了 return fun2 的结果和执行所花费的时间,我们将这两个值打包在一个散列映射中(也可以是其他集合 - 我们稍后会解构它) .请注意,我们对其执行计时的代码包含在对 time 的调用中,因此我们触发了打印副作用并将其捕获在 s# 中。最后,.replaceAll 只是为了确保我们只提取实际数值(以毫秒为单位),因为 time 打印出 "Elapsed time: 0.014617 msecs".

形式的内容

将其合并到您的代码中,我们需要像这样重写 sampleFunction

(defn sampleFunction [sampleInput]
  (let [{:keys [return time]} (time-execution (fun2 sampleInput))]
    (logTime time)
    (fun1 return)))

我们简单地解构散列映射以访问 fun2 的 return 值和执行时间,然后我们使用 logTime 记录执行时间,最后我们通过在 fun2.

的 return 值上调用 fun1 来完成

tupelo.prof 如果您想捕获一个或多个函数的执行时间并在多次调用中累积它,那么库 tupelo.prof 为您提供了多种选择。一个例子:

(ns tst.demo.core
  (:use tupelo.core tupelo.test)
  (:require
    [tupelo.profile :as prof]))

(defn add2 [x y] (+ x y))
(prof/defnp fast [] (reduce add2 0 (range 10000)))
(prof/defnp slow [] (reduce add2 0 (range 10000000)))

(dotest
  (prof/timer-stats-reset)
  (dotimes [i 10000] (fast))
  (dotimes [i 10] (slow))
  (prof/print-profile-stats)
  )

结果:

--------------------------------------
   Clojure 1.10.2-alpha1    Java 14
--------------------------------------

Testing tst.demo.core

    ---------------------------------------------------------------------------------------------------
    Profile Stats:
       Samples       TOTAL        MEAN      SIGMA           ID
        10000        0.955     0.000096   0.000045   :tst.demo.core/fast                                                              
           10        0.905     0.090500   0.000965   :tst.demo.core/slow                                                              
    ---------------------------------------------------------------------------------------------------

如果您想要单个方法的详细计时,the Criterium library 就是您所需要的。从 quick-bench 函数开始。