]> source.dussan.org Git - vaadin-framework.git/commitdiff
Using StringTokenizer instead of String.split() in AbstractComponent (#8759)
authorFabian Lange <lange.fabian@gmail.com>
Mon, 10 Jun 2013 09:12:20 +0000 (11:12 +0200)
committerVaadin Code Review <review@vaadin.com>
Wed, 12 Jun 2013 13:37:52 +0000 (13:37 +0000)
Avoids wasteful creation and parsing of regular expressions, which are not required here.

Change-Id: I247088fbfc4eca6c2500bd6b4da9afc9d66d0a51

server/src/com/vaadin/ui/AbstractComponent.java
server/tests/src/com/vaadin/benchmarks/PerformanceTester8759.java [new file with mode: 0644]

index 772a26bda290d9ad116ad2df23b47c42536d2bd9..262d47af18cbee83b2114c1064d9fd0137449a93 100644 (file)
@@ -22,6 +22,7 @@ import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
+import java.util.StringTokenizer;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -176,11 +177,9 @@ public abstract class AbstractComponent extends AbstractClientConnector
         }
         List<String> styles = getState().styles;
         styles.clear();
-        String[] styleParts = style.split(" +");
-        for (String part : styleParts) {
-            if (part.length() > 0) {
-                styles.add(part);
-            }
+        StringTokenizer tokenizer = new StringTokenizer(style, " ");
+        while (tokenizer.hasMoreTokens()) {
+            styles.add(tokenizer.nextToken());
         }
     }
 
@@ -201,8 +200,9 @@ public abstract class AbstractComponent extends AbstractClientConnector
         }
         if (style.contains(" ")) {
             // Split space separated style names and add them one by one.
-            for (String realStyle : style.split(" ")) {
-                addStyleName(realStyle);
+            StringTokenizer tokenizer = new StringTokenizer(style, " ");
+            while (tokenizer.hasMoreTokens()) {
+                addStyleName(tokenizer.nextToken());
             }
             return;
         }
@@ -219,11 +219,9 @@ public abstract class AbstractComponent extends AbstractClientConnector
     @Override
     public void removeStyleName(String style) {
         if (ComponentStateUtil.hasStyles(getState())) {
-            String[] styleParts = style.split(" +");
-            for (String part : styleParts) {
-                if (part.length() > 0) {
-                    getState().styles.remove(part);
-                }
+            StringTokenizer tokenizer = new StringTokenizer(style, " ");
+            while (tokenizer.hasMoreTokens()) {
+                getState().styles.remove(tokenizer.nextToken());
             }
         }
     }
diff --git a/server/tests/src/com/vaadin/benchmarks/PerformanceTester8759.java b/server/tests/src/com/vaadin/benchmarks/PerformanceTester8759.java
new file mode 100644 (file)
index 0000000..968edd4
--- /dev/null
@@ -0,0 +1,52 @@
+package com.vaadin.benchmarks;
+
+import com.vaadin.ui.Label;
+
+/*
+ * This simple test shows the performance difference between the StringTokenizer implementation and the String.split() implementation in AbstractComponent.
+ * Your results will vary.
+ * The real world use case motivating it was a 10k Row table, which generated labels for 10 columns. 
+ * This is 1/10th of what this performance tester demonstrates.
+ * 
+ * Please run with -server and -Xloggc:/tmp/gclog.vgc -verbose:gc -XX:+PrintCompilation
+ * 
+ * My results Win 7 64, i7 2760QM 2.4Ghz, Java 7 21.
+ * 
+ * Proposed Patch with StringTokenizer:
+ * 13 GC activations, 1.009GB allocated memory over time, total time 948ms
+ * 
+ * Current String.split implementation:
+ * 31 GC activations, 2.277 GB allocated memory over time, total time 1557ms
+ * 
+ */
+public class PerformanceTester8759 {
+
+    public static void main(String[] args) throws InterruptedException {
+        warmup();
+
+        long start = System.currentTimeMillis();
+        runBenchmark(1000000);
+        long end = System.currentTimeMillis();
+        System.out.println("took " + (end - start) + " ms");
+
+    }
+
+    private static void warmup() throws InterruptedException {
+        runBenchmark(10000);
+        System.gc();
+        System.out.println("warmup and gc complete. sleeping 5 seconds.");
+        Thread.sleep(5000l);
+        System.out.println("woke up - go.");
+    }
+
+    private static void runBenchmark(int loops) {
+        Label label = null;
+        for (int i = 0; i < loops; i++) {
+            label = new Label();
+            label.setStyleName("mainStyle");
+            label.addStyleName("foo bar  baz");
+            label.addStyleName("vaadin");
+        }
+    }
+
+}