Search code examples
javamultithreadingperformancexsltsaxon

how can I use net.sf.saxon.s9api.XsltTransformer in multiple threads to avoid impacting perfromance and throughput?


In my project I am trying to use net.sf.saxon.s9api.XsltTransformer in multiple threads using synchronization in java because as per documentation An XsltTransformer must not be used concurrently in multiple threads. It is safe, however, to reuse the object within a single thread to run the same stylesheet several times. Running the stylesheet does not change the context that has been established. Some of the public methods are synchronized: this is not because multi-threaded execution is supported, rather it is to reduce the damage if multi-threaded execution is attempted. but while trying to make stress test using JMeter by sending 100 request per second I found that net.sf.saxon.s9api.XsltTransformer.transform() takes more time and sometimes reach to 6 mins. How can I use net.sf.saxon.s9api.XsltTransformer.transform() in multiple threads without impacting performance?

I tried to make class TransformerSingleton as below

public class TransformerSingleton {

    private static XsltTransformer transformer;

    private TransformerSingleton() {

    }

    public static void xsltLoad() {

        if (transformer == null) {
            synchronized (XsltTransformer.class){
                try {
                    Processor processor = new Processor(false);
                    XsltCompiler compiler = processor.newXsltCompiler();
                    XsltExecutable xslt = compiler.compile(new StreamSource("/my_path/"));
                    transformer = xslt.load();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static XsltTransformer getTransformer(){
        if (transformer == null) {
            synchronized (XsltTransformer.class) {
                xsltLoad();
            }

        } return transformer;

    }

}
public static void main(String[] args) {
        XsltTransformer transformer = XsltTransformerSingleton.getTransformer();
        String xml = "<Users><name>AAA</name></Users>"; // for example
        try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(xml.getBytes())) {
            synchronized (transformer){
           Transformer.setSource(new StreamSource(byteArrayInputStream));
            XdmDestination chainResult = new XdmDestination();
            Transformer.setDestination(chainResult);
            Transformer.transform();
            }
        }
    }

expected to make throughput reach to 100 requests per second. actual I reached to 60 per second.


Solution

  • The way to run the same stylesheet in parallel in multiple threads is to compile the stylesheet once into an XsltExecutable, and then create a new XsltTransformer for each transformation. Creating an XsltTransformer from an XsltExecutable is very cheap.