DocumentBuilder
和
XPathCompiler
来测量执行时间,希望能够保持一致的“冷”运行。
static def measureSaxon(String xml, String xpath) {
Processor processor = new Processor(false);
processor.setConfigurationProperty(FeatureKeys.OPTIMIZATION_LEVEL, "0")
XdmNode xdm = processor.newDocumentBuilder().build(new StreamSource(new StringReader(xml)));
def compiler = processor.newXPathCompiler()
return measureExecutionTime(
"Saxon",
xpath,
{
def evaluate = compiler.evaluate(xpath, xdm)
if (evaluate instanceof XdmValue && evaluate.size() > 0) {
return evaluate.itemAt(0).getStringValue()
} else {
return "No node found"
}
}
)
}
wo,第一个调用总是比随后的呼叫要慢得多,后续调用似乎从某种的缓存或优化中受益 - 即使我尝试过:processor.setConfigurationProperty(FeatureKeys.OPTIMIZATION_LEVEL, "0")
below是我的基准结果。您可以看到第一个呼叫的方式非常慢,随后的呼叫速度更快:# Benchmark Results for Saxon
| XPath Expression | Execution Time (ns) | Execution Time (ms) | Result |
|---------------------------------|---------------------|---------------------|----------------------|
| `/program/@name` | 151562270 | 151.56227 | j$Collections |
| `/program/objects/o/@base` | 522288 | 0.522288 | some.class |
| `/program/objects/o/o/o/o/@base`| 12328695 | 12.328695 | org.lang.bytes |
撒克逊本身中有更深的缓存机制或内部优化,不能简单地将
Processor
或设置OPTIMIZATION_LEVEL
除非您已经非常小心以防止它,否则这是Java热身时间。首先,Java必须加载Saxon类,并且首先引用每个类时,它会逐步进行。然后,最频繁地调用方法的热点编译器监控器,当它检测到热点时,它会执行优化,例如内部和适当生成本机机器代码。通常需要几秒钟才能全速运行。也有一些撒克逊初始化成本,例如设置标准数据类型和内置功能的索引。撒克逊人整体上一次完成了一次,当您创建撒克逊处理器/配置时,有些是完成的。但是我认为撒克逊的初始化成本远低于爪哇的热身。
显然是从中的一个教训,即在生产中,您应该不惜一切代价为每个撒克逊人任务加载新的Java VM。