以下是行为记录。我不知道是否真的进行了反射,但性能惩罚(大约 1300x)暗示了这一点。
user=> (use 'criterium.core)
nil
user=> (def b (make-array Double/TYPE 1000 1000))
#'user/b
user=> (quick-bench (aget ^"[[D" b 304 175))
警告:最终 GC 需要 3.5198021166354323 % 的运行时间
警告:最终 GC 需要 29.172288684474303 % 的运行时间
评估计数:63558 在 6 个样本的 10593 次调用中。
平均执行时间:9.457308 µs
执行时间标准差:126.220954 纳秒
执行时间下四分位数:9.344450 µs ( 2.5%)
执行时间上四分位数:9.629202 µs (97.5%)
使用的开销:2.477107 纳秒
一种解决方案是使用多个 aget。
user=> (quick-bench (aget ^"[D" (aget ^"[[D" b 304) 175))
警告:最终 GC 需要 40.59820310542545 % 的运行时间
评估计数:62135436 在 6 个样本的 10355906 次调用中。
平均执行时间:6.999273 ns
执行时间标准差:0.112703 ns
执行时间下四分位数:6.817782 ns ( 2.5%)
执行时间上四分位数:7.113845 ns (97.5%)
使用的开销:2.477107 纳秒
*原因:内联版本仅适用于 2 个参数的函数,否则它将进行反射。