更新:这已在 Guava 14中修复。
您遇到了 u21 中存在的某种 JIT 错误,可能是更早的版本,但至少在某些更高的 JDK 版本中没有。这是 u21 中测试程序的 -XX:+PrintCompilation 输出:
1 java.util.Arrays::binarySearch0 (72 bytes)
2 com.google.common.base.CharMatcher$Or::matches (28 bytes)
3 com.google.common.base.CharMatcher$12::matches (22 bytes)
2 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
4 com.google.common.base.CharMatcher$11::matches (17 bytes)
5 java.util.Arrays::binarySearch (9 bytes)
6 com.google.common.base.CharMatcher$Or::matches (28 bytes)
1% com.google.common.base.CharMatcher::slowGetChars @ 9 (52 bytes)
6 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
7 com.google.common.base.CharMatcher$Or::matches (28 bytes)
7 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
1% made not entrant com.google.common.base.CharMatcher::slowGetChars @ -2 (52 bytes)
2% com.google.common.base.CharMatcher::slowGetChars @ 9 (52 bytes)
8 com.google.common.base.CharMatcher$Or::matches (28 bytes)
8 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
2% made not entrant com.google.common.base.CharMatcher::slowGetChars @ -2 (52 bytes)
3% com.google.common.base.CharMatcher::slowGetChars @ 9 (52 bytes)
9 com.google.common.base.CharMatcher$Or::matches (28 bytes)
9 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
3% made not entrant com.google.common.base.CharMatcher::slowGetChars @ -2 (52 bytes)
4% com.google.common.base.CharMatcher::slowGetChars @ 9 (52 bytes)
10 com.google.common.base.CharMatcher$Or::matches (28 bytes)
10 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
4% made not entrant com.google.common.base.CharMatcher::slowGetChars @ -2 (52 bytes)
11 com.google.common.base.CharMatcher$Or::matches (28 bytes)
5% com.google.common.base.CharMatcher::slowGetChars @ 9 (52 bytes)
11 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
12 com.google.common.base.CharMatcher$Or::matches (28 bytes)
5% made not entrant com.google.common.base.CharMatcher::slowGetChars @ -2 (52 bytes)
12 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
6% com.google.common.base.CharMatcher::slowGetChars @ 9 (52 bytes)
13 com.google.common.base.CharMatcher$Or::matches (28 bytes)
13 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
6% made not entrant com.google.common.base.CharMatcher::slowGetChars @ -2 (52 bytes)
7% com.google.common.base.CharMatcher::slowGetChars @ 9 (52 bytes)
14 com.google.common.base.CharMatcher$Or::matches (28 bytes)
15 com.google.common.base.CharMatcher::slowGetChars (52 bytes)
14 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
7% made not entrant com.google.common.base.CharMatcher::slowGetChars @ -2 (52 bytes)
16 com.google.common.base.CharMatcher$Or::matches (28 bytes)
16 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
17 com.google.common.base.CharMatcher$Or::matches (28 bytes)
17 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
8% com.google.common.base.CharMatcher::slowGetChars @ 9 (52 bytes)
18 com.google.common.base.CharMatcher$Or::matches (28 bytes)
18 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
19 com.google.common.base.CharMatcher$Or::matches (28 bytes)
19 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
20 com.google.common.base.CharMatcher$Or::matches (28 bytes)
8% made not entrant com.google.common.base.CharMatcher::slowGetChars @ -2 (52 bytes)
20 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
21 com.google.common.base.CharMatcher$Or::matches (28 bytes)
21 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
22 com.google.common.base.CharMatcher$Or::matches (28 bytes)
9% com.google.common.base.CharMatcher::slowGetChars @ 9 (52 bytes)
22 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
23 com.google.common.base.CharMatcher$Or::matches (28 bytes)
23 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
24 com.google.common.base.CharMatcher$Or::matches (28 bytes)
24 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
9% made not entrant com.google.common.base.CharMatcher::slowGetChars @ -2 (52 bytes)
25 com.google.common.base.CharMatcher$Or::matches (28 bytes)
25 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
26 com.google.common.base.CharMatcher$Or::matches (28 bytes)
26 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
10% com.google.common.base.CharMatcher::slowGetChars @ 9 (52 bytes)
27 com.google.common.base.CharMatcher$Or::matches (28 bytes)
27 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
28 com.google.common.base.CharMatcher$Or::matches (28 bytes)
28 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
10% made not entrant com.google.common.base.CharMatcher::slowGetChars @ -2 (52 bytes)
29 com.google.common.base.CharMatcher$Or::matches (28 bytes)
29 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
30 com.google.common.base.CharMatcher$Or::matches (28 bytes)
30 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
11% com.google.common.base.CharMatcher::slowGetChars @ 9 (52 bytes)
31 com.google.common.base.CharMatcher$Or::matches (28 bytes)
31 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
32 com.google.common.base.CharMatcher$Or::matches (28 bytes)
32 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
11% made not entrant com.google.common.base.CharMatcher::slowGetChars @ -2 (52 bytes)
33 com.google.common.base.CharMatcher$Or::matches (28 bytes)
33 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
34 com.google.common.base.CharMatcher$Or::matches (28 bytes)
34 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
35 com.google.common.base.CharMatcher$Or::matches (28 bytes)
12% com.google.common.base.CharMatcher::slowGetChars @ 9 (52 bytes)
35 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
36 com.google.common.base.CharMatcher$Or::matches (28 bytes)
36 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
37 com.google.common.base.CharMatcher$Or::matches (28 bytes)
37 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
12% made not entrant com.google.common.base.CharMatcher::slowGetChars @ -2 (52 bytes)
38 com.google.common.base.CharMatcher$Or::matches (28 bytes)
38 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
39 com.google.common.base.CharMatcher$Or::matches (28 bytes)
39 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
13% com.google.common.base.CharMatcher::slowGetChars @ 9 (52 bytes)
40 com.google.common.base.CharMatcher$Or::matches (28 bytes)
40 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
41 com.google.common.base.CharMatcher$Or::matches (28 bytes)
41 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
13% made not entrant com.google.common.base.CharMatcher::slowGetChars @ -2 (52 bytes)
42 com.google.common.base.CharMatcher$Or::matches (28 bytes)
42 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
43 com.google.common.base.CharMatcher$Or::matches (28 bytes)
43 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
44 com.google.common.base.CharMatcher$Or::matches (28 bytes)
14% com.google.common.base.CharMatcher::slowGetChars @ 9 (52 bytes)
44 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
45 com.google.common.base.CharMatcher$Or::matches (28 bytes)
45 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
46 com.google.common.base.CharMatcher$Or::matches (28 bytes)
46 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
14% made not entrant com.google.common.base.CharMatcher::slowGetChars @ -2 (52 bytes)
47 com.google.common.base.CharMatcher$Or::matches (28 bytes)
47 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
48 com.google.common.base.CharMatcher$Or::matches (28 bytes)
48 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
15% com.google.common.base.CharMatcher::slowGetChars @ 9 (52 bytes)
49 com.google.common.base.CharMatcher$Or::matches (28 bytes)
49 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
50 com.google.common.base.CharMatcher$Or::matches (28 bytes)
50 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
15% made not entrant com.google.common.base.CharMatcher::slowGetChars @ -2 (52 bytes)
51 com.google.common.base.CharMatcher$Or::matches (28 bytes)
51 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
52 com.google.common.base.CharMatcher$Or::matches (28 bytes)
52 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
16% com.google.common.base.CharMatcher::slowGetChars @ 9 (52 bytes)
53 com.google.common.base.CharMatcher$Or::matches (28 bytes)
53 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
54 com.google.common.base.CharMatcher$Or::matches (28 bytes)
54 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
16% made not entrant com.google.common.base.CharMatcher::slowGetChars @ -2 (52 bytes)
55 com.google.common.base.CharMatcher$Or::matches (28 bytes)
55 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
56 com.google.common.base.CharMatcher$Or::matches (28 bytes)
56 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
57 com.google.common.base.CharMatcher$Or::matches (28 bytes)
17% com.google.common.base.CharMatcher::slowGetChars @ 9 (52 bytes)
57 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
58 com.google.common.base.CharMatcher$Or::matches (28 bytes)
58 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
59 com.google.common.base.CharMatcher$Or::matches (28 bytes)
59 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
17% made not entrant com.google.common.base.CharMatcher::slowGetChars @ -2 (52 bytes)
60 com.google.common.base.CharMatcher$Or::matches (28 bytes)
60 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
61 com.google.common.base.CharMatcher$Or::matches (28 bytes)
61 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
18% com.google.common.base.CharMatcher::slowGetChars @ 9 (52 bytes)
62 com.google.common.base.CharMatcher$Or::matches (28 bytes)
62 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
63 com.google.common.base.CharMatcher$Or::matches (28 bytes)
63 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
18% made not entrant com.google.common.base.CharMatcher::slowGetChars @ -2 (52 bytes)
64 com.google.common.base.CharMatcher$Or::matches (28 bytes)
64 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
65 com.google.common.base.CharMatcher$Or::matches (28 bytes)
65 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
19% com.google.common.base.CharMatcher::slowGetChars @ 9 (52 bytes)
66 com.google.common.base.CharMatcher$Or::matches (28 bytes)
<I omitted ~500 very similar lines here>
143% made not entrant com.google.common.base.CharMatcher::setBits @ -2 (30 bytes)
144% com.google.common.base.CharMatcher::setBits @ 2 (30 bytes)
144% made not entrant com.google.common.base.CharMatcher::setBits @ -2 (30 bytes)
145% com.google.common.base.CharMatcher::setBits @ 2 (30 bytes)
145% made not entrant com.google.common.base.CharMatcher::setBits @ -2 (30 bytes)
took 7599 ms
2nd took 0 ms
这是 u34 的相同输出:
64 1 java.util.Arrays::binarySearch0 (72 bytes)
68 2 com.google.common.base.CharMatcher$Or::matches (28 bytes)
68 3 com.google.common.base.CharMatcher$12::matches (22 bytes)
70 4 com.google.common.base.CharMatcher$11::matches (17 bytes)
71 5 java.util.Arrays::binarySearch (9 bytes)
71 1% com.google.common.base.CharMatcher::slowGetChars @ 9 (52 bytes)
76 2 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
76 6 com.google.common.base.CharMatcher$Or::matches (28 bytes)
88 1% made not entrant com.google.common.base.CharMatcher::slowGetChars @ -2 (52 bytes)
88 6 made not entrant com.google.common.base.CharMatcher$Or::matches (28 bytes)
88 7 com.google.common.base.CharMatcher::slowGetChars (52 bytes)
89 8 com.google.common.base.CharMatcher$Or::matches (28 bytes)
91 9 com.google.common.base.CharMatcher$8::matches (14 bytes)
91 2% com.google.common.base.CharMatcher::slowGetChars @ 9 (52 bytes)
98 10 java.lang.String::indexOf (166 bytes)
98 11 java.lang.String::indexOf (151 bytes)
102 3% com.google.common.base.CharMatcher::setBits @ 2 (30 bytes)
113 12 com.google.common.base.CharMatcher::setBits (30 bytes)
113 13 com.google.common.base.CharMatcher$LookupTable::set (15 bytes)
正如你所看到的,在 u34 中它是一个更加理智的地狱。看起来 u21 中发生的事情是OSR(影响slowGetChars
方法,因为它有一个大循环)和递归超态调用(影响CharMatcher$Or
和其他子类- 在递归链CharMatcher
的末尾调用)的某种组合产生了一个完美的CharMatcher$Or
JIT 反优化和后续重新编译的风暴,这在 u34 中得到了解决。
尽管如此,我认为 Guava 家伙在静态初始化期间创建 65k 元素 LUT 有点滥用,即使您从不使用有问题的匹配器,当 JIT 正常工作时,这仍然需要大约 50 毫秒。我提交了一个针对番石榴的错误,让我们看看维护者是否同意:)。更新:该错误在我提交此文件后的几天内得到修复,修复将在 Guava 14 中。这就是我所说的快速周转!
原帖如下:
我有完全相同的行为并跑到这篇文章中寻找解决方案。
查看代码,似乎他们正在制作一个 65k 元素(每个元素占用一位)查找表并检查每个字符是否匹配,由于用于定义匹配器的流畅样式,这需要许多嵌套函数调用:
public static final CharMatcher INVISIBLE = inRange('\u0000', '\u0020')
.or(inRange('\u007f', '\u00a0'))
.or(is('\u00ad'))
.or(inRange('\u0600', '\u0604'))
.or(anyOf("\u06dd\u070f\u1680\u180e"))
.or(inRange('\u2000', '\u200f'))
.or(inRange('\u2028', '\u202f'))
.or(inRange('\u205f', '\u2064'))
.or(inRange('\u206a', '\u206f'))
.or(is('\u3000'))
.or(inRange('\ud800', '\uf8ff'))
.or(anyOf("\ufeff\ufff9\ufffa\ufffb"))
.withToString("CharMatcher.INVISIBLE")
.precomputed();
那是触发长静态初始化的代码,在我的快速盒子上大约需要 7 秒。这是您的应用在我的盒子上的输出:
took 6814 ms
2nd took 0 ms
我正在提交一个番石榴错误。