scala专门化 – 使用对象而不是类导致减速?
我已经做了一些基准测试并且得到了我不知道如何解释的结果.
简而言之: 我有2个类使用泛型数组做同样的事情(计算繁重),它们都使用专门化(@specialized,后来的@spec).一个类定义如下: class A [@spec T] { def a(d: Array[T],c: Whatever[T],...) = ... ... } 第二:(单身人士) object B { def a[@spec T](d: Array[T],...) = ... ... } 在第二种情况下,我获得了巨大的性能.为什么会这样? (注意:目前我不太了解Java字节码,而Scala编译器内部也是如此.) 更多细节: 完整代码在这里:https://github.com/magicgoose/trashbox/tree/master/sorting_tests/src/magicgoose/sorting JavaSort | JavaSortGen$mcI$sp | JavaSortGenSingleton$mcI$sp length 2 | time 0.00003ms | length 2 | time 0.00004ms | length 2 | time 0.00006ms length 3 | time 0.00003ms | length 3 | time 0.00005ms | length 3 | time 0.00011ms length 4 | time 0.00005ms | length 4 | time 0.00006ms | length 4 | time 0.00017ms length 6 | time 0.00008ms | length 6 | time 0.00010ms | length 6 | time 0.00036ms length 9 | time 0.00013ms | length 9 | time 0.00015ms | length 9 | time 0.00069ms length 13 | time 0.00022ms | length 13 | time 0.00028ms | length 13 | time 0.00135ms length 19 | time 0.00037ms | length 19 | time 0.00040ms | length 19 | time 0.00245ms length 28 | time 0.00072ms | length 28 | time 0.00060ms | length 28 | time 0.00490ms length 42 | time 0.00127ms | length 42 | time 0.00096ms | length 42 | time 0.01018ms length 63 | time 0.00173ms | length 63 | time 0.00179ms | length 63 | time 0.01052ms length 94 | time 0.00280ms | length 94 | time 0.00280ms | length 94 | time 0.01522ms length 141 | time 0.00458ms | length 141 | time 0.00479ms | length 141 | time 0.02376ms length 211 | time 0.00731ms | length 211 | time 0.00763ms | length 211 | time 0.03648ms length 316 | time 0.01310ms | length 316 | time 0.01436ms | length 316 | time 0.06333ms length 474 | time 0.02116ms | length 474 | time 0.02158ms | length 474 | time 0.09121ms length 711 | time 0.03250ms | length 711 | time 0.03387ms | length 711 | time 0.14341ms length 1066 | time 0.05099ms | length 1066 | time 0.05305ms | length 1066 | time 0.21971ms length 1599 | time 0.08040ms | length 1599 | time 0.08349ms | length 1599 | time 0.33692ms length 2398 | time 0.12971ms | length 2398 | time 0.13084ms | length 2398 | time 0.51396ms length 3597 | time 0.20300ms | length 3597 | time 0.20893ms | length 3597 | time 0.79176ms length 5395 | time 0.32087ms | length 5395 | time 0.32491ms | length 5395 | time 1.30021ms 后者是在对象内部定义的,它很糟糕(大约慢4倍). 更新1 我使用和不使用scalac优化选项运行基准测试,并没有明显的差异(只有较慢的编译与优化). 解决方法
这只是专业化中的许多错误之一 – 我不确定是否已经在错误跟踪器上报告了这个错误.如果从排序中抛出异常,您将看到它调用泛型版本而不是第二种类型的专用版本:
java.lang.Exception: Boom! at magicgoose.sorting.DualPivotQuicksortGenSingleton$.magicgoose$sorting$DualPivotQuicksortGenSingleton$$sort(DualPivotQuicksortGenSingleton.scala:33) at magicgoose.sorting.DualPivotQuicksortGenSingleton$.sort$mFc$sp(DualPivotQuicksortGenSingleton.scala:13) 注意堆栈顶部的东西是DualPivotQuicksortGenSingleton $$sort(…)而不是… sort $mFc $sp(…)?编译错误,不好! 作为一种变通方法,您可以将私有方法包装在最终的辅助对象中,例如 def sort[@ spec T](a: Array[T]) { Helper.sort(a,a.length) } private final object Helper { def sort[@spec T](a: Array[T],i0: Int,i1: Int) { ... } } 无论出于何种原因,编译器然后意识到它应该调用专用变体.我没有测试是否每个被另一个调用的专用方法都需要在它自己的对象中;我会通过抛出异常的技巧把它留给你. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |