Clojure 的随机函数目前使用 {{Math.random}} 以及相关功能,这使得它们无法进行种子设置。这似乎是动态变量(相对于额外的参数)的合适用途,因为希望表现得随机的库代码可以透明地支持种子设置,而无需额外的努力。
我在 {{clojure.core}} 中提议 {{(def ^:dynamic \*rand* (java.util.Random.))}},并且建议 {{rand}}、{{rand-int}}、{{rand-nth}} 和 {{shuffle}} 被更新以使用 {{\*rand*}}。
我认为在语义上这不会是一个破坏性更改。
h2. 评判标准基准
我进行了一些基准测试,试图了解使用动态变量的性能影响,并测量并发访问的改变。
使用的代码位于 [
https://github.com/gfredericks/clj-1452-tests]; 原始输出在注释中。
由于 {{rand}} 慢了一些,而 {{shuffle}} 的速度只略有提升。从 8 个线程中使用 {{shuffle}} 略慢,但手动切换到补丁版本中的 {{ThreadLocalRandom}} 时,速度提高 2.5 倍。
在 8 核 Linode 虚拟机上运行
||基准测试||Clojure||运行时平均值||运行时标准差||
|{{rand}}|1.6.0|61.3ns|7.06ns|
|{{rand}}|1.6.0 + {{\*rand\*}}|63.7ns|1.80ns|
|{{shuffle}}|1.6.0|12.9µs|251ns|
|{{shuffle}}|1.6.0 + {{\*rand\*}}|12.8µs|241ns|
|{{threaded-shuffling}}|1.6.0|151ms|2.31ms|
|{{threaded-shuffling}}|1.6.0 + {{\*rand\*}}|152ms|8.77ms|
|{{threaded-local-shuffling}}|1.6.0|N/A|N/A|
|{{threaded-local-shuffling}}|1.6.0 + {{\*rand\*}}|64.5ms|1.41ms|
*方法:* 创建一个动态变量 *rand* 并更新 {{rand}}、{{rand-int}}、{{rand-nth}} 和 {{shuffle}} 以使用 {{\*rand*}}
*补丁:* CLJ-1452.patch
*筛选:**