Saxon xslt 转换为 PDF 在服务器上速度慢但在本地速度快
Saxon xslt transform to PDF slow on server but fast on local
我在使用 saxon 和 apache fo 将 xml 转换为 PDF 时遇到性能问题。我们用来测试的 pdf 有 85 页,大约 320k。它在 transform 方法调用上花费了将近 2 分钟,而在本地只需要不到 5 秒。
我们在该方法调用期间监控 cpu 使用率和 GC,发现在服务器上,cpu 使用率稳定在 5%,并且我们对服务器端的 cpu 没有任何限制。 GC 每 1 到 2 秒发生一次,但它们都是次要 GC,每次只需要 10 到 50 毫秒。我们还在测试期间监控 io 等待,它保持在非常低的水平。
我们使用的库是:‖saxon 9.1 和 apache fop 2.1(我们测试了不同的 saxon 和 apache 版本,但问题仍然存在)
xml 和 xsl 文件太大,所以我无法 post 它们。下面是转换的示例代码:
public static TransformerFactory transformerFactory;
public static Transformer xlsProcessor;
public static byte[] generatePDF(InputStream xmlData, String xslFile)
throws TransformerException, IOException {
byte[] fileArray = null;
InputStream xsltfile = null;
ByteArrayOutputStream outStream = null;
try {
xsltfile =
XmlToPdfGenerator.class.getClassLoader()
.getResourceAsStream(xslFile);
StreamSource source = new StreamSource(xmlData);
StreamSource transformSource = new StreamSource(xsltfile);
if (null== fopFactory){
File xconf= new File(XmlToPdfGenerator.class.getClassLoader().getResource("a xconf file").getFile());
fopFactory = FopFactory.newInstance(xconf);
}
FOUserAgent foUserAgent = fopFactory.newFOUserAgent();
outStream = new ByteArrayOutputStream();
Transformer xslfoTransformer =
getTransformer(transformSource);
if (xslfoTransformer != null) {
Fop fop;
try {
fop =
fopFactory.newFop(MimeConstants.MIME_PDF,
foUserAgent, outStream);
Result res = new SAXResult(fop.getDefaultHandler());
try {
xslfoTransformer.transform(source, res);
fileArray = outStream.toByteArray();
} catch (TransformerException e) {
// some error handling logic omitted
} catch (Exception e) {
// some error handling logic omitted
}
} catch (FOPException e) {
// some error handling logic omitted
}
}
} catch (TransformerFactoryConfigurationError e) {
// some error handling logic omitted
} catch (Exception e) {
// some error handling logic omitted
} finally {
if (null != xsltfile) {
xsltfile.close();
}
if (null != outStream) {
outStream.close();
}
}
return fileArray;
}
private static Transformer getTransformer(StreamSource streamSource) {
if (null==transformerFactory){
transformerFactory =
new net.sf.saxon.TransformerFactoryImpl();
}
try {
if (xlsProcessor == null) {
xlsProcessor =
transformerFactory.newTransformer(streamSource);
}
return xlsProcessor ;
} catch (TransformerConfigurationException e) {
// some error handling logic
}
return null;
}
我怀疑是否有任何代码问题导致了这个问题,因为它在本地可以正常工作。
如果对此有任何想法,将不胜感激!
显然您没有提供足够的信息来诊断问题,因此我们所能做的就是就如何进一步深入研究以获得一些诊断数据提供建议。如果您转到当前版本 (9.7),帮助会容易得多,甚至可能会解决问题。
检查转换是否正在向 W3C 服务器(或其他地方)发出任何 HTTP 请求。例如,获取常见的 DTD。 W3C 故意限制这些请求。 Saxon 的最新版本拦截这些请求并在 Saxon 软件中使用该文件的本地副本,但您使用的是非常旧的版本。您可以使用多种工具来监控 HTTP 流量。
运行 在没有任何 Apache FOP 处理的情况下自行转换以查看数字比较情况。您需要确定问题是在 XSLT 处理过程中还是在 XSL-FO 处理过程中,最好的方法是 运行 一个,一个不放。
检查从命令行 运行 自行转换时是否遇到相同的性能问题。
检查使用 -TP:profile.html 获得的 Saxon 执行配置文件,并查看结果在两台机器上的比较情况。
检查 Java 配置文件数据,例如使用 运行=hprof,看看它在两台机器上的比较。任何主要差异都为进一步调查提供了线索。
我在使用 saxon 和 apache fo 将 xml 转换为 PDF 时遇到性能问题。我们用来测试的 pdf 有 85 页,大约 320k。它在 transform 方法调用上花费了将近 2 分钟,而在本地只需要不到 5 秒。
我们在该方法调用期间监控 cpu 使用率和 GC,发现在服务器上,cpu 使用率稳定在 5%,并且我们对服务器端的 cpu 没有任何限制。 GC 每 1 到 2 秒发生一次,但它们都是次要 GC,每次只需要 10 到 50 毫秒。我们还在测试期间监控 io 等待,它保持在非常低的水平。
我们使用的库是:‖saxon 9.1 和 apache fop 2.1(我们测试了不同的 saxon 和 apache 版本,但问题仍然存在)
xml 和 xsl 文件太大,所以我无法 post 它们。下面是转换的示例代码:
public static TransformerFactory transformerFactory;
public static Transformer xlsProcessor;
public static byte[] generatePDF(InputStream xmlData, String xslFile)
throws TransformerException, IOException {
byte[] fileArray = null;
InputStream xsltfile = null;
ByteArrayOutputStream outStream = null;
try {
xsltfile =
XmlToPdfGenerator.class.getClassLoader()
.getResourceAsStream(xslFile);
StreamSource source = new StreamSource(xmlData);
StreamSource transformSource = new StreamSource(xsltfile);
if (null== fopFactory){
File xconf= new File(XmlToPdfGenerator.class.getClassLoader().getResource("a xconf file").getFile());
fopFactory = FopFactory.newInstance(xconf);
}
FOUserAgent foUserAgent = fopFactory.newFOUserAgent();
outStream = new ByteArrayOutputStream();
Transformer xslfoTransformer =
getTransformer(transformSource);
if (xslfoTransformer != null) {
Fop fop;
try {
fop =
fopFactory.newFop(MimeConstants.MIME_PDF,
foUserAgent, outStream);
Result res = new SAXResult(fop.getDefaultHandler());
try {
xslfoTransformer.transform(source, res);
fileArray = outStream.toByteArray();
} catch (TransformerException e) {
// some error handling logic omitted
} catch (Exception e) {
// some error handling logic omitted
}
} catch (FOPException e) {
// some error handling logic omitted
}
}
} catch (TransformerFactoryConfigurationError e) {
// some error handling logic omitted
} catch (Exception e) {
// some error handling logic omitted
} finally {
if (null != xsltfile) {
xsltfile.close();
}
if (null != outStream) {
outStream.close();
}
}
return fileArray;
}
private static Transformer getTransformer(StreamSource streamSource) {
if (null==transformerFactory){
transformerFactory =
new net.sf.saxon.TransformerFactoryImpl();
}
try {
if (xlsProcessor == null) {
xlsProcessor =
transformerFactory.newTransformer(streamSource);
}
return xlsProcessor ;
} catch (TransformerConfigurationException e) {
// some error handling logic
}
return null;
}
我怀疑是否有任何代码问题导致了这个问题,因为它在本地可以正常工作。 如果对此有任何想法,将不胜感激!
显然您没有提供足够的信息来诊断问题,因此我们所能做的就是就如何进一步深入研究以获得一些诊断数据提供建议。如果您转到当前版本 (9.7),帮助会容易得多,甚至可能会解决问题。
检查转换是否正在向 W3C 服务器(或其他地方)发出任何 HTTP 请求。例如,获取常见的 DTD。 W3C 故意限制这些请求。 Saxon 的最新版本拦截这些请求并在 Saxon 软件中使用该文件的本地副本,但您使用的是非常旧的版本。您可以使用多种工具来监控 HTTP 流量。
运行 在没有任何 Apache FOP 处理的情况下自行转换以查看数字比较情况。您需要确定问题是在 XSLT 处理过程中还是在 XSL-FO 处理过程中,最好的方法是 运行 一个,一个不放。
检查从命令行 运行 自行转换时是否遇到相同的性能问题。
检查使用 -TP:profile.html 获得的 Saxon 执行配置文件,并查看结果在两台机器上的比较情况。
检查 Java 配置文件数据,例如使用 运行=hprof,看看它在两台机器上的比较。任何主要差异都为进一步调查提供了线索。