[英]Scala Generic Type slow
I do need to create a method for comparison for either Int or String or Char. 我确实需要创建一个用于比较Int或String或Char的方法。 Using AnyVal was not make it possible as there were no method's for <, > comparison.
由于没有用于<,>比较的方法,因此无法使用AnyVal。
However Typing it into Ordered shows a significant slowness. 但是,将其键入Ordered显示出明显的缓慢性。 Are there better ways to achieve this?
有更好的方法来实现这一目标吗? The plan is to do a generic binary sorting, and found Generic typing decreases the performance.
该计划是进行通用二进制排序,发现通用类型会降低性能。
def sample1[T <% Ordered[T]](x:T) = { x < (x) }
def sample2(x:Ordered[Int]) = { x < 1 }
def sample3(x:Int) = { x < 1 }
val start1 = System.nanoTime
sample1(5)
println(System.nanoTime - start1)
val start2 = System.nanoTime
sample2(5)
println(System.nanoTime - start2)
val start3 = System.nanoTime
sample3(5)
println(System.nanoTime - start3)
val start4 = System.nanoTime
sample3(5)
println(System.nanoTime - start4)
val start5 = System.nanoTime
sample2(5)
println(System.nanoTime - start5)
val start6 = System.nanoTime
sample1(5)
println(System.nanoTime - start6)
The results shows: 结果显示:
Sample1:696122
样本1:696122
Sample2:45123
样品2:45123
Sample3:13947
样本3:13947
Sample3:5332
样本3:5332
Sample2:194438
样品2:194438
Sample1:497992
样本1:497992
Am I doing the incorrect way of handling Generics? 我在处理泛型时做错了方法吗? Or should I be doing the old Java method of using Comparator in this case, sample as in:
或者在这种情况下,我应该使用使用Comparator的旧Java方法,示例如下:
object C extends Comparator[Int] {
override def compare(a:Int, b:Int):Int = {
a - b
}
}
def sample4[T](a:T, b:T, x:Comparator[T]) {x.compare(a,b)}
Do not do micro-tests in such way if you want to get results somehow similar you will have in production env. 如果要获得与生产环境类似的结果,请不要以这种方式进行微测试。 First of all you need to warm-up jvm.
首先,您需要预热jvm。 And after that do your test as average of many iterations.
之后,将您的测试作为多次迭代的平均值。 Also, you need to prevent possible jvm optimizations because of const data.
另外,由于const数据,您需要防止可能的jvm优化。 Eg
例如
def sample1[T <% Ordered[T]](x:T) = { x < (x) }
def sample2(x:Ordered[Int]) = { x < 1 }
def sample3(x:Int) = { x < 1 }
val r = new Random()
def measure(f: => Unit): Long = {
val start1 = System.nanoTime
f
System.nanoTime - start1
}
val n = 1000000
(1 to n).map(_ => measure {val k = r.nextInt();sample1(k)})
(1 to n).map(_ => measure {val k = r.nextInt();sample2(k)})
(1 to n).map(_ => measure {val k = r.nextInt();sample3(k)})
val avg1 = (1 to n).map(_ => measure {val k = r.nextInt();sample1(k)}).sum / n
println(avg1)
val avg2 = (1 to n).map(_ => measure {val k = r.nextInt();sample2(k)}).sum / n
println(avg2)
val avg3 = (1 to n).map(_ => measure {val k = r.nextInt();sample3(k)}).sum / n
println(avg3)
I got results, which look more fare for me: 我得到了结果,对我来说更有价值:
134
92
83
This book could give some light on performance tests. 这本书可以提供一些有关性能测试的信息。
The Scala equivalent of Java Comparator
is Ordering
. Java
Comparator
的Scala等效项是Ordering
。 One of the main differences is that, if you don't provide one manually, a suitable Ordering
can be injected implicitly by the compiler. 主要区别之一是,如果不手动提供,则编译器可以隐式注入适当的
Ordering
。 By default, this will be done for Byte
, Int
, Float
and other primitives, for any subclass of Ordered
or Comparable
, and for some other obvious cases. 默认情况下,将对
Byte
, Int
, Float
和其他基元, Ordered
或Comparable
任何子类以及其他一些明显的情况执行此操作。
Also, Ordering
provides method definitions for all the main comparison methods as extension methods, so you can write the following: 另外,
Ordering
提供了所有主要比较方法的方法定义作为扩展方法,因此您可以编写以下内容:
import Ordering.Implicits._
def sample5[T : Ordering](a: T, b: T) = a < b
def run() = sample5(1, 2)
As of Scala 2.12, those extension operations (ie, a < b
) invoke wrapping in a temporary object Ordering#Ops
, so the code will be slower than with a Comparator
. 从Scala 2.12开始,这些扩展操作(即
a < b
)调用包装在临时对象Ordering#Ops
包装,因此代码将比使用Comparator
慢。 Not much in most real cases, but still significant if you care about micro-optimisations. 在大多数实际情况下并不多,但是如果您关心微优化,那仍然很重要。
But you can use an alternative syntax to define an implicit Ordering[T]
parameter and invoke methods on the Ordering
object directly. 但是,您可以使用其他语法来定义隐式
Ordering[T]
参数并直接在Ordering
对象上调用方法。 Actually even the generated bytecode for the following two methods will be identical (except for the type of the third argument, and potentially the implementation of the respective compare
methods): 实际上,即使为以下两种方法生成的字节码也将是相同的(除了第三个参数的类型,以及相应
compare
方法的实现之外):
def withOrdering[T](x: T, y: T)(implicit cmp: Ordering[T]) = {
cmp.compare(x, y) // also supports other methods, like `cmp.lt(x, y)`
}
def withComparator[T](x: T, y: T, cmp: Comparator[T]) = {
cmp.compare(x, y)
}
In practice the runtime on my machine is the same, when invoking these methods with Int
arguments. 实际上,当使用
Int
参数调用这些方法时,我的机器上的运行时是相同的。
So, if you want to compare types generically in Scala, you should usually use Ordering
. 因此,如果要比较Scala中的常规类型,通常应使用
Ordering
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.