我不相信我充分理解XsltTransformer类足以解释为什么方法f1优于f2。事实上,f1在大约40秒内完成,消耗750mbB和1GB内存。我期待f2是一个更好的解决方案,但它永远不会完成相同冗长的输入文件列表。当我杀了它时,它只处理了大约1000个输入文件,同时消耗了超过4GB的内存。
import java.io.*;
import javax.xml.transform.stream.StreamSource;
import net.sf.saxon.s9api.*;
public class foreachfile {
private static long f1 (Processor p, XsltExecutable e, Serializer ser, String args[]) {
long maxTotalMemory = 0;
Runtime rt = Runtime.getRuntime();
for (int i=1; i<args.length; i++) {
String xmlfile = args[i];
try {
XsltTransformer t = e.load();
t.setDestination(ser);
t.setInitialContextNode(p.newDocumentBuilder().build(new StreamSource(new File(xmlfile))));
t.transform();
long tm = rt.totalMemory();
if (tm > maxTotalMemory)
maxTotalMemory = tm;
} catch (Throwable ex) {
System.err.println(ex);
}
}
return maxTotalMemory;
}
private static long f2 (Processor p, XsltExecutable e, Serializer ser, String args[]) {
long maxTotalMemory = 0;
Runtime rt = Runtime.getRuntime();
XsltTransformer t = e.load();
t.setDestination(ser);
for (int i=1; i<args.length; i++) {
String xmlfile = args[i];
try {
t.setInitialContextNode(p.newDocumentBuilder().build(new StreamSource(new File(xmlfile))));
t.transform();
long tm = rt.totalMemory();
if (tm > maxTotalMemory)
maxTotalMemory = tm;
} catch (Throwable ex) {
System.err.println(ex);
}
}
return maxTotalMemory;
}
public static void main (String args[]) throws SaxonApiException, Exception {
String usecase = System.getProperty("xslt.usecase");
int uc = Integer.parseInt(usecase);
String xslfile = args[0];
Processor p = new Processor(true);
XsltCompiler c = p.newXsltCompiler();
XsltExecutable e = c.compile(new StreamSource(new File(xslfile)));
Serializer ser = new Serializer();
ser.setOutputStream(System.out);
long maxTotalMemory = uc == 1 ? f1(p, e, ser, args) : f2(p, e, ser, args);
System.err.println(String.format("Max total memory was %d", maxTotalMemory));
}
}
答案 0 :(得分:1)
我通常建议为每次转换使用新的XsltTransformer。但是,该类是可串行重用的(您可以一个接一个地执行多个转换,但不能同时执行)。 XsltTransformer将某些资源保留在内存中,以防再次需要它们:特别是,使用doc()或document()函数读取的所有文档。例如,如果要将一组输入文档转换为五种不同的输出格式(作为发布工作流程的一部分),这可能很有用。但是,如果这种资源的重用并没有给你带来任何好处,那么它只会增加内存使用成本,你可以通过每次创建一个新的变换器来避免这种成本。如果使用JAXP接口,则同样适用。