我似乎在与Guava的Charmatcher有一个问题.我正在编写一些JUnit测试,我注意到第一个测试需要一点时间(15秒),但是将来的测试大致相同(.3秒),大多数测试运行在相同的代码.
我对代码的分析指出,Guava的图书馆中的Charmatcher似乎是罪魁祸首.看起来CharMatcher中有一些静态的初始化代码,这可能是真正的原因.有什么办法可以禁用或优化这种行为吗?有没有从wiki页面或帮助文件中丢失的东西?
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的番石榴库.另外我打包一个可执行的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
解决方法
您正在遇到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中解决了.
尽管如此,我认为在静态初始化过程中,通过创建一个65k的元素LUT,即使您没有使用所讨论的匹配器,Guava的用户仍然有点侮辱,当JIT正常工作时,它仍然需要约50ms.我提交a bug反对番石榴,让我们看看维护者是否同意:).更新:这个错误在几天之内就被修复了,这个修复将在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();
这就是触发长静态init的代码,这在我的快速框中需要大约7秒钟.这是您的应用程序在我的框上的输出:
took 6814 ms 2nd took 0 ms
我正在提交一个番石榴臭虫