![](/img/trans.png)
[英]use Guava CharMatcher as a static fields in a class . Is CharMatcher thread safe?
[英]Guava Charmatcher static initialization slow
更新:看起来我的13.0.1正在调用来自这个差异化CharMatcher的代码。
我似乎遇到了番石榴的Charmatcher的问题。 我目前正在编写一些JUnit测试,我注意到第一次测试花费了一些时间(15+秒),但未来的测试大致相同(.3秒),大多数测试都是通过相同的码。
我对代码的分析表明,Guava图书馆中的Charmatcher似乎是罪魁祸首。 看起来CharMatcher中有一些静态初始化代码可能是它花费这么长时间的真正原因。 有什么办法可以禁用或优化这种行为吗? 维基页面或帮助文件中是否存在我遗漏的内容?
Guava版本13.0.1,系统:Linux 64,Eclipse 3.6.1
编辑:我用以下代码构建了一个测试应用程序:
import com.google.common.base.CharMatcher;
public class Main {
public static void main(String[] args) {
// Using system instead of stopwatch to isolate library.
long startTime = System.currentTimeMillis();
CharMatcher.is(' ');
long endTime = System.currentTimeMillis();
System.out.println("took " + String.valueOf(endTime-startTime) + " ms");
startTime = System.currentTimeMillis();
CharMatcher.is('d');
endTime = System.currentTimeMillis();
System.out.println("2nd took " + String.valueOf(endTime-startTime) + " ms");
}
}
这导致以下输出:
took 15945 ms
2nd took 0 ms
我在eclipse中运行了这个减去JUnit框架和google的guava库。 我还打包了一个可执行的char并收到了类似的结果。 在我通过它运行一个分析器后,我会再回来进行第二次编辑。
谢谢你的帮助。
编辑2:分析结果:
Main.main(String[]) 22,556 ms
com.google.common.base.CharMatcher.<clinit>() 22.556 ms
com.google.common.base.CharMatcher.precomputed() 22,550 ms
com.google.common.base.Platform.precomputeCharMatcher(CharMatcher) 22,550 ms
com.google.common.base.CharMatcher.precomputedInternal() 22,550 ms
com.google.common.base.CharMatcher.slowGetChars() 13,638 ms
com.google.common.base.CharMatcher.setBits(CharMatcher$LookupTable) 8,911 ms
更新:这在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
chain)产生了JIT去优化和后续重新编译的完美风暴,这在u34中得到了解决。
尽管如此,我认为Guava家伙在静态初始化期间创建一个65k元素的LUT有点滥用,即使你从未使用过相关的匹配器,当JIT工作正常时它仍需要大约50ms。 我提交了一个针对番石榴的错误 ,让我们看看维护者是否同意:)。 更新:在我提交此文件的几天内修复了该错误,修复程序将在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
我正在提交一个番石榴虫。
刚刚测试过:
@Test
public void testCharMatcherSlow() throws Exception {
System.out.println(CharMatcher.JAVA_DIGIT.matches('1'));
}
并且执行需要0.06秒。 还查看了CharMatcher代码,没有什么可以解释你遇到的缓慢行为。 您应该通过模拟替换CharMatcher,以确定它不是问题,并且可能使用分析器来查找原因。
我刚刚运行了你提供的确切基准,并得到了
花了74毫秒
第二节花了0毫秒
......问题可能出在Eclipse的最后? 你在调试模式下运行吗?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.