Skip to content

Commit ecd1092

Browse files
authored
Performance improvements (#106)
* Significantly reduce memory allocations in XMLParseUtil and ColorTable This was largely done by avoiding Pattern instantiation. Signed-off-by: Taylor Smock <[email protected]> * Update ant version Signed-off-by: Taylor Smock <[email protected]> * Add parent pom Signed-off-by: Taylor Smock <[email protected]> * Avoid NumberCharState instantiations by (effectively) inlining it Signed-off-by: Taylor Smock <[email protected]> --------- Signed-off-by: Taylor Smock <[email protected]>
1 parent 9df50c7 commit ecd1092

File tree

8 files changed

+65
-41
lines changed

8 files changed

+65
-41
lines changed

pom.xml

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
2+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
3+
<modelVersion>4.0.0</modelVersion>
4+
<groupId>com.github.blackears</groupId>
5+
<artifactId>svgSalamanderParent</artifactId>
6+
<version>1.1.5-SNAPSHOT</version>
7+
<packaging>pom</packaging>
8+
<modules>
9+
<module>svg-core</module>
10+
<module>svg-example</module>
11+
</modules>
12+
</project>

svg-core/pom.xml

+9-4
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,17 @@
44
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
55
<modelVersion>4.0.0</modelVersion>
66

7-
<groupId>com.github.blackears</groupId>
7+
<parent>
8+
<groupId>com.github.blackears</groupId>
9+
<artifactId>svgSalamanderParent</artifactId>
10+
<version>1.1.5-SNAPSHOT</version>
11+
<relativePath>../pom.xml</relativePath>
12+
</parent>
13+
814
<artifactId>svgSalamander</artifactId>
9-
<version>1.1.5</version>
1015
<packaging>jar</packaging>
1116

12-
<name>com.github.blackears:svgSalamander</name>
17+
<name>${groupId}:${artifactId}</name>
1318
<description>A tool for displaying and playing SVG content using the Java2D.</description>
1419
<url>https://github.com/blackears/svgSalamander</url>
1520

@@ -68,7 +73,7 @@
6873
<dependency>
6974
<groupId>org.apache.ant</groupId>
7075
<artifactId>ant</artifactId>
71-
<version>1.9.13</version>
76+
<version>1.10.13</version>
7277
<optional>true</optional>
7378
</dependency>
7479
</dependencies>

svg-core/src/main/java/com/kitfox/svg/pathcmd/PathParser.java

+22-8
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,16 @@
4444
*/
4545
public class PathParser
4646
{
47+
/*
48+
* This was part of NumberCharState. Unfortunately, it is not inlined as of Java 20. Maybe when Java has value
49+
* classes this will change.
50+
*/
51+
int iteration = 0;
52+
boolean dotAllowed = true;
53+
boolean signAllowed = true;
54+
boolean exponentAllowed = true;
55+
/* End NumberCharState class information */
56+
4757
private final String input;
4858
private final int inputLength;
4959
private int index;
@@ -82,7 +92,7 @@ private boolean hasNext()
8292
// This only checks for the rough structure of a number as we need to know
8393
// when to separate the next token.
8494
// Explicit parsing is done by Float#parseFloat.
85-
private boolean isValidNumberChar(char c, NumberCharState state)
95+
private boolean isValidNumberChar(char c, PathParser state)
8696
{
8797
boolean valid = '0' <= c && c <= '9';
8898
if (valid && state.iteration == 1 && input.charAt(index - 1) == '0')
@@ -121,7 +131,7 @@ private void consumeWhiteSpaceOrSeparator() {
121131
private float nextFloat()
122132
{
123133
int start = index;
124-
NumberCharState state = new NumberCharState();
134+
PathParser state = this.resetNumberCharState();
125135
while (hasNext() && isValidNumberChar(peek(), state)) {
126136
consume();
127137
}
@@ -241,11 +251,15 @@ public PathCommand[] parsePathCommand()
241251
return commands.toArray(new PathCommand[0]);
242252
}
243253

244-
private static class NumberCharState
245-
{
246-
int iteration = 0;
247-
boolean dotAllowed = true;
248-
boolean signAllowed = true;
249-
boolean exponentAllowed = true;
254+
/**
255+
* Reset the NumberCharState
256+
* @return {this}, for ease of changing back to a NumberCharState class later.
257+
*/
258+
private PathParser resetNumberCharState() {
259+
this.iteration = 0;
260+
this.dotAllowed = true;
261+
this.signAllowed = true;
262+
this.exponentAllowed = true;
263+
return this;
250264
}
251265
}

svg-core/src/main/java/com/kitfox/svg/xml/ColorTable.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@
4848
public class ColorTable
4949
{
5050

51+
private static final String NUMBER_REGEX = "\\s*(((\\d+)(\\.\\d*)?)|(\\.\\d+))(%)?\\s*";
52+
private static final Pattern PATTERN_RGB = Pattern.compile("rgb\\(" + NUMBER_REGEX + "," + NUMBER_REGEX + "," + NUMBER_REGEX + "\\)", Pattern.CASE_INSENSITIVE);
53+
5154
static final Map<String, Color> colorTable;
5255
static {
5356
HashMap<String, Color> table = new HashMap<String, Color>();
@@ -240,10 +243,7 @@ public static Color parseColor(String val)
240243
}
241244
else
242245
{
243-
final String number = "\\s*(((\\d+)(\\.\\d*)?)|(\\.\\d+))(%)?\\s*";
244-
final Matcher rgbMatch = Pattern.compile("rgb\\(" + number + "," + number + "," + number + "\\)", Pattern.CASE_INSENSITIVE).matcher("");
245-
246-
rgbMatch.reset(val);
246+
final Matcher rgbMatch = PATTERN_RGB.matcher(val);
247247
if (rgbMatch.matches())
248248
{
249249
float rr = Float.parseFloat(rgbMatch.group(1));

svg-core/src/main/java/com/kitfox/svg/xml/StyleAttribute.java

+4-3
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ public class StyleAttribute implements Serializable
5252
{
5353
public static final long serialVersionUID = 0;
5454

55+
private static final Pattern PATTERN_WHITESPACE = Pattern.compile("\\s+");
56+
private static final Pattern PATTERN_JDK_5_WORKAROUND = Pattern.compile("[a-zA-Z]:!\\\\.*");
5557
static final Pattern patternUrl = Pattern.compile("\\s*url\\((.*)\\)\\s*");
5658
static final Pattern patternFpNumUnits = Pattern.compile("\\s*([-+]?((\\d*\\.\\d+)|(\\d+))([-+]?[eE]\\d+)?)\\s*(px|cm|mm|in|pc|pt|em|ex)\\s*");
5759
String name;
@@ -262,13 +264,12 @@ public URI getURIValue(URI base)
262264
{
263265
try {
264266
String fragment = parseURLFn();
265-
if (fragment == null) fragment = stringValue.replaceAll("\\s+", "");
267+
if (fragment == null) fragment = PATTERN_WHITESPACE.matcher(stringValue).replaceAll("");
266268
if (fragment == null) return null;
267269

268270
//======================
269271
//This gets around a bug in the 1.5.0 JDK
270-
if (Pattern.matches("[a-zA-Z]:!\\\\.*", fragment))
271-
{
272+
if (PATTERN_JDK_5_WORKAROUND.matcher(fragment).matches()) {
272273
File file = new File(fragment);
273274
return file.toURI();
274275
}

svg-core/src/main/java/com/kitfox/svg/xml/XMLParseUtil.java

+6-7
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@
5252
*/
5353
public class XMLParseUtil
5454
{
55+
private static final Pattern PATTERN_WHITESPACE = Pattern.compile("[^\\s]+");
56+
private static final Pattern PATTERN_SEMI_COLON = Pattern.compile(";");
5557
static final Pattern fpPat = Pattern.compile("([-+]?((\\d*\\.\\d+)|(\\d+))([eE][+-]?\\d+)?)(\\%|in|cm|mm|pt|pc|px|em|ex)?");
5658
static final Pattern intPat = Pattern.compile("[-+]?\\d+");
5759
static final Pattern quotePat = Pattern.compile("^'|'$");
@@ -103,9 +105,7 @@ public static Element getFirstChild(Element root, String name)
103105

104106
public static String[] parseStringList(String list)
105107
{
106-
// final Pattern patWs = Pattern.compile("\\s+");
107-
final Matcher matchWs = Pattern.compile("[^\\s]+").matcher("");
108-
matchWs.reset(list);
108+
final Matcher matchWs = PATTERN_WHITESPACE.matcher(list);
109109

110110
LinkedList<String> matchList = new LinkedList<String>();
111111
while (matchWs.find())
@@ -735,7 +735,7 @@ public static int[] getElementArrayInt(Element root, String name, String attrib)
735735
try { eleVal = Integer.parseInt(valS); }
736736
catch (Exception e) {}
737737

738-
elementCache.addLast(new Integer(eleVal));
738+
elementCache.addLast(Integer.valueOf(eleVal));
739739
}
740740

741741
int[] retArr = new int[elementCache.size()];
@@ -801,13 +801,12 @@ public static HashMap<String, StyleAttribute> parseStyle(String styleString) {
801801
* @param map - A map to which these styles will be added
802802
*/
803803
public static HashMap<String, StyleAttribute> parseStyle(String styleString, HashMap<String, StyleAttribute> map) {
804-
final Pattern patSemi = Pattern.compile(";");
805804

806-
String[] styles = patSemi.split(styleString);
805+
String[] styles = PATTERN_SEMI_COLON.split(styleString);
807806

808807
for (int i = 0; i < styles.length; i++)
809808
{
810-
if (styles[i].length() == 0)
809+
if (styles[i].isEmpty())
811810
{
812811
continue;
813812
}

svg-core/src/main/java/module-info.java

-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626

2727
module com.kitfox.svgSalamander {
2828
requires static ant;
29-
requires static ant.launcher;
3029
requires java.desktop;
3130
requires java.xml;
3231
requires java.logging;

svg-example/pom.xml

+8-14
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,14 @@
33
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
44
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
55
<modelVersion>4.0.0</modelVersion>
6+
<parent>
7+
<groupId>com.github.blackears</groupId>
8+
<artifactId>svgSalamanderParent</artifactId>
9+
<version>1.1.5-SNAPSHOT</version>
10+
<relativePath>../pom.xml</relativePath>
11+
</parent>
612

7-
<groupId>com.github.blackears</groupId>
813
<artifactId>svgSalamander-examples</artifactId>
9-
<version>1.1.5-SNAPSHOT</version>
1014
<packaging>jar</packaging>
1115

1216
<name>com.kitfox:svgSalamander Examples</name>
@@ -55,20 +59,10 @@
5559
</testResources>
5660
</build>
5761
<dependencies>
58-
<!--
59-
<dependency>
60-
<groupId>${project.groupId}</groupId>
61-
<artifactId>svgSalamander</artifactId>
62-
<version>1.1.5</version>
63-
</dependency>
64-
-->
6562
<dependency>
66-
<groupId>${project.groupId}</groupId>
63+
<groupId>${groupId}</groupId>
6764
<artifactId>svgSalamander</artifactId>
68-
<version>1.1.5</version>
69-
<scope>system</scope>
70-
<systemPath>${project.basedir}/../svg-core/target/svgSalamander-1.1.5.jar</systemPath>
65+
<version>${version}</version>
7166
</dependency>
72-
7367
</dependencies>
7468
</project>

0 commit comments

Comments
 (0)