Improve memory effeciency (#22)

#20 Use s9api only for internal processing; 
Improve memory effeciency
This commit is contained in:
apenski 2019-02-13 08:19:02 +01:00 committed by GitHub
parent aacbce522b
commit 34d79d5e2c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 326 additions and 202 deletions

View file

@ -19,24 +19,29 @@
package de.kosit.validationtool.cmd;
import de.kosit.validationtool.cmd.assertions.AssertionType;
import de.kosit.validationtool.cmd.assertions.Assertions;
import de.kosit.validationtool.impl.model.Result;
import de.kosit.validationtool.impl.tasks.CheckAction;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.sf.saxon.s9api.*;
import org.apache.commons.lang3.StringUtils;
import org.w3c.dom.Document;
import javax.xml.transform.dom.DOMSource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import de.kosit.validationtool.cmd.assertions.AssertionType;
import de.kosit.validationtool.cmd.assertions.Assertions;
import de.kosit.validationtool.impl.model.Result;
import de.kosit.validationtool.impl.tasks.CheckAction;
import net.sf.saxon.s9api.Processor;
import net.sf.saxon.s9api.SaxonApiException;
import net.sf.saxon.s9api.XPathCompiler;
import net.sf.saxon.s9api.XPathSelector;
import net.sf.saxon.s9api.XdmNode;
/**
* Überprüft den Report mittels bereitgestellter Assertions. Diese {@link CheckAction} dient der Überprüfung der von der
* KoSIT bereitgestellten Prüfszenarien und den darin enthaltenen Artefakten.
@ -64,7 +69,7 @@ public class CheckAssertionAction implements CheckAction {
final List<AssertionType> toCheck = findAssertions(results.getName());
final List<String> errors = new ArrayList<>();
if (toCheck != null && !toCheck.isEmpty()) {
final XdmNode node = loadDocument(results.getReport());
final XdmNode node = results.getReport();
toCheck.forEach(a -> {
if (!check(node, a)) {
log.error("Assertion mismatch: {}", a.getValue());
@ -86,15 +91,6 @@ public class CheckAssertionAction implements CheckAction {
return getMapped().entrySet().stream().filter(e -> matches(e.getKey(), name)).map(Map.Entry::getValue).findFirst().orElse(null);
}
private XdmNode loadDocument(Document d) {
DocumentBuilder documentBuilder = getProcessor().newDocumentBuilder();
try {
return documentBuilder.build(new DOMSource(d));
} catch (SaxonApiException e) {
log.error("Can not load result document. Therefore can not run defined assertions", e);
}
return null;
}
private boolean check(XdmNode document, AssertionType assertion) {
try {

View file

@ -77,6 +77,8 @@ public class CommandLineApplication {
private static final Option CHECK_ASSERTIONS = Option.builder("c").longOpt("check-assertions").hasArg()
.desc("Check the result using defined assertions").argName("assertions-file").build();
private static final Option PRINT_MEM_STATS = Option.builder("m").longOpt("memory-stats").desc("Prints some memory stats").build();
private CommandLineApplication() {
// main class -> hide constructor
}
@ -151,6 +153,9 @@ public class CommandLineApplication {
Assertions assertions = loadAssertions(cmd.getOptionValue(CHECK_ASSERTIONS.getOpt()));
check.getCheckSteps().add(new CheckAssertionAction(assertions, ObjectFactory.createProcessor()));
}
if (cmd.hasOption(PRINT_MEM_STATS.getOpt())) {
check.getCheckSteps().add(new PrintMemoryStats());
}
log.info("Setup completed in {}ms\n", System.currentTimeMillis() - start);
@ -226,7 +231,7 @@ public class CommandLineApplication {
try {
return Files.list(d).filter(path -> path.toString().endsWith(".xml")).collect(Collectors.toList());
} catch (IOException e) {
throw new IllegalStateException("IOException while liste directory content. Can not determine test targets.", e);
throw new IllegalStateException("IOException while list directory content. Can not determine test targets.", e);
}
}
@ -293,6 +298,7 @@ public class CommandLineApplication {
options.addOption(EXTRACT_HTML);
options.addOption(DEBUG);
options.addOption(CHECK_ASSERTIONS);
options.addOption(PRINT_MEM_STATS);
return options;
}
}

View file

@ -23,15 +23,19 @@ import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;
import javax.xml.transform.dom.DOMSource;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import de.kosit.validationtool.impl.ContentRepository;
import de.kosit.validationtool.impl.tasks.CheckAction;
import net.sf.saxon.s9api.*;
import net.sf.saxon.s9api.QName;
import net.sf.saxon.s9api.SaxonApiException;
import net.sf.saxon.s9api.Serializer;
import net.sf.saxon.s9api.XPathExecutable;
import net.sf.saxon.s9api.XPathSelector;
import net.sf.saxon.s9api.XdmItem;
import net.sf.saxon.s9api.XdmNode;
/**
* Extrahiert HTML-Dokumente aus dem Report und persistiert diese im konfigurierten Ausgabe-Verzeichnis.
@ -54,9 +58,7 @@ public class ExtractHtmlContentAction implements CheckAction {
public void check(Bag results) {
try {
final XPathSelector selector = getSelector();
DocumentBuilder documentBuilder = repository.getProcessor().newDocumentBuilder();
final XdmNode xdmSource = documentBuilder.build(new DOMSource(results.getReport()));
final XdmNode xdmSource = results.getReport();
selector.setContextItem(xdmSource);
selector.forEach(m -> print(results.getName(), m));

View file

@ -26,6 +26,8 @@ import de.kosit.validationtool.api.Input;
import de.kosit.validationtool.impl.DefaultCheck;
import de.kosit.validationtool.impl.tasks.CheckAction;
import net.sf.saxon.s9api.XdmNode;
/**
* Simple Erweiterung der Klasse {@link DefaultCheck} um das Ergebnis der Assertion-Prüfung auszwerten und auszugeben.
* Diese Klasse stellt keine fachlicher Erweiterung des eigentlichen Prüfvorganges dar!
@ -54,16 +56,17 @@ class InternalCheck extends DefaultCheck {
* @param input die Prüflinge
* @return false wenn es Assertion-Fehler gibt, sonst true
*/
void checkInput(Input input) {
public XdmNode checkInput(Input input) {
CheckAction.Bag bag = new CheckAction.Bag(input, createReport());
runCheckInternal(bag);
XdmNode result = runCheckInternal(bag);
if (bag.getAssertionResult() != null) {
checkAssertions += bag.getAssertionResult().getObject();
failedAssertions += bag.getAssertionResult().getErrors().size();
}
return result;
}
public boolean printAndEvaluate() {
boolean printAndEvaluate() {
if (failedAssertions > 0) {
log.error("Assertion check failed.\n\nAssertions run: {}, Assertions failed: {}\n", checkAssertions, failedAssertions);
} else if (checkAssertions > 0) {

View file

@ -0,0 +1,52 @@
/*
* Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under
* one or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. KoSIT 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 de.kosit.validationtool.cmd;
import java.text.NumberFormat;
import lombok.extern.slf4j.Slf4j;
/**
*
* Prints some memory usage information for debugging purposes.
*
* @author Andreas Penski
*/
@Slf4j
public class PrintMemoryStats implements de.kosit.validationtool.impl.tasks.CheckAction {
private static final int BYTES_PER_K = 1024;
@Override
public void check(final Bag results) {
final Runtime runtime = Runtime.getRuntime();
long maxMemory = runtime.maxMemory();
long allocatedMemory = runtime.totalMemory();
long freeMemory = runtime.freeMemory();
NumberFormat format = NumberFormat.getInstance();
final String freeStr = format.format(freeMemory / BYTES_PER_K);
final String allocStr = format.format(allocatedMemory / BYTES_PER_K);
final String maxStr = format.format(maxMemory / BYTES_PER_K);
final String totalFreeStr = format.format((freeMemory + (maxMemory - allocatedMemory)) / BYTES_PER_K);
log.info("free memory: {}MB; allocated memory: {}MB", freeStr, allocStr);
log.info("max memory: {}MB; total free memory: {}MB", maxStr, totalFreeStr);
}
}

View file

@ -21,18 +21,14 @@ package de.kosit.validationtool.cmd;
import java.io.StringWriter;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import lombok.extern.slf4j.Slf4j;
import de.kosit.validationtool.impl.ObjectFactory;
import de.kosit.validationtool.impl.tasks.CheckAction;
import net.sf.saxon.s9api.SaxonApiException;
import net.sf.saxon.s9api.Serializer;
/**
* Gibt das Ergebnis-Document auf std-out aus.
*
@ -44,13 +40,11 @@ public class PrintReportAction implements CheckAction {
@Override
public void check(Bag results) {
try {
Transformer transformer = ObjectFactory.createTransformer(true);
final StringWriter writer = new StringWriter();
Result output = new StreamResult(writer);
Source input = new DOMSource(results.getReport());
transformer.transform(input, output);
final Serializer serializer = ObjectFactory.createProcessor().newSerializer(writer);
serializer.serializeNode(results.getReport());
System.out.print(writer.toString());
} catch (TransformerException e) {
} catch (SaxonApiException e) {
log.error("Error while printing result to stdout", e);
}
}

View file

@ -19,18 +19,16 @@
package de.kosit.validationtool.cmd;
import de.kosit.validationtool.impl.ObjectFactory;
import de.kosit.validationtool.impl.tasks.CheckAction;
import java.nio.file.Path;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.nio.file.Path;
import de.kosit.validationtool.impl.ObjectFactory;
import de.kosit.validationtool.impl.tasks.CheckAction;
import net.sf.saxon.s9api.SaxonApiException;
import net.sf.saxon.s9api.Serializer;
/**
* Schreibt das Prüfergebnis als XML-Dokument an eine definierte Stelle.
@ -48,11 +46,9 @@ public class SerializeReportAction implements CheckAction {
final Path file = outputDirectory.resolve(results.getName() + "-report.xml");
try {
log.info("Serializing result to {}", file.toAbsolutePath());
Transformer transformer = ObjectFactory.createTransformer(true);
Result output = new StreamResult(file.toFile());
Source input = new DOMSource(results.getReport());
transformer.transform(input, output);
} catch (TransformerException e) {
final Serializer serializer = ObjectFactory.createProcessor().newSerializer(file.toFile());
serializer.serializeNode(results.getReport());
} catch (SaxonApiException e) {
log.error("Can not serialize result report to {}", file.toAbsolutePath(), e);
}
}