2024 Clojure 状态调查! 中分享你的想法。

欢迎!请参阅 关于 页面以获取更多相关信息。

0
Java 互操作

Math.random() 是通过声明为同步静态方法以保证线程安全的。

这个补丁使用了 java.util.concurrent.ThreadLocalRandom,实际上在简单的单线程 criterium.core/bench 中比普通的 Math.random() 快两倍。

我之所以研究这个函数,是为了确保在多线程负载生成时进行性能测试时,随机数生成不会成为瓶颈。

如果需要,当然可以根据类 java.util.concurrent.ThreadLocalRandom 的存在与否进行条件声明(如 fj-reducers),以便 Clojure 1.7 与 Java 版本 < 1.7 兼容。

10 答案

0
评论由:claj_ 提供

在当前 rand(clojure 1.6.0)上的基准测试,$ java -version
java 版本 "1.7.0_51"
OpenJDK 运行环境(IcedTea 2.4.4)(7u51-2.4.4-0ubuntu0.13.10.1)
OpenJDK 64 位服务器 VM(构建 24.45-b08,混合模式)

:jvm-opts ^:replace [] (即不向 JVM 传递参数)


(bench (rand 10))                                                                                                                                                                                                           
评估次数:1281673680次,来自21361228次调用中的60个样本。
    平均执行时间:43.630075纳秒
    执行时间标准差:0.420801纳秒
   执行时间下四分位数:42.823363纳秒(2.5%)
   执行时间上四分位数:44.456267纳秒(97.5%)
      消耗的额外开销:3.194591纳秒
                                                                                                                                                                                                                                   
在60个样本中找到1个异常值(1.6667%)
        轻度至严重       1(1.6667%)
异常值引起的变化:1.6389% 异常值略微增加方差

Clojure 1.7.0 主开发版本.

基准测试(rand 10)
评估次数:2622694860次,在60个样本中的43711581次调用。
        平均执行时间:20.474605纳秒
    标准偏差执行时间:0.248034纳秒
   执行时间的下四分位数:20.129894纳秒(2.5%)
   执行时间的上四分位数:21.009303纳秒(97.5%)
        使用的开销:2.827337纳秒
                                                                                                              
在60个样本中找到2个异常值(3.3333%)
        轻度至严重       2(3.3333%)
异常值引起的变化:1.6389% 异常值略微增加方差

在Clojure 1.6.0版本中也得到了类似的结果,并运行了几个不同但结果相似的测试。java.util.Random.nextInt 方法出奇地烂。ThreadLocalRandom版本的.nextInt 性能更好,但rand-int 函数可以接受负整数,这意味着对于 (.nextInt (ThreadLocalRandom/current) n) 的调用,会有一些参数转换问题,因为它需要上界和下界,而不是简单地用随机数 [0,1) 的乘积。

更改

(.nextDouble (ThreadLocalRandom/current)) 参数调用的速度非常快,但不能处理负参数。直接乘积的响应时间约为30纳秒。
0

评论者:claj

添加了一些简单的测试来确保rand和rand-int可以接受比、双精度和多种类型的负数。真正的测试将可能包括重复的生成测试,这些测试主要是为了了解各种参数是否有效等。

0

评论者:claj

0001-rand-using-ThreadLocalRandom-and-tests-for-random.patch 文件包含更改后的 (rand) 和测试用例。

0

评论者:alexmiller

Clojure需要Java 1.6.0,因此需要在以后重新考虑这一点。目前我们并没有计划在Clojure 1.7中提高最低要求的JDK版本,尽管这可能会改变。

0

评论者:gfredericks

我总是认为由于不能对PRNG设置种子,所以随机功能总体上作用有限,* } 动态变量会是一种合理的方式来实现。

也许可以通过标准库来部分解决这两个问题?我已在 https://github.com/fredericksgary/four 上开始了一个,但假定一个 contrib 库更容易为大家标准化。

0

评论者:claj

Gary,我完全支持创建一个经过深思熟虑的随机库,如果那会很有用,它可以是clojure.core.random的一些候选库。

请查看http://code.google.com/p/javarng/,因为它似乎能做您库4要做的事情(甚至更多)。我们可能可以从这个库中拯救API、算法或两者。

我将通过邮件与您联系!

0

评论者:gfredericks

回想起来,clojure.core中的rand变量不应该造成破坏性改变,所以我将为此创建一个工单来看一下进展。至少这应该能够解决与{{binding}}相关的并发问题。我唯一能想到的反对意见是与动态变量相关的性能问题吗?

0

评论者:gfredericks

新问题是CLJ-1452。

0

评论者:jafingerhut

2014年5月11日的补丁0001-rand-using-ThreadLocalRandom-and-tests-for-random.patch,在2014年8月29日对Clojure进行某些提交后已无法干净地应用于最新的master版本。在此之前,它能够干净地应用。

我没有检查更新此补丁的难易程度。请参阅此维基页面上的“更新陈旧补丁”部分,了解一些更新补丁的技巧:http://dev.clojure.org/display/community/Developing Patches

0
...