如何提高 C# 中 Saxon 求值的速度?
How to increase the speed of Saxon evaluation in C#?
我目前正在使用 Saxon 在我们的 .NET 应用程序中处理 Xquery。我们正在处理非常大的 XML 文件 (~2GB)。 运行直接使用 Saxon 二进制文件对这些文件之一执行 Xquery 时,完成评估所需的时间大约为 2 分钟,但是当从我的 C# 应用程序进行评估时,经过的时间增加到大约 10分钟,我还不能确定我做错了什么。
这就是我 运行 使用 Saxon 二进制文件的 Xquery 时所做的
通过命令行:
Query.exe -config:config.xml -q:XQueryTest.txt
这些是config.xml
的内容:
<configuration xmlns="http://saxon.sf.net/ns/configuration" edition="HE">
<xquery defaultElementNamespace="http://www.irs.gov/efile"/>
</configuration>
而XQueryTest.txt
包含我们要处理的Xquery。当从命令行 运行 连接 Xquery 时,我们修改它以指示我们将 运行 它针对的文件,使用 doc()
函数。这是一个示例行:
for
$ReturnData at $currentReturnDataPos in if(exists(doc("2GB.XML")/Return/ReturnData)) then doc("2GB.XML")/Return/ReturnData else element{'ReturnData'} {''}
如上所述,运行执行此命令大约需要 2 分钟才能完成。
现在我正在我的 .NET 应用程序中做同样的评估。
Processor processor = new Processor();
DocumentBuilder documentBuilder = processor.NewDocumentBuilder();
documentBuilder.IsLineNumbering = true;
documentBuilder.WhitespacePolicy = WhitespacePolicy.PreserveAll;
XQueryCompiler compiler = processor.NewXQueryCompiler();
string query = BuildXqueryString();
if (!String.IsNullOrEmpty(query))
{
XQueryExecutable executable = compiler.Compile(query);
XQueryEvaluator evaluator = executable.Load();
using (XmlReader myReader = XmlReader.Create(@"C:\Users\Administrator\DesktopGB.xml"))
{
evaluator.ContextItem = documentBuilder.Build(myReader);
}
var evaluations = evaluator.Evaluate();
}
我们遇到的问题在这一行:evaluator.ContextItem = documentBuilder.Build(myReader)
。这甚至不是评估,而只是文件的加载。这条线的执行时间太长,我需要知道这是否符合预期,或者是否有提高速度的方法。我已经使用了 Build()
方法的所有不同重载,它们都需要很长时间才能完成,远远超过从命令行执行时执行所需的 2 分钟。
关于使用 Saxon 的流容量来按部分读取文件,由于我们生成的 Xqueries,这不是一个选项,因为 Xquery 可以组合 XML 的任何部分中的信息。
在某些情况下,Java 平台上的 Saxon 与 .NET 平台上的 Saxon 之间的比率相似,为 5 比 1,但我们还没有弄清楚为什么会发生这种情况尽管进行了广泛的调查。部分原因是它似乎不一致。当我们第一次使用 IKVMC 交叉编译器在 .NET 上发布 Saxon 时,这个比率要好得多,在 .NET 上只有大约 25% 的开销,但从那以后似乎在技术上发生了一些变化:Java VM 变得更快,IKVMC 已经从使用 GNU Classpath 库切换到 OpenJDK,而 .NET 本身并没有停滞不前。
不过,我很陌生,相同的代码在 .NET 命令行中 运行 比在 .NET 运行 中快得多API。
这里最大的不同是,当您从命令行 运行 时,Saxon 使用 Apache Xerces 解析器构建文档(使用 IKVMC 转换为 .NET 代码),而当您使用 DocumentBuilder.build() 如图所示,您使用的是 Microsoft 的 XmlReader。
当您提供(文件系统)URI 时,我希望文档构建速度最快 运行,但我不能说我已经对其进行了测量。可能值得做一些实验(也许使用较小的文件)并向我们展示结果。或者,您是否尝试过使用应用程序中的 doc() 方法,而不是先构建文档?
性能下降是由于使用 .NET XmlReader 进行解析造成的。使用 .NET XML 解析器和 Saxon 接收器的 Push/Pull SAX 事件处理比直接使用 Saxon 中提供的 JAXP xerces 解析器要慢得多。
要强制使用 JAXP 解析器,您可以执行以下操作:
evaluator.ContextItem = documentBuilder.Build(new Uri("file:///C:\Users\Administrator\DesktopGB.xml"));
我目前正在使用 Saxon 在我们的 .NET 应用程序中处理 Xquery。我们正在处理非常大的 XML 文件 (~2GB)。 运行直接使用 Saxon 二进制文件对这些文件之一执行 Xquery 时,完成评估所需的时间大约为 2 分钟,但是当从我的 C# 应用程序进行评估时,经过的时间增加到大约 10分钟,我还不能确定我做错了什么。
这就是我 运行 使用 Saxon 二进制文件的 Xquery 时所做的 通过命令行:
Query.exe -config:config.xml -q:XQueryTest.txt
这些是config.xml
的内容:
<configuration xmlns="http://saxon.sf.net/ns/configuration" edition="HE">
<xquery defaultElementNamespace="http://www.irs.gov/efile"/>
</configuration>
而XQueryTest.txt
包含我们要处理的Xquery。当从命令行 运行 连接 Xquery 时,我们修改它以指示我们将 运行 它针对的文件,使用 doc()
函数。这是一个示例行:
for
$ReturnData at $currentReturnDataPos in if(exists(doc("2GB.XML")/Return/ReturnData)) then doc("2GB.XML")/Return/ReturnData else element{'ReturnData'} {''}
如上所述,运行执行此命令大约需要 2 分钟才能完成。
现在我正在我的 .NET 应用程序中做同样的评估。
Processor processor = new Processor();
DocumentBuilder documentBuilder = processor.NewDocumentBuilder();
documentBuilder.IsLineNumbering = true;
documentBuilder.WhitespacePolicy = WhitespacePolicy.PreserveAll;
XQueryCompiler compiler = processor.NewXQueryCompiler();
string query = BuildXqueryString();
if (!String.IsNullOrEmpty(query))
{
XQueryExecutable executable = compiler.Compile(query);
XQueryEvaluator evaluator = executable.Load();
using (XmlReader myReader = XmlReader.Create(@"C:\Users\Administrator\DesktopGB.xml"))
{
evaluator.ContextItem = documentBuilder.Build(myReader);
}
var evaluations = evaluator.Evaluate();
}
我们遇到的问题在这一行:evaluator.ContextItem = documentBuilder.Build(myReader)
。这甚至不是评估,而只是文件的加载。这条线的执行时间太长,我需要知道这是否符合预期,或者是否有提高速度的方法。我已经使用了 Build()
方法的所有不同重载,它们都需要很长时间才能完成,远远超过从命令行执行时执行所需的 2 分钟。
关于使用 Saxon 的流容量来按部分读取文件,由于我们生成的 Xqueries,这不是一个选项,因为 Xquery 可以组合 XML 的任何部分中的信息。
在某些情况下,Java 平台上的 Saxon 与 .NET 平台上的 Saxon 之间的比率相似,为 5 比 1,但我们还没有弄清楚为什么会发生这种情况尽管进行了广泛的调查。部分原因是它似乎不一致。当我们第一次使用 IKVMC 交叉编译器在 .NET 上发布 Saxon 时,这个比率要好得多,在 .NET 上只有大约 25% 的开销,但从那以后似乎在技术上发生了一些变化:Java VM 变得更快,IKVMC 已经从使用 GNU Classpath 库切换到 OpenJDK,而 .NET 本身并没有停滞不前。
不过,我很陌生,相同的代码在 .NET 命令行中 运行 比在 .NET 运行 中快得多API。
这里最大的不同是,当您从命令行 运行 时,Saxon 使用 Apache Xerces 解析器构建文档(使用 IKVMC 转换为 .NET 代码),而当您使用 DocumentBuilder.build() 如图所示,您使用的是 Microsoft 的 XmlReader。
当您提供(文件系统)URI 时,我希望文档构建速度最快 运行,但我不能说我已经对其进行了测量。可能值得做一些实验(也许使用较小的文件)并向我们展示结果。或者,您是否尝试过使用应用程序中的 doc() 方法,而不是先构建文档?
性能下降是由于使用 .NET XmlReader 进行解析造成的。使用 .NET XML 解析器和 Saxon 接收器的 Push/Pull SAX 事件处理比直接使用 Saxon 中提供的 JAXP xerces 解析器要慢得多。
要强制使用 JAXP 解析器,您可以执行以下操作:
evaluator.ContextItem = documentBuilder.Build(new Uri("file:///C:\Users\Administrator\DesktopGB.xml"));