我想做一些实时图形渲染,并尝试对每帧每个像素进行多次计算。然后我很快注意到这非常慢并且从最基础开始:我能以多快的速度循环所有像素?
我发现 dotimes 相当快,但是当我在 REPL 中执行此操作时,速度非常慢:
user=> (dotimes [_ 10] (time (dotimes [_ 1e7] (+ 1 1))))
"Elapsed time: 409.177477 msecs"
"Elapsed time: 417.755502 msecs"
"Elapsed time: 418.939182 msecs"
"Elapsed time: 420.131575 msecs"
"Elapsed time: 419.83529 msecs"
"Elapsed time: 417.612003 msecs"
"Elapsed time: 420.749229 msecs"
"Elapsed time: 418.918554 msecs"
"Elapsed time: 414.403957 msecs"
"Elapsed time: 417.729624 msecs"
nil
user=>
然后我将其放入 Leiningen 项目中。当我做“lein run”时,速度也一样慢。但是当我创建 uberjar 并使用 java 命令运行它时,速度要快得多:
% java -jar target/looping-0.1.0-SNAPSHOT-standalone.jar
"Elapsed time: 122.006758 msecs"
"Elapsed time: 3.667653 msecs"
"Elapsed time: 3.60515 msecs"
"Elapsed time: 4.008436 msecs"
"Elapsed time: 3.961558 msecs"
"Elapsed time: 3.60212 msecs"
"Elapsed time: 3.592532 msecs"
"Elapsed time: 4.573949 msecs"
"Elapsed time: 3.959568 msecs"
"Elapsed time: 3.607495 msecs"
虽然第一次运行还是慢了很多。有什么不同?在这两种情况下,代码都是编译的,没有解释的 Clojure,对吧?是为 REPL 设置的 JIT、一些优化还是一些特殊的 JVM 选项?
感谢您的任何想法。
Leiningen 使用某些默认选项运行 JVM,这些选项可以缩短启动时间,但会损害运行时性能。因此,您可能需要再次检查:jvm-opts ^:replace []
添加到您的project.clj
.
除此之外,虽然下面没有添加任何内容来解释 REPL 和 überjar 之间的时间差异,但如果您关心准确的结果,我想我应该对基准测试发表评论:
time
不是一个很好的基准测试工具,无论是dotimes
或不。 (不dotimes
-- JIT 编译器不会启动;和dotimes
——它可能会,但很可能会决定循环体是一个空操作并完全优化它。)
雨果邓肯的标准赛 https://github.com/hugoduncan/criterium是强大的 Clojure 解决方案,负责 JIT 预热、以不会优化的方式循环以及结果的统计处理。一个简单的 Criterium 基准测试可能如下所示:
(require '[criterium.core :as c])
(def v [0 1 2])
(c/bench (nth v 0))
(这测量了访问 Var 中保存的短向量的初始元素的时间。我希望(+ 1 1)
最终被编译为常量,因此可能没有什么可以进行基准测试。)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)