Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Performance 此功能的评估时间为85纳秒和10秒(!?) 客观的_Performance_Clojure_Benchmarking_Read Eval Print Loop - Fatal编程技术网

Performance 此功能的评估时间为85纳秒和10秒(!?) 客观的

Performance 此功能的评估时间为85纳秒和10秒(!?) 客观的,performance,clojure,benchmarking,read-eval-print-loop,Performance,Clojure,Benchmarking,Read Eval Print Loop,我试图弄明白为什么我创建的函数,items-staged-f的计算时间既长又短 你说奇怪? 我说“奇怪”是因为: (时间(items-staged-f))产生1.313毫秒 (time(items-staged-f))第二次产生0.035毫秒(这并不奇怪,因为结果是一个延迟序列,必须已被记忆) 基准测试系统报告需要85.149767 ns(这并不奇怪) 然而 在REPL中实际评估(items-staged-f)所需的时间约为10秒。这甚至在它打印任何东西之前。我最初认为它可能需要这么长的时

我试图弄明白为什么我创建的函数,
items-staged-f
的计算时间既长又短

你说奇怪? 我说“奇怪”是因为:

  • (时间(items-staged-f))
    产生
    1.313毫秒
  • (time(items-staged-f))
    第二次产生
    0.035毫秒
    (这并不奇怪,因为结果是一个延迟序列,必须已被记忆)
  • 基准测试系统报告需要
    85.149767 ns
    (这并不奇怪)
然而

  • 在REPL中实际评估
    (items-staged-f)
    所需的时间约为10秒。这甚至在它打印任何东西之前。我最初认为它可能需要这么长的时间,因为它准备打印到REPL,因为它是一个长而复杂的数据结构(嵌套的映射和向量以惰性顺序排列),但奇怪的是,结果甚至要到10秒后才开始打印,而这(假设)需要85纳秒。可能是因为它在预先计算如何打印数据结构
  • (时间(最后一次(items-staged-f))
    产生
    10498.16毫秒
    (尽管这可能会在20秒左右变化),原因可能与上述相同
现在是代码。。。 功能
items-staged-f
的目标是可视化需要做什么,以便对会计数据库中的库存项目进行一些必要的更改

下面可以找到
items-staged-f
中引用的不熟悉功能

(defn items-staged-f []
  (let [items-0 (lazy-seq (items-staged :items))
        both-types? #(in? % (group+line-items))
        items-from-group #(get items-0 %)
        replace-subgroups
          (fn [[g-item l-items :as group]]
            (let [items-in-both
                    (->> l-items
                         (map :item)
                         (filter both-types?))]
              (->> (concat
                        (remove #(in? (:item %)  items-in-both) l-items)
                        (mapcat items-from-group items-in-both))
                   (into [])
                   (assoc group 1))))
        replaced (map replace-subgroups items-0)]
   replaced))
items-staged
是一个输出原始数据的函数,由
items-staged-f
操作<代码>(项目暂存:项目)输出带有字符串键(组项目)的地图,其值为地图矢量(子项目列表):

请注意,
items-staged-f
的输出在结构上几乎与
items-staged
的输出相同,只是它是一个延迟的向量序列,而不是具有哈希映射项的哈希映射,这是通过调用哈希映射上的
map
函数所期望的

in?
是检查对象是否在给定集合中的谓词。例如,
(在?1[1 2 3])
的计算结果为
true

组+行项目
是一个函数,它输出我希望消除的某些重复项目的延迟序列。例如,
(组+行项目)
的计算结果为:
(“428X”“41SF”“6998”“75D22”)

笔记 VisualVM 1.3.8表示clojure.lang.Reflector.getMethods()的时钟频率为28700毫秒(51.3%),clojure.lang.LineNumberingPushbackReader.read()的时钟频率为9000毫秒(16.2%),clojure.lang.RT.nthFrom()的时钟频率为7800毫秒(13.9%)

但是,当我在REPL中分别计算惰性序列
(nth items-staged-fn)
的每个元素时,只有clojure.lang.LineNumberingPushbackReader.read()会上升。调用以32的增量递增,这是惰性seq分块大小。其他方法/功能所用的时间可以忽略不计

另一个需要考虑的问题是,
items-staged
是一个最终从Excel文件(通过读取)中提取数据的函数。但是,Excel文件中的原始数据存储为var,因此这不应该成为问题,因为它在被存储之前只计算一次(我认为)


谢谢你的帮助

补遗
曾经我使用
doall
强制实现惰性序列(我认为该序列正在实现),Criterium现在说该函数需要
11.370356秒
来计算,不幸的是这是有意义的。重构后我将重新发布。

根据定义,惰性序列仅在需要时计算其元素。打印到REPL或请求
last
元素都会强制实现。对生成延迟序列的函数调用进行计时并不重要

(defn slow-and-lazy [] (map #(do (Thread/sleep 1000) (inc %)) (range 10)))

user=> (time (slow-and-lazy))
"Elapsed time: 0.837002 msecs"
(1 2 3 4 5 6 7 8 9 10) ; printed 10 seconds later

user=> (time (doall (slow-and-lazy)))
"Elapsed time: 10000.205709 msecs"
(1 2 3 4 5 6 7 8 9 10)
(time(slow and lazy))
的情况下,
slow and lazy
快速返回一个未实现的延迟序列,
time
完成,打印经过的时间,并将未实现的结果传递给REPL。然后,REPL尝试打印序列。为了做到这一点,它必须实现顺序



话虽如此,10秒对于一台计算机来说是永恒的,因此这确实值得检查/分析。我建议将代码重构为更小的自包含函数。特别是,数据应该作为参数传入。一旦你钉住瓶颈(时间用代码> DOALL < /代码>强制实现!),然后考虑发布一个新的问题。由于无法准确判断此代码发生了什么,或者
项目中的IO是否是真正的瓶颈,因此似乎仍有改进的余地。

感谢您的帮助。我没有意识到,
(时间(缓慢和懒惰))
会立即打印计时,但会实现打印计时的整个序列。我将重构代码并发布更新。@alexandergunnarson如果回答了直接的问题,您可以接受这个答案(在答案左边打勾)。然后,将发现的任何子问题作为新的单独问题发布。
(defn slow-and-lazy [] (map #(do (Thread/sleep 1000) (inc %)) (range 10)))

user=> (time (slow-and-lazy))
"Elapsed time: 0.837002 msecs"
(1 2 3 4 5 6 7 8 9 10) ; printed 10 seconds later

user=> (time (doall (slow-and-lazy)))
"Elapsed time: 10000.205709 msecs"
(1 2 3 4 5 6 7 8 9 10)