Clojure 的随机函数目前使用 {{Math.random}} 以及相关的功能,这使得它们无法进行种子。使用动态 var(与额外参数相比)似乎是一个合适的用法,因为希望表现出随机行为的库代码可以不用任何额外的工作透明地支持 seeds。
我建议在 {{clojure.core}} 中使用 {{(def ^:dynamic \*rand* (java.util.Random.))}},并且将 {{rand}}、{{rand-int}}、{{rand-nth}} 和 {{shuffle}} 更新为使用 {{\*rand*}}。
我认为这从语义上讲不会是一个破坏性变更。
### Criterium 基准测试
我进行了一些基准测试来尝试了解使用动态 var 的性能影响,以及测量并发访问的变化。
使用的代码位于 [
https://github.com/gfredericks/clj-1452-tests]; 原始输出位于注释中。
{{rand}} 稍微慢一些,而 {{shuffle}} 签的正常速度更快。使用来自 8 个线程的 {{shuffle}} 稍慢,但在修补版本中将 {{ThreadLocalRandom}} 手动更改为后,结果是速度提升了 2.5 倍。
在我的 8 核心 Linode VM 上运行
||基准||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|
**方法**:创建一个动态 var \*rand* 并更新 {{rand}}、{{rand-int}}、{{rand-nth}} 和 {{shuffle}} 以使用 {{\*rand*}}
**补丁**:CLJ-1452.patch
**筛选**: