Clojure 的随机函数目前使用 {{Math.random}} 和相关特性,这使得它们无法播种。这看起来动态变量(与额外的参数相比)是一个合适的使用,因为希望表现出随机行为的库代码可以无额外努力透明地支持播种。
我在 {{clojure.core}} 中提出 {{(def ^:dynamic \*rand* (java.util.Random.))}},并更新 {{rand}}, {{rand-int}}, {{rand-nth}}, 和 {{shuffle}} 以使用 {{\*rand*}}。
我认为这不会造成语义上的破坏性更改。
h2. Criterium 性能基准
我进行了一些基准测试,以了解使用动态变量的性能影响,以及测量并发访问的变化。
使用的代码在 [
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
**审查人员**: