blob: cb8b3b3e856e8622fa0757a9d0c539df02c896bb [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.wss4j.performance;
import org.apache.wss4j.common.ext.WSSecurityException;
import org.apache.wss4j.dom.handler.WSHandlerConstants;
import org.apache.xml.security.stax.securityEvent.SecurityEvent;
import org.apache.wss4j.stax.WSSec;
import org.apache.wss4j.stax.ext.InboundWSSec;
import org.apache.wss4j.stax.ext.OutboundWSSec;
import org.apache.wss4j.stax.ext.WSSConstants;
import org.apache.wss4j.stax.ext.WSSSecurityProperties;
import org.apache.wss4j.stax.test.CallbackHandlerImpl;
import org.apache.wss4j.stax.test.utils.XmlReaderToWriter;
import org.testng.annotations.*;
import org.w3c.dom.Document;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.*;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
public class PerformanceMemoryTest extends AbstractTestBase {
private FileWriter outSamples;
@BeforeClass
public void createDir() throws Exception {
new File("target/performanceMemoryTest").mkdirs();
}
@BeforeGroups(groups = {"memory-out"})
public void createSampleFileOut() throws Exception {
outSamples = new FileWriter("target/memory-out-samples.txt");
}
//warm up.
@BeforeMethod(groups = {"memory-out"})
public void setUpOut() throws Exception {
File input = genBigFile(1);
doDOMSecurityOutbound(input, new File("target/performanceMemoryTest/bigfile-dom.xml"));
doStreamingSecurityOutbound(input, new File("target/performanceMemoryTest/bigfile-stream.xml"));
}
@AfterGroups(groups = {"memory-out"})
public void tearDownOut() throws Exception {
outSamples.close();
}
@DataProvider(name = "xmlsizes")
public Object[][] getXMLSizes() throws Exception {
genBigFile(1);
int tagCount = 0;
File target = new File("target/performanceMemoryTest/tmp.xml");
XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(new BufferedInputStream(new FileInputStream(target)));
while (xmlStreamReader.hasNext()) {
int eventType = xmlStreamReader.next();
if (eventType == XMLStreamConstants.START_ELEMENT) {
tagCount++;
}
}
/*Object[][] objectArray = new Object[1][2];
objectArray[0][0] = 10;
objectArray[0][1] = (tagCount - 4) * 10;*/
int size = 16;
Object[][] objectArray = new Object[size][2];
for (int i = 0; i < size; i++) {
objectArray[i][0] = i + 1;
objectArray[i][1] = (tagCount - 4) * (i + 1) * 40;
}
return objectArray;
}
@BeforeGroups(groups = {"memory-out"}, dependsOnMethods = {"createSampleFileOut"})
public void printTagCountsOut() throws Exception {
Object[][] sizes = getXMLSizes();
for (int i = 0; i < sizes.length; i++) {
Object[] size = sizes[i];
outSamples.write("" + size[1] + " ");
}
}
@Test(groups = "memory-out", dataProvider = "xmlsizes", dependsOnMethods = {"doBeforeStreamOut"})
public void testOutStreamingMemoryPerformance(int run, int tagCount) throws Exception {
System.out.println("Run " + run);
File input = genBigFile(run * 40);
long startMem = getUsedMemory();
ThreadStopper threadStopper = new ThreadStopper();
Thread thread = new Thread(new MemorySamplerThread(threadStopper, outSamples, startMem));
thread.setPriority(9);
thread.start();
doStreamingSecurityOutbound(input, new File("target/performanceMemoryTest/stream-" + tagCount + ".xml"));
threadStopper.setStop(true);
thread.join();
}
@Test(groups = "memory-out", dataProvider = "xmlsizes", dependsOnMethods = {"doBeforeStreamCompressedOut"})
public void testOutStreamingCompressedMemoryPerformance(int run, int tagCount) throws Exception {
System.out.println("Run " + run);
File input = genBigFile(run * 40);
long startMem = getUsedMemory();
ThreadStopper threadStopper = new ThreadStopper();
Thread thread = new Thread(new MemorySamplerThread(threadStopper, outSamples, startMem));
thread.setPriority(9);
thread.start();
doStreamingSecurityOutboundCompressed(input, new File("target/performanceMemoryTest/stream-compressed-" + tagCount + ".xml"), "http://www.apache.org/2012/04/xmlsec/gzip");
threadStopper.setStop(true);
thread.join();
}
@Test(groups = "memory-out", dataProvider = "xmlsizes", dependsOnMethods = {"doBeforeDOMOut"})
public void testOutDOMMemoryPerformance(int run, int tagCount) throws Exception {
System.out.println("Run " + run);
File input = genBigFile(run * 40);
long startMem = getUsedMemory();
ThreadStopper threadStopper = new ThreadStopper();
Thread thread = new Thread(new MemorySamplerThread(threadStopper, outSamples, startMem));
thread.setPriority(9);
thread.start();
doDOMSecurityOutbound(input, new File("target/performanceMemoryTest/dom-" + tagCount + ".xml"));
threadStopper.setStop(true);
thread.join();
}
@Test(groups = {"memory-out"})
public void doBeforeDOMOut() throws Exception {
outSamples.write("\n");
}
@Test(groups = {"memory-out"})
public void doBeforeStreamOut() throws Exception {
outSamples.write("\n");
}
@Test(groups = {"memory-out"})
public void doBeforeStreamCompressedOut() throws Exception {
outSamples.write("\n");
}
@Test(groups = {"memory-in"})
public void doBeforeDOMIn() throws Exception {
inSamples.write("\n");
}
@Test(groups = {"memory-in"})
public void doBeforeStreamIn() throws Exception {
inSamples.write("\n");
}
@Test(groups = {"memory-in"})
public void doBeforeStreamCompressedIn() throws Exception {
inSamples.write("\n");
}
private FileWriter inSamples;
@BeforeGroups(groups = {"memory-in"})
public void createSampleFileIn() throws Exception {
inSamples = new FileWriter("target/memory-in-samples.txt");
}
//warm up.
@BeforeMethod(groups = {"memory-in"}, dependsOnGroups = {"memory-out"})
public void setUpIn() throws Exception {
genBigFile(1);
doDOMInSecurity(new File("target/performanceMemoryTest/bigfile-dom.xml"));
doStreamingInSecurity(new File("target/performanceMemoryTest/bigfile-stream.xml"));
}
@AfterGroups(groups = {"memory-in"})
public void tearDownIn() throws Exception {
inSamples.close();
}
@BeforeGroups(groups = {"memory-in"}, dependsOnMethods = {"createSampleFileIn"})
public void printTagCountsIn() throws Exception {
Object[][] sizes = getXMLSizes();
for (int i = 0; i < sizes.length; i++) {
Object[] size = sizes[i];
inSamples.write("" + size[1] + " ");
}
}
@Test(groups = "memory-in", dataProvider = "xmlsizes", dependsOnMethods = {"doBeforeStreamIn", "testOutStreamingMemoryPerformance"})
public void testInboundStreamingMemoryPerformance(int run, int tagCount) throws Exception {
System.out.println("Run " + run);
long startMem = getUsedMemory();
ThreadStopper threadStopper = new ThreadStopper();
Thread thread = new Thread(new MemorySamplerThread(threadStopper, inSamples, startMem));
thread.setPriority(9);
thread.start();
doStreamingInSecurity(new File("target/performanceMemoryTest/stream-" + tagCount + ".xml"));
threadStopper.setStop(true);
thread.join();
}
@Test(groups = "memory-in", dataProvider = "xmlsizes", dependsOnMethods = {"doBeforeStreamCompressedIn", "testOutStreamingCompressedMemoryPerformance"})
public void testInboundStreamingCompressedMemoryPerformance(int run, int tagCount) throws Exception {
System.out.println("Run " + run);
long startMem = getUsedMemory();
ThreadStopper threadStopper = new ThreadStopper();
Thread thread = new Thread(new MemorySamplerThread(threadStopper, inSamples, startMem));
thread.setPriority(9);
thread.start();
doStreamingInSecurity(new File("target/performanceMemoryTest/stream-compressed-" + tagCount + ".xml"));
threadStopper.setStop(true);
thread.join();
}
@Test(groups = "memory-in", dataProvider = "xmlsizes", dependsOnMethods = {"doBeforeDOMIn", "testOutDOMMemoryPerformance"})
public void testInboundDOMMemoryPerformance(int run, int tagCount) throws Exception {
System.out.println("Run " + run);
long startMem = getUsedMemory();
ThreadStopper threadStopper = new ThreadStopper();
Thread thread = new Thread(new MemorySamplerThread(threadStopper, inSamples, startMem));
thread.setPriority(9);
thread.start();
doDOMInSecurity(new File("target/performanceMemoryTest/dom-" + tagCount + ".xml"));
threadStopper.setStop(true);
thread.join();
}
private OutboundWSSec outboundWSSec;
private void doStreamingSecurityOutbound(File source, File output) throws Exception {
if (outboundWSSec == null) {
WSSSecurityProperties securityProperties = new WSSSecurityProperties();
securityProperties.setCallbackHandler(new CallbackHandlerImpl());
securityProperties.setEncryptionUser("receiver");
securityProperties.loadEncryptionKeystore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
securityProperties.setSignatureUser("transmitter");
securityProperties.loadSignatureKeyStore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
List<WSSConstants.Action> actions = new ArrayList<WSSConstants.Action>();
actions.add(WSSConstants.TIMESTAMP);
actions.add(WSSConstants.SIGNATURE);
actions.add(WSSConstants.ENCRYPT);
securityProperties.setActions(actions);
securityProperties.setTimestampTTL(60 * 60 * 24 * 7); //a week for testing:)
outboundWSSec = WSSec.getOutboundWSSec(securityProperties);
}
InputStream sourceDocument = new BufferedInputStream(new FileInputStream(source));
XMLStreamWriter xmlStreamWriter = outboundWSSec.processOutMessage(new BufferedOutputStream(new FileOutputStream(output)), "UTF-8", new ArrayList<>());
XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(sourceDocument);
XmlReaderToWriter.writeAll(xmlStreamReader, xmlStreamWriter);
xmlStreamWriter.close();
xmlStreamReader.close();
}
private OutboundWSSec outboundWSSecCompressed;
private void doStreamingSecurityOutboundCompressed(File source, File output, String compress) throws Exception {
if (outboundWSSecCompressed == null) {
WSSSecurityProperties securityProperties = new WSSSecurityProperties();
securityProperties.setCallbackHandler(new CallbackHandlerImpl());
securityProperties.setEncryptionUser("receiver");
securityProperties.loadEncryptionKeystore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
securityProperties.setSignatureUser("transmitter");
securityProperties.loadSignatureKeyStore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
List<WSSConstants.Action> actions = new ArrayList<WSSConstants.Action>();
actions.add(WSSConstants.TIMESTAMP);
actions.add(WSSConstants.SIGNATURE);
actions.add(WSSConstants.ENCRYPT);
securityProperties.setActions(actions);
securityProperties.setTimestampTTL(60 * 60 * 24 * 7); //a week for testing:)
securityProperties.setEncryptionCompressionAlgorithm(compress);
outboundWSSecCompressed = WSSec.getOutboundWSSec(securityProperties);
}
InputStream sourceDocument = new BufferedInputStream(new FileInputStream(source));
XMLStreamWriter xmlStreamWriter = outboundWSSecCompressed.processOutMessage(new BufferedOutputStream(new FileOutputStream(output)), "UTF-8", new ArrayList<>());
XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(sourceDocument);
XmlReaderToWriter.writeAll(xmlStreamReader, xmlStreamWriter);
xmlStreamWriter.close();
xmlStreamReader.close();
}
private void doDOMSecurityOutbound(File input, File output) throws WSSecurityException, FileNotFoundException, TransformerException {
Properties properties = new Properties();
properties.setProperty(WSHandlerConstants.ENC_SYM_ALGO, "http://www.w3.org/2001/04/xmlenc#aes256-cbc");
properties.setProperty(WSHandlerConstants.ENC_KEY_TRANSPORT, "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p");
properties.setProperty(WSHandlerConstants.TTL_TIMESTAMP, "" + 60 * 60 * 24 * 7);
Document doc = doOutboundSecurityWithWSS4J(new FileInputStream(input), WSHandlerConstants.TIMESTAMP + " " + WSHandlerConstants.SIGNATURE + " " + WSHandlerConstants.ENCRYPT, properties);
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.transform(new DOMSource(doc), new StreamResult(output));
}
private File genBigFile(int factor) throws IOException {
File target = new File("target/performanceMemoryTest/tmp.xml");
FileWriter fileWriter = new FileWriter(target, false);
fileWriter.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<env:Envelope xmlns:env=\"http://schemas.xmlsoap.org/soap/envelope/\">\n" +
"<env:Header></env:Header>\n" +
"<env:Body><test xmlns=\"http://www.example.com\">");
fileWriter.close();
FileOutputStream fileOutputStream = new FileOutputStream(target, true);
for (int i = 0; i < factor; i++) {
int read = 0;
byte[] buffer = new byte[4096];
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
while ((read = inputStream.read(buffer)) != -1) {
fileOutputStream.write(buffer, 0, read);
}
inputStream.close();
}
fileOutputStream.close();
fileWriter = new FileWriter(target, true);
fileWriter.write("</test></env:Body>\n" +
"</env:Envelope>");
fileWriter.close();
return target;
}
private void doDOMInSecurity(File input) throws Exception {
String action = WSHandlerConstants.TIMESTAMP + " " + WSHandlerConstants.SIGNATURE + " " + WSHandlerConstants.ENCRYPT;
Properties properties = new Properties();
properties.setProperty(WSHandlerConstants.TTL_TIMESTAMP, "" + 60 * 60 * 24 * 7);
doInboundSecurityWithWSS4J_1(documentBuilderFactory.newDocumentBuilder().parse(input), action, properties, false);
}
private InboundWSSec inboundWSSec;
private void doStreamingInSecurity(File input) throws Exception {
if (inboundWSSec == null) {
WSSSecurityProperties inSecurityProperties = new WSSSecurityProperties();
inSecurityProperties.setStrictTimestampCheck(false);
inSecurityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
inSecurityProperties.loadDecryptionKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
inSecurityProperties.setCallbackHandler(new CallbackHandlerImpl());
inboundWSSec = WSSec.getInboundWSSec(inSecurityProperties);
}
InputStream fileInputStream = new BufferedInputStream(new FileInputStream(input));
XMLStreamReader outXmlStreamReader = inboundWSSec.processInMessage(xmlInputFactory.createXMLStreamReader(fileInputStream));
while (outXmlStreamReader.hasNext()) {
outXmlStreamReader.next();
}
fileInputStream.close();
outXmlStreamReader.close();
}
private static void gc() {
System.gc();
System.runFinalization();
System.gc();
}
private static long getUsedMemory() {
gc();
gc();
long totalMemory = Runtime.getRuntime().totalMemory();
long freeMemory = Runtime.getRuntime().freeMemory();
return totalMemory - freeMemory;
}
class ThreadStopper {
private volatile boolean stop = false;
public boolean isStop() {
return stop;
}
public void setStop(boolean stop) {
this.stop = stop;
}
}
class MemorySamplerThread implements Runnable {
private ThreadStopper threadStopper;
private FileWriter fileWriter;
private long memoryDiff;
private List<Integer> memory = new LinkedList<Integer>();
MemorySamplerThread(ThreadStopper threadStopper, FileWriter fileWriter, long memoryDiff) {
this.threadStopper = threadStopper;
this.fileWriter = fileWriter;
this.memoryDiff = memoryDiff;
}
@Override
public void run() {
int sleepTime = 100;
while (!threadStopper.isStop()) {
try {
Thread.sleep(sleepTime);
if (threadStopper.isStop()) {
break;
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
//parentThread.suspend();
memory.add((int) (((getUsedMemory()) - memoryDiff) / 1024.0 / 1024.0));
//System.out.println("Sample: " + memory.get(memory.size() - 1));
//parentThread.resume();
}
System.out.println("Collected " + memory.size() + " samples");
int maxMem = Integer.MIN_VALUE;
for (int i = 0; i < memory.size(); i++) {
//System.out.println("Sample: " + memory.get(i));
int mem = memory.get(i);
maxMem = mem > maxMem ? mem : maxMem;
}
try {
fileWriter.write("" + maxMem + " ");
fileWriter.flush();
} catch (Exception e) {
throw new RuntimeException(e);
}
System.out.println("Max memory usage: " + maxMem + "MB");
}
}
}