net.sf.saxon.s9api.XsltTransformer 是一次性使用的吗?

Is net.sf.saxon.s9api.XsltTransformer designed for one time use?

我认为我对 XsltTransformer class 的理解不足以解释为什么方法 f1 优于 f2。事实上,f1 在大约 40 秒内完成,消耗了 750mb 到 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));
    }
}

我通常建议为每个转换使用一个新的 XsltTransformer。然而,class 是连续可重用的(您可以一个接一个地执行多个转换,但不能同时执行)。 XsltTransformer 将某些资源保存在内存中,以备再次需要时使用:特别是使用 doc() 或 document() 函数读取的所有文档。这可能很有用,例如,如果您想要将一组输入文档转换为五种不同的输出格式作为发布工作流程的一部分。但是,如果这种资源重用不会给您带来任何好处,它只会增加内存使用成本,您可以通过每次创建一个新转换器来避免这种情况。如果您使用 JAXP 接口,同样适用。