From 29e16df0576f33c86d529643dc1cc965e90fc89c Mon Sep 17 00:00:00 2001 From: David Date: Tue, 28 Mar 2017 22:21:35 +0200 Subject: [PATCH] Improve escaper performance --- pom.xml | 6 +++ src/main/java/j2html/utils/SimpleEscaper.java | 42 +++++++++------- src/test/java/j2html/PerformanceTest.java | 49 +++++++++++++++++++ 3 files changed, 80 insertions(+), 17 deletions(-) create mode 100644 src/test/java/j2html/PerformanceTest.java diff --git a/pom.xml b/pom.xml index 2950fc9..34ce6bb 100644 --- a/pom.xml +++ b/pom.xml @@ -52,6 +52,12 @@ 1.3 test + + org.apache.commons + commons-lang3 + 3.0 + test + jar diff --git a/src/main/java/j2html/utils/SimpleEscaper.java b/src/main/java/j2html/utils/SimpleEscaper.java index 00d53a0..b710f91 100644 --- a/src/main/java/j2html/utils/SimpleEscaper.java +++ b/src/main/java/j2html/utils/SimpleEscaper.java @@ -1,28 +1,36 @@ package j2html.utils; -import java.util.HashMap; -import java.util.Map; - public class SimpleEscaper { - private static Map map = new HashMap() {{ - put('&', "&"); - put('<', "<"); - put('>', ">"); - put('"', """); - put('\'', "'"); - }}; - public static String escape(String s) { - if(s == null) { + if (s == null) { return null; } - String escapedString = ""; - for(char c : s.toCharArray()) { - String escaped = map.get(c); - escapedString += escaped != null ? escaped : c; + StringBuilder escapedText = new StringBuilder(); + char currentChar; + for (int i = 0; i < s.length(); i++) { + currentChar = s.charAt(i); + switch (currentChar) { + case '<': + escapedText.append("<"); + break; + case '>': + escapedText.append(">"); + break; + case '&': + escapedText.append("&"); + break; + case '"': + escapedText.append("""); + break; + case '\'': + escapedText.append("'"); + break; + default: + escapedText.append(currentChar); + } } - return escapedString; + return escapedText.toString(); } } diff --git a/src/test/java/j2html/PerformanceTest.java b/src/test/java/j2html/PerformanceTest.java new file mode 100644 index 0000000..b6476b1 --- /dev/null +++ b/src/test/java/j2html/PerformanceTest.java @@ -0,0 +1,49 @@ +package j2html; + +import java.util.concurrent.Callable; + +import org.apache.commons.lang3.StringEscapeUtils; +import org.junit.Test; + +import j2html.utils.SimpleEscaper; + +public class PerformanceTest { + + private String shortTestString = "\n" + + "

Heading!

\n" + + " \n" + + ""; + + // syntax-highlighted getting started example from j2html.com: + private String longTestString = + "
import static j2html.TagCreator.*;\n"
+                    + "\n"
+                    + "public class Main {\n"
+                    + "    public static void main(String[] args) {\n"
+                    + "        body().with(\n"
+                    + "                h1(\"Heading!\").withClass(\"example\"),\n"
+                    + "                img().withSrc(\"img/hello.png\")\n"
+                    + "        ).render();\n"
+                    + "    }\n"
+                    + "}\n"
+                    + "
"; + + @Test + public void test_escaper_performnce() throws Exception { + timeEscaper("SimpleEscaper#short", () -> SimpleEscaper.escape(shortTestString)); + timeEscaper("SimpleEscaper#long", () -> SimpleEscaper.escape(longTestString)); + timeEscaper("ApacheEscaper#short", () -> StringEscapeUtils.escapeHtml4(shortTestString)); + timeEscaper("ApacheEscaper#long", () -> StringEscapeUtils.escapeHtml4(longTestString)); + } + + private void timeEscaper(String name, Callable escaper) throws Exception { + long startTime = System.nanoTime(); + for (int i = 0; i < 1000; i++) { + escaper.call(); + } + long endTime = System.nanoTime(); + long durationMs = (endTime - startTime) / 1000000; + System.out.println(String.format("%-21s%s", name + ":", +durationMs + "ms")); + } + +}