[英]How fast is pattern matching in Scala
I'm new to Scala. 我是Scala的新手。 When I am learning it by reading Scala code written by others, one of the most distinguishing feature I find in Scala code that is different from other languages is its pattern matching.
当我通过阅读其他人编写的Scala代码来学习它时,我在Scala代码中发现的与其他语言不同的一个最显着特征是它的模式匹配。
At the same time I feel the convenience and expressiveness it brings, I can't help being curious of the potential performance cost behind it -- generally speaking, how fast is match
? 与此同时,我感受到它带来的便利性和表现力,我不禁对它背后的潜在性能成本感到好奇 - 一般来说,
match
速度有多快?
Firstly, without "advanced" features such as matching parameters of constructors, match
in Scala, IMO, is the counterpart of switch-case
in other languages. 首先,如果没有“高级”功能,例如匹配构造函数的参数,Scala中的
match
,IMO,是其他语言中switch-case
的对应物。 For instance, 例如,
color match {
0 => println "color is red!"
1 => println "color is green!"
2 => println "color is blue!"
}
As a novice, I want to know if the code above is exactly as fast as equivalent code in if-else
statement? 作为一个新手,我想知道上面的代码是否和
if-else
语句中的等效代码一样快?
Secondly, now taking those "advanced" features back, for instance: 其次,现在恢复这些“高级”功能,例如:
expr match {
Animal(name) => ...
Animal(name, age) => ...
Animal(_, _, id) => ...
}
As for the code above or other features of match(list matching, pair matching, etc.), I am curious about how Scala implemented these fancy usage? 至于上面的代码或匹配的其他功能(列表匹配,配对匹配等),我很好奇Scala如何实现这些花哨的用法? And most importantly, how fast can I expect these code to be?
最重要的是,我能期望这些代码有多快? (Say, are they still as fast as the
match
in the first case? Or maybe slightly slower? Or extremely slow owing to the use of some technology such as reflection?) (比方说,它们仍然和第一种情况下的
match
一样快吗?或者可能稍微慢一些?或者由于使用某些技术(如反射)而非常慢?)
Thanks in advance! 提前致谢!
First snippet is translated to bytecode's TableSwitch
(or LookupSwitch
) and is as fast as Java's switch/case: 第一个代码段被转换为字节码的
TableSwitch
(或LookupSwitch
),并且与Java的switch / case一样快:
scala> def foo(i: Int) = i match {
| case 1 => 2
| case 2 => 10
| case 3 => 42
| case _ => 777
| }
foo: (i: Int)Int
scala> :javap -c foo
Compiled from "<console>"
public class {
public static final MODULE$;
public static {};
Code:
0: new #2 // class
3: invokespecial #12 // Method "<init>":()V
6: return
public int foo(int);
Code:
0: iload_1
1: istore_2
2: iload_2
3: tableswitch { // 1 to 3
1: 44
2: 39
3: 34
default: 28
}
28: sipush 777
31: goto 45
34: bipush 42
36: goto 45
39: bipush 10
41: goto 45
44: iconst_2
45: ireturn
public ();
Code:
0: aload_0
1: invokespecial #18 // Method java/lang/Object."<init>":()V
4: aload_0
5: putstatic #20 // Field MODULE$:L;
8: return
Second snipped is translated to bunch of unapply/isInstanceOf/null checks
calls, and is (obviously) slower than tableswitch
. 第二个剪切被转换为一堆
unapply/isInstanceOf/null checks
调用,并且(显然)比tableswitch
慢。 But it has same (or better, if compiler can optimize something) performance as manual checking via isInstanceOf
(no reflection or similar stuff): 但它具有相同(或更好,如果编译器可以优化某些东西)性能作为手动检查通过
isInstanceOf
(没有反射或类似的东西):
scala> case class Foo(s: String, i: Int)
defined class Foo
scala> def bar(foo: Foo) = foo match {
| case Foo("test", _) => 1
| case Foo(_, 42) => 2
| case _ => 3
| }
bar: (foo: Foo)Int
scala> :javap -c bar
Compiled from "<console>"
public class {
public static final MODULE$;
public static {};
Code:
0: new #2 // class
3: invokespecial #12 // Method "<init>":()V
6: return
public int bar(Foo);
Code:
0: aload_1
1: astore_2
2: aload_2
3: ifnull 26
6: aload_2
7: invokevirtual #20 // Method Foo.s:()Ljava/lang/String;
10: astore_3
11: ldc #22 // String test
13: aload_3
14: invokevirtual #26 // Method java/lang/Object.equals:(Ljava/lang/Object;)Z
17: ifeq 26
20: iconst_1
21: istore 4
23: goto 52
26: aload_2
27: ifnull 49
30: aload_2
31: invokevirtual #30 // Method Foo.i:()I
34: istore 5
36: bipush 42
38: iload 5
40: if_icmpne 49
43: iconst_2
44: istore 4
46: goto 52
49: iconst_3
50: istore 4
52: iload 4
54: ireturn
public ();
Code:
0: aload_0
1: invokespecial #34 // Method java/lang/Object."<init>":()V
4: aload_0
5: putstatic #36 // Field MODULE$:L;
8: return
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.