Re: GWT vs js performance: Collections and Strings
Have you done any testing with JsArray or JsArrayOf ? Le mardi 5 mai 2015 14:34:46 UTC+2, Vassilis Virvilis a écrit : Hi, At some point in time I needed to handle lzw compressing/uncompressing in the client so I found https://gist.github.com/revolunet/843889 Later on I rewrite the LZW in java. So I did. I benchmarked the difference and the new implementation was way slower when compressing. GWT/java is actually better when uncompressing. I changed the java collections to javascript collections JsMap, and JsList and the difference was greatly reduced but not enough to be able to scrap the js implementation. My guess any remaining gains are hidden in the StringBuilder but I may by wrong. Chrome Firefox IE Js 544/61 626/78 795/171 Java 750/48 1702/48 2401/468 JavaJsCollections 785/38 1398/38 1877/351 The numbers are compressing/uncompressing 1000 iterations with a random string multiplied 10 times I am using a single permutation with collapse-all. Can this be the culprit? Any idea what to change in order to increase the performance in the java code? Here is the code package com.biovista.lib.gwt.client; import com.google.gwt.core.client.JavaScriptObject; public class Util { private static final char DICT_SIZE = 256; public static class JsMapT extends JavaScriptObject { protected JsMap() { } public final native void put(String key, T value) /*-{ this[key] = value; }-*/; public final native boolean containsKey(String key) /*-{ return (key in this); }-*/; public final native T get(String key) /*-{ return this[key]; }-*/; public static JsMap createInstance() { return (JsMap) createObject(); } } public static class JsListT extends JavaScriptObject { protected JsList() { } public final native void add(T value) /*-{ this.push(value); }-*/; public final native int size() /*-{ return this.length; }-*/; public final native T get(char index) /*-{ return this[index]; }-*/; public static JsList createInstance() { return (JsList) createArray(); } } public static String compressLZW(String text) { // Build the dictionary. // final MapString, Character map = new HashMapString, Character( // DICT_SIZE); final JsMapCharacter map = JsMap.createInstance(); for (char i = 0; i DICT_SIZE; i++) { map.put( + i, i); } char dict_size = DICT_SIZE; String w = ; final StringBuilder result = new StringBuilder(); for (char c : text.toCharArray()) { final String wc = w + c; if (map.containsKey(wc)) w = wc; else { result.append(map.get(w)); // Add wc to the dictionary. map.put(wc, dict_size++); w = + c; } } // Output the code for w. if (!w.equals()) result.append(map.get(w)); return result.toString(); } /** uncompress a string. */ public static String uncompressLZW(String compressed_text) { // Build the dictionary. // final ListString rmap = new ArrayListString(DICT_SIZE); final JsListString rmap = JsList.createInstance(); for (char i = 0; i DICT_SIZE; i++) { rmap.add( + i); } final char[] compressed = compressed_text.toCharArray(); String w = + compressed[0]; final StringBuilder result = new StringBuilder(w); for (int i = 1; i compressed.length; i++) { final char k = compressed[i]; final String entry = k rmap.size() ? rmap.get(k) : w + w.charAt(0); result.append(entry); // Add w+entry[0] to the dictionary. rmap.add(w + entry.charAt(0)); w = entry; } return result.toString(); } // LZW-compress a string public static native String lzwCompress(String s) /*-{ var dict = {}; var data = (s + ).split(); var out = []; var currChar; var phrase = data[0]; var code = 256; for (var i = 1; i data.length; i++) { currChar = data[i]; if (dict[phrase + currChar] != null) { phrase += currChar; } else { out.push(phrase.length 1 ? dict[phrase] : phrase
Re: GWT vs js performance: Collections and Strings
Hi Eric, I haven't use the JsArray because the compression algorithm requires map access and not list access. Vassilis On Wed, May 6, 2015 at 12:35 PM, Eric Ponthiaux ponthiau...@sfeir.com wrote: Have you done any testing with JsArray or JsArrayOf ? Le mardi 5 mai 2015 14:34:46 UTC+2, Vassilis Virvilis a écrit : Hi, At some point in time I needed to handle lzw compressing/uncompressing in the client so I found https://gist.github.com/revolunet/843889 Later on I rewrite the LZW in java. So I did. I benchmarked the difference and the new implementation was way slower when compressing. GWT/java is actually better when uncompressing. I changed the java collections to javascript collections JsMap, and JsList and the difference was greatly reduced but not enough to be able to scrap the js implementation. My guess any remaining gains are hidden in the StringBuilder but I may by wrong. Chrome Firefox IE Js 544/61 626/78 795/171 Java 750/48 1702/48 2401/468 JavaJsCollections 785/38 1398/38 1877/351 The numbers are compressing/uncompressing 1000 iterations with a random string multiplied 10 times I am using a single permutation with collapse-all. Can this be the culprit? Any idea what to change in order to increase the performance in the java code? Here is the code package com.biovista.lib.gwt.client; import com.google.gwt.core.client.JavaScriptObject; public class Util { private static final char DICT_SIZE = 256; public static class JsMapT extends JavaScriptObject { protected JsMap() { } public final native void put(String key, T value) /*-{ this[key] = value; }-*/; public final native boolean containsKey(String key) /*-{ return (key in this); }-*/; public final native T get(String key) /*-{ return this[key]; }-*/; public static JsMap createInstance() { return (JsMap) createObject(); } } public static class JsListT extends JavaScriptObject { protected JsList() { } public final native void add(T value) /*-{ this.push(value); }-*/; public final native int size() /*-{ return this.length; }-*/; public final native T get(char index) /*-{ return this[index]; }-*/; public static JsList createInstance() { return (JsList) createArray(); } } public static String compressLZW(String text) { // Build the dictionary. // final MapString, Character map = new HashMapString, Character( // DICT_SIZE); final JsMapCharacter map = JsMap.createInstance(); for (char i = 0; i DICT_SIZE; i++) { map.put( + i, i); } char dict_size = DICT_SIZE; String w = ; final StringBuilder result = new StringBuilder(); for (char c : text.toCharArray()) { final String wc = w + c; if (map.containsKey(wc)) w = wc; else { result.append(map.get(w)); // Add wc to the dictionary. map.put(wc, dict_size++); w = + c; } } // Output the code for w. if (!w.equals()) result.append(map.get(w)); return result.toString(); } /** uncompress a string. */ public static String uncompressLZW(String compressed_text) { // Build the dictionary. // final ListString rmap = new ArrayListString(DICT_SIZE); final JsListString rmap = JsList.createInstance(); for (char i = 0; i DICT_SIZE; i++) { rmap.add( + i); } final char[] compressed = compressed_text.toCharArray(); String w = + compressed[0]; final StringBuilder result = new StringBuilder(w); for (int i = 1; i compressed.length; i++) { final char k = compressed[i]; final String entry = k rmap.size() ? rmap.get(k) : w + w.charAt(0); result.append(entry); // Add w+entry[0] to the dictionary. rmap.add(w + entry.charAt(0)); w = entry; } return result.toString(); } // LZW-compress a string public static native String lzwCompress(String s) /*-{ var dict = {}; var data = (s + ).split(); var out = []; var currChar; var phrase = data[0]; var code = 256; for (var i = 1; i data.length; i++) { currChar = data[i]; if (dict[phrase + currChar] != null) { phrase += currChar;
Re: GWT vs js performance: Collections and Strings
Anyway I profiled a bit. Here is the results compress total time: 721 compress self: 203 ? What is it doing? The main loop probably containsKey 180 (Map operation with jonL suggestion) put 164 (Map) append self 91 / total 119 (StringBuilder) toString() 16 (StringBuilder) valueOf 16 (convert dict_size++ to something in order to put it in the map) The difference with the js version is around 200-250 msec. I can't imagine where the next low hanging fruit would be. JonL after implementing __correctly__ your suggestion I was able to trim 40-45 msec from the profile run (SDM). Unfortunately I cannot see that improvement in the fully compiled version. Vassilis On Wed, May 6, 2015 at 4:12 PM, Vassilis Virvilis vasv...@gmail.com wrote: Hi Eric, I haven't use the JsArray because the compression algorithm requires map access and not list access. Vassilis On Wed, May 6, 2015 at 12:35 PM, Eric Ponthiaux ponthiau...@sfeir.com wrote: Have you done any testing with JsArray or JsArrayOf ? Le mardi 5 mai 2015 14:34:46 UTC+2, Vassilis Virvilis a écrit : Hi, At some point in time I needed to handle lzw compressing/uncompressing in the client so I found https://gist.github.com/revolunet/843889 Later on I rewrite the LZW in java. So I did. I benchmarked the difference and the new implementation was way slower when compressing. GWT/java is actually better when uncompressing. I changed the java collections to javascript collections JsMap, and JsList and the difference was greatly reduced but not enough to be able to scrap the js implementation. My guess any remaining gains are hidden in the StringBuilder but I may by wrong. Chrome Firefox IE Js 544/61 626/78 795/171 Java 750/48 1702/48 2401/468 JavaJsCollections 785/38 1398/38 1877/351 The numbers are compressing/uncompressing 1000 iterations with a random string multiplied 10 times I am using a single permutation with collapse-all. Can this be the culprit? Any idea what to change in order to increase the performance in the java code? Here is the code package com.biovista.lib.gwt.client; import com.google.gwt.core.client.JavaScriptObject; public class Util { private static final char DICT_SIZE = 256; public static class JsMapT extends JavaScriptObject { protected JsMap() { } public final native void put(String key, T value) /*-{ this[key] = value; }-*/; public final native boolean containsKey(String key) /*-{ return (key in this); }-*/; public final native T get(String key) /*-{ return this[key]; }-*/; public static JsMap createInstance() { return (JsMap) createObject(); } } public static class JsListT extends JavaScriptObject { protected JsList() { } public final native void add(T value) /*-{ this.push(value); }-*/; public final native int size() /*-{ return this.length; }-*/; public final native T get(char index) /*-{ return this[index]; }-*/; public static JsList createInstance() { return (JsList) createArray(); } } public static String compressLZW(String text) { // Build the dictionary. // final MapString, Character map = new HashMapString, Character( // DICT_SIZE); final JsMapCharacter map = JsMap.createInstance(); for (char i = 0; i DICT_SIZE; i++) { map.put( + i, i); } char dict_size = DICT_SIZE; String w = ; final StringBuilder result = new StringBuilder(); for (char c : text.toCharArray()) { final String wc = w + c; if (map.containsKey(wc)) w = wc; else { result.append(map.get(w)); // Add wc to the dictionary. map.put(wc, dict_size++); w = + c; } } // Output the code for w. if (!w.equals()) result.append(map.get(w)); return result.toString(); } /** uncompress a string. */ public static String uncompressLZW(String compressed_text) { // Build the dictionary. // final ListString rmap = new ArrayListString(DICT_SIZE); final JsListString rmap = JsList.createInstance(); for (char i = 0; i DICT_SIZE; i++) { rmap.add( + i); } final char[] compressed = compressed_text.toCharArray(); String w = + compressed[0]; final StringBuilder result = new StringBuilder(w); for (int i = 1; i compressed.length;
Re: GWT vs js performance: Collections and Strings
Why would that be weird for there to be a difference? The more loops you have, the more computation time. Your java version is doing 256 additional iterations. On Wed, May 6, 2015 at 11:34 AM, Vassilis Virvilis vasv...@gmail.com wrote: Personal preference I guess... It looks more correct to me to have the initialization phase clearly separated from the main loop. Do you think that something like that can create that difference? I have been surprised in the past trying to understand where the computer spends the time but that would be really - really weird, Vassilis On Wed, May 6, 2015 at 6:30 PM, JonL j...@percsolutions.com wrote: Hmm.. in the Javascript version of the compress, you don't have a loop to initialize the dict like you do the map. It appears you are updating the dict during the same loop. While in the Java version, you have two loops. Why the slight difference in logic? On Wednesday, May 6, 2015 at 7:35:14 AM UTC-7, Vassilis Virvilis wrote: Anyway I profiled a bit. Here is the results compress total time: 721 compress self: 203 ? What is it doing? The main loop probably containsKey 180 (Map operation with jonL suggestion) put 164 (Map) append self 91 / total 119 (StringBuilder) toString() 16 (StringBuilder) valueOf 16 (convert dict_size++ to something in order to put it in the map) The difference with the js version is around 200-250 msec. I can't imagine where the next low hanging fruit would be. JonL after implementing __correctly__ your suggestion I was able to trim 40-45 msec from the profile run (SDM). Unfortunately I cannot see that improvement in the fully compiled version. Vassilis On Wed, May 6, 2015 at 4:12 PM, Vassilis Virvilis vas...@gmail.com wrote: Hi Eric, I haven't use the JsArray because the compression algorithm requires map access and not list access. Vassilis On Wed, May 6, 2015 at 12:35 PM, Eric Ponthiaux ponth...@sfeir.com wrote: Have you done any testing with JsArray or JsArrayOf ? Le mardi 5 mai 2015 14:34:46 UTC+2, Vassilis Virvilis a écrit : Hi, At some point in time I needed to handle lzw compressing/uncompressing in the client so I found https://gist.github.com/revolunet/843889 Later on I rewrite the LZW in java. So I did. I benchmarked the difference and the new implementation was way slower when compressing. GWT/java is actually better when uncompressing. I changed the java collections to javascript collections JsMap, and JsList and the difference was greatly reduced but not enough to be able to scrap the js implementation. My guess any remaining gains are hidden in the StringBuilder but I may by wrong. Chrome Firefox IE Js 544/61 626/78 795/171 Java 750/48 1702/48 2401/468 JavaJsCollections 785/38 1398/38 1877/351 The numbers are compressing/uncompressing 1000 iterations with a random string multiplied 10 times I am using a single permutation with collapse-all. Can this be the culprit? Any idea what to change in order to increase the performance in the java code? Here is the code package com.biovista.lib.gwt.client; import com.google.gwt.core.client.JavaScriptObject; public class Util { private static final char DICT_SIZE = 256; public static class JsMapT extends JavaScriptObject { protected JsMap() { } public final native void put(String key, T value) /*-{ this[key] = value; }-*/; public final native boolean containsKey(String key) /*-{ return (key in this); }-*/; public final native T get(String key) /*-{ return this[key]; }-*/; public static JsMap createInstance() { return (JsMap) createObject(); } } public static class JsListT extends JavaScriptObject { protected JsList() { } public final native void add(T value) /*-{ this.push(value); }-*/; public final native int size() /*-{ return this.length; }-*/; public final native T get(char index) /*-{ return this[index]; }-*/; public static JsList createInstance() { return (JsList) createArray(); } } public static String compressLZW(String text) { // Build the dictionary. // final MapString, Character map = new HashMapString, Character( // DICT_SIZE); final JsMapCharacter map = JsMap.createInstance(); for (char i = 0; i DICT_SIZE; i++) { map.put( + i, i); } char dict_size = DICT_SIZE; String w = ; final StringBuilder result = new StringBuilder(); for (char c : text.toCharArray())
Re: GWT vs js performance: Collections and Strings
Oups... You are right. They are not functionally the same... My java code is doing more operations. If the input is 0 bytes it is doing +256 operations if the input is big enough it eventually phases out the difference. It still makes +256 iterations but without the meat of them that is get/push/append So maybe - my trivial data input was not a good example. I will check tomorrow... Vassilis On Wed, May 6, 2015 at 9:43 PM, Jonathon Lamon j...@percsolutions.com wrote: Why would that be weird for there to be a difference? The more loops you have, the more computation time. Your java version is doing 256 additional iterations. On Wed, May 6, 2015 at 11:34 AM, Vassilis Virvilis vasv...@gmail.com wrote: Personal preference I guess... It looks more correct to me to have the initialization phase clearly separated from the main loop. Do you think that something like that can create that difference? I have been surprised in the past trying to understand where the computer spends the time but that would be really - really weird, Vassilis On Wed, May 6, 2015 at 6:30 PM, JonL j...@percsolutions.com wrote: Hmm.. in the Javascript version of the compress, you don't have a loop to initialize the dict like you do the map. It appears you are updating the dict during the same loop. While in the Java version, you have two loops. Why the slight difference in logic? On Wednesday, May 6, 2015 at 7:35:14 AM UTC-7, Vassilis Virvilis wrote: Anyway I profiled a bit. Here is the results compress total time: 721 compress self: 203 ? What is it doing? The main loop probably containsKey 180 (Map operation with jonL suggestion) put 164 (Map) append self 91 / total 119 (StringBuilder) toString() 16 (StringBuilder) valueOf 16 (convert dict_size++ to something in order to put it in the map) The difference with the js version is around 200-250 msec. I can't imagine where the next low hanging fruit would be. JonL after implementing __correctly__ your suggestion I was able to trim 40-45 msec from the profile run (SDM). Unfortunately I cannot see that improvement in the fully compiled version. Vassilis On Wed, May 6, 2015 at 4:12 PM, Vassilis Virvilis vas...@gmail.com wrote: Hi Eric, I haven't use the JsArray because the compression algorithm requires map access and not list access. Vassilis On Wed, May 6, 2015 at 12:35 PM, Eric Ponthiaux ponth...@sfeir.com wrote: Have you done any testing with JsArray or JsArrayOf ? Le mardi 5 mai 2015 14:34:46 UTC+2, Vassilis Virvilis a écrit : Hi, At some point in time I needed to handle lzw compressing/uncompressing in the client so I found https://gist.github.com/revolunet/843889 Later on I rewrite the LZW in java. So I did. I benchmarked the difference and the new implementation was way slower when compressing. GWT/java is actually better when uncompressing. I changed the java collections to javascript collections JsMap, and JsList and the difference was greatly reduced but not enough to be able to scrap the js implementation. My guess any remaining gains are hidden in the StringBuilder but I may by wrong. Chrome Firefox IE Js 544/61 626/78 795/171 Java 750/48 1702/48 2401/468 JavaJsCollections 785/38 1398/38 1877/351 The numbers are compressing/uncompressing 1000 iterations with a random string multiplied 10 times I am using a single permutation with collapse-all. Can this be the culprit? Any idea what to change in order to increase the performance in the java code? Here is the code package com.biovista.lib.gwt.client; import com.google.gwt.core.client.JavaScriptObject; public class Util { private static final char DICT_SIZE = 256; public static class JsMapT extends JavaScriptObject { protected JsMap() { } public final native void put(String key, T value) /*-{ this[key] = value; }-*/; public final native boolean containsKey(String key) /*-{ return (key in this); }-*/; public final native T get(String key) /*-{ return this[key]; }-*/; public static JsMap createInstance() { return (JsMap) createObject(); } } public static class JsListT extends JavaScriptObject { protected JsList() { } public final native void add(T value) /*-{ this.push(value); }-*/; public final native int size() /*-{ return this.length; }-*/; public final native T get(char index) /*-{ return this[index]; }-*/; public static JsList createInstance() { return (JsList) createArray(); } }
Re: GWT vs js performance: Collections and Strings
Personal preference I guess... It looks more correct to me to have the initialization phase clearly separated from the main loop. Do you think that something like that can create that difference? I have been surprised in the past trying to understand where the computer spends the time but that would be really - really weird, Vassilis On Wed, May 6, 2015 at 6:30 PM, JonL j...@percsolutions.com wrote: Hmm.. in the Javascript version of the compress, you don't have a loop to initialize the dict like you do the map. It appears you are updating the dict during the same loop. While in the Java version, you have two loops. Why the slight difference in logic? On Wednesday, May 6, 2015 at 7:35:14 AM UTC-7, Vassilis Virvilis wrote: Anyway I profiled a bit. Here is the results compress total time: 721 compress self: 203 ? What is it doing? The main loop probably containsKey 180 (Map operation with jonL suggestion) put 164 (Map) append self 91 / total 119 (StringBuilder) toString() 16 (StringBuilder) valueOf 16 (convert dict_size++ to something in order to put it in the map) The difference with the js version is around 200-250 msec. I can't imagine where the next low hanging fruit would be. JonL after implementing __correctly__ your suggestion I was able to trim 40-45 msec from the profile run (SDM). Unfortunately I cannot see that improvement in the fully compiled version. Vassilis On Wed, May 6, 2015 at 4:12 PM, Vassilis Virvilis vas...@gmail.com wrote: Hi Eric, I haven't use the JsArray because the compression algorithm requires map access and not list access. Vassilis On Wed, May 6, 2015 at 12:35 PM, Eric Ponthiaux ponth...@sfeir.com wrote: Have you done any testing with JsArray or JsArrayOf ? Le mardi 5 mai 2015 14:34:46 UTC+2, Vassilis Virvilis a écrit : Hi, At some point in time I needed to handle lzw compressing/uncompressing in the client so I found https://gist.github.com/revolunet/843889 Later on I rewrite the LZW in java. So I did. I benchmarked the difference and the new implementation was way slower when compressing. GWT/java is actually better when uncompressing. I changed the java collections to javascript collections JsMap, and JsList and the difference was greatly reduced but not enough to be able to scrap the js implementation. My guess any remaining gains are hidden in the StringBuilder but I may by wrong. Chrome Firefox IE Js 544/61 626/78 795/171 Java 750/48 1702/48 2401/468 JavaJsCollections 785/38 1398/38 1877/351 The numbers are compressing/uncompressing 1000 iterations with a random string multiplied 10 times I am using a single permutation with collapse-all. Can this be the culprit? Any idea what to change in order to increase the performance in the java code? Here is the code package com.biovista.lib.gwt.client; import com.google.gwt.core.client.JavaScriptObject; public class Util { private static final char DICT_SIZE = 256; public static class JsMapT extends JavaScriptObject { protected JsMap() { } public final native void put(String key, T value) /*-{ this[key] = value; }-*/; public final native boolean containsKey(String key) /*-{ return (key in this); }-*/; public final native T get(String key) /*-{ return this[key]; }-*/; public static JsMap createInstance() { return (JsMap) createObject(); } } public static class JsListT extends JavaScriptObject { protected JsList() { } public final native void add(T value) /*-{ this.push(value); }-*/; public final native int size() /*-{ return this.length; }-*/; public final native T get(char index) /*-{ return this[index]; }-*/; public static JsList createInstance() { return (JsList) createArray(); } } public static String compressLZW(String text) { // Build the dictionary. // final MapString, Character map = new HashMapString, Character( // DICT_SIZE); final JsMapCharacter map = JsMap.createInstance(); for (char i = 0; i DICT_SIZE; i++) { map.put( + i, i); } char dict_size = DICT_SIZE; String w = ; final StringBuilder result = new StringBuilder(); for (char c : text.toCharArray()) { final String wc = w + c; if (map.containsKey(wc)) w = wc; else { result.append(map.get(w)); // Add wc to the dictionary. map.put(wc,
Re: GWT vs js performance: Collections and Strings
Hmm.. in the Javascript version of the compress, you don't have a loop to initialize the dict like you do the map. It appears you are updating the dict during the same loop. While in the Java version, you have two loops. Why the slight difference in logic? On Wednesday, May 6, 2015 at 7:35:14 AM UTC-7, Vassilis Virvilis wrote: Anyway I profiled a bit. Here is the results compress total time: 721 compress self: 203 ? What is it doing? The main loop probably containsKey 180 (Map operation with jonL suggestion) put 164 (Map) append self 91 / total 119 (StringBuilder) toString() 16 (StringBuilder) valueOf 16 (convert dict_size++ to something in order to put it in the map) The difference with the js version is around 200-250 msec. I can't imagine where the next low hanging fruit would be. JonL after implementing __correctly__ your suggestion I was able to trim 40-45 msec from the profile run (SDM). Unfortunately I cannot see that improvement in the fully compiled version. Vassilis On Wed, May 6, 2015 at 4:12 PM, Vassilis Virvilis vas...@gmail.com javascript: wrote: Hi Eric, I haven't use the JsArray because the compression algorithm requires map access and not list access. Vassilis On Wed, May 6, 2015 at 12:35 PM, Eric Ponthiaux ponth...@sfeir.com javascript: wrote: Have you done any testing with JsArray or JsArrayOf ? Le mardi 5 mai 2015 14:34:46 UTC+2, Vassilis Virvilis a écrit : Hi, At some point in time I needed to handle lzw compressing/uncompressing in the client so I found https://gist.github.com/revolunet/843889 Later on I rewrite the LZW in java. So I did. I benchmarked the difference and the new implementation was way slower when compressing. GWT/java is actually better when uncompressing. I changed the java collections to javascript collections JsMap, and JsList and the difference was greatly reduced but not enough to be able to scrap the js implementation. My guess any remaining gains are hidden in the StringBuilder but I may by wrong. Chrome Firefox IE Js 544/61 626/78 795/171 Java 750/48 1702/48 2401/468 JavaJsCollections 785/38 1398/38 1877/351 The numbers are compressing/uncompressing 1000 iterations with a random string multiplied 10 times I am using a single permutation with collapse-all. Can this be the culprit? Any idea what to change in order to increase the performance in the java code? Here is the code package com.biovista.lib.gwt.client; import com.google.gwt.core.client.JavaScriptObject; public class Util { private static final char DICT_SIZE = 256; public static class JsMapT extends JavaScriptObject { protected JsMap() { } public final native void put(String key, T value) /*-{ this[key] = value; }-*/; public final native boolean containsKey(String key) /*-{ return (key in this); }-*/; public final native T get(String key) /*-{ return this[key]; }-*/; public static JsMap createInstance() { return (JsMap) createObject(); } } public static class JsListT extends JavaScriptObject { protected JsList() { } public final native void add(T value) /*-{ this.push(value); }-*/; public final native int size() /*-{ return this.length; }-*/; public final native T get(char index) /*-{ return this[index]; }-*/; public static JsList createInstance() { return (JsList) createArray(); } } public static String compressLZW(String text) { // Build the dictionary. // final MapString, Character map = new HashMapString, Character( // DICT_SIZE); final JsMapCharacter map = JsMap.createInstance(); for (char i = 0; i DICT_SIZE; i++) { map.put( + i, i); } char dict_size = DICT_SIZE; String w = ; final StringBuilder result = new StringBuilder(); for (char c : text.toCharArray()) { final String wc = w + c; if (map.containsKey(wc)) w = wc; else { result.append(map.get(w)); // Add wc to the dictionary. map.put(wc, dict_size++); w = + c; } } // Output the code for w. if (!w.equals()) result.append(map.get(w)); return result.toString(); } /** uncompress a string. */ public static String uncompressLZW(String
GWT vs js performance: Collections and Strings
Hi, At some point in time I needed to handle lzw compressing/uncompressing in the client so I found https://gist.github.com/revolunet/843889 Later on I rewrite the LZW in java. So I did. I benchmarked the difference and the new implementation was way slower when compressing. GWT/java is actually better when uncompressing. I changed the java collections to javascript collections JsMap, and JsList and the difference was greatly reduced but not enough to be able to scrap the js implementation. My guess any remaining gains are hidden in the StringBuilder but I may by wrong. Chrome Firefox IE Js 544/61 626/78 795/171 Java 750/48 1702/48 2401/468 JavaJsCollections 785/38 1398/38 1877/351 The numbers are compressing/uncompressing 1000 iterations with a random string multiplied 10 times I am using a single permutation with collapse-all. Can this be the culprit? Any idea what to change in order to increase the performance in the java code? Here is the code package com.biovista.lib.gwt.client; import com.google.gwt.core.client.JavaScriptObject; public class Util { private static final char DICT_SIZE = 256; public static class JsMapT extends JavaScriptObject { protected JsMap() { } public final native void put(String key, T value) /*-{ this[key] = value; }-*/; public final native boolean containsKey(String key) /*-{ return (key in this); }-*/; public final native T get(String key) /*-{ return this[key]; }-*/; public static JsMap createInstance() { return (JsMap) createObject(); } } public static class JsListT extends JavaScriptObject { protected JsList() { } public final native void add(T value) /*-{ this.push(value); }-*/; public final native int size() /*-{ return this.length; }-*/; public final native T get(char index) /*-{ return this[index]; }-*/; public static JsList createInstance() { return (JsList) createArray(); } } public static String compressLZW(String text) { // Build the dictionary. // final MapString, Character map = new HashMapString, Character( // DICT_SIZE); final JsMapCharacter map = JsMap.createInstance(); for (char i = 0; i DICT_SIZE; i++) { map.put( + i, i); } char dict_size = DICT_SIZE; String w = ; final StringBuilder result = new StringBuilder(); for (char c : text.toCharArray()) { final String wc = w + c; if (map.containsKey(wc)) w = wc; else { result.append(map.get(w)); // Add wc to the dictionary. map.put(wc, dict_size++); w = + c; } } // Output the code for w. if (!w.equals()) result.append(map.get(w)); return result.toString(); } /** uncompress a string. */ public static String uncompressLZW(String compressed_text) { // Build the dictionary. // final ListString rmap = new ArrayListString(DICT_SIZE); final JsListString rmap = JsList.createInstance(); for (char i = 0; i DICT_SIZE; i++) { rmap.add( + i); } final char[] compressed = compressed_text.toCharArray(); String w = + compressed[0]; final StringBuilder result = new StringBuilder(w); for (int i = 1; i compressed.length; i++) { final char k = compressed[i]; final String entry = k rmap.size() ? rmap.get(k) : w + w.charAt(0); result.append(entry); // Add w+entry[0] to the dictionary. rmap.add(w + entry.charAt(0)); w = entry; } return result.toString(); } // LZW-compress a string public static native String lzwCompress(String s) /*-{ var dict = {}; var data = (s + ).split(); var out = []; var currChar; var phrase = data[0]; var code = 256; for (var i = 1; i data.length; i++) { currChar = data[i]; if (dict[phrase + currChar] != null) { phrase += currChar; } else { out.push(phrase.length 1 ? dict[phrase] : phrase .charCodeAt(0)); dict[phrase + currChar] = code; code++; phrase = currChar; } } out.push(phrase.length 1 ? dict[phrase] : phrase.charCodeAt(0)); for (var i = 0; i out.length; i++) { out[i] = String.fromCharCode(out[i]); }
Re: GWT vs js performance: Collections and Strings
Hi, I am using final out of habit mostly (coming from c++) although I could cite some arguments in favor of using it anywhere possible. I tried the optimization you suggested and it didn't make a difference. Good catch though... Vassilis On Tue, May 5, 2015 at 4:50 PM, JonL j...@percsolutions.com wrote: Why all the final variables in the Java version? You aren't passing the variables to anonymous inner classes or anything, so there should be no need to mark anything final. I'm not 100% sure what effect that will have on the output from the GWT compiler though as far as speed. As far as I can tell, the biggest difference is in the way you are checking if a value is already in your map. In java code you are calling : if (map.containsKey(wc)) w = wc; map.containsKey converts to: return (key in this) In javascript you are calling: if (dict[phrase + currChar] != null) { phrase += currChar; According to the below speed test, key in this is the slowest of the options for comparing if an object contains a key and would almost double the runtime. https://jsperf.com/checking-if-a-key-exists-in-a-javascript-array On Tuesday, May 5, 2015 at 5:34:46 AM UTC-7, Vassilis Virvilis wrote: Hi, At some point in time I needed to handle lzw compressing/uncompressing in the client so I found https://gist.github.com/revolunet/843889 Later on I rewrite the LZW in java. So I did. I benchmarked the difference and the new implementation was way slower when compressing. GWT/java is actually better when uncompressing. I changed the java collections to javascript collections JsMap, and JsList and the difference was greatly reduced but not enough to be able to scrap the js implementation. My guess any remaining gains are hidden in the StringBuilder but I may by wrong. Chrome Firefox IE Js 544/61 626/78 795/171 Java 750/48 1702/48 2401/468 JavaJsCollections 785/38 1398/38 1877/351 The numbers are compressing/uncompressing 1000 iterations with a random string multiplied 10 times I am using a single permutation with collapse-all. Can this be the culprit? Any idea what to change in order to increase the performance in the java code? Here is the code package com.biovista.lib.gwt.client; import com.google.gwt.core.client.JavaScriptObject; public class Util { private static final char DICT_SIZE = 256; public static class JsMapT extends JavaScriptObject { protected JsMap() { } public final native void put(String key, T value) /*-{ this[key] = value; }-*/; public final native boolean containsKey(String key) /*-{ return (key in this); }-*/; public final native T get(String key) /*-{ return this[key]; }-*/; public static JsMap createInstance() { return (JsMap) createObject(); } } public static class JsListT extends JavaScriptObject { protected JsList() { } public final native void add(T value) /*-{ this.push(value); }-*/; public final native int size() /*-{ return this.length; }-*/; public final native T get(char index) /*-{ return this[index]; }-*/; public static JsList createInstance() { return (JsList) createArray(); } } public static String compressLZW(String text) { // Build the dictionary. // final MapString, Character map = new HashMapString, Character( // DICT_SIZE); final JsMapCharacter map = JsMap.createInstance(); for (char i = 0; i DICT_SIZE; i++) { map.put( + i, i); } char dict_size = DICT_SIZE; String w = ; final StringBuilder result = new StringBuilder(); for (char c : text.toCharArray()) { final String wc = w + c; if (map.containsKey(wc)) w = wc; else { result.append(map.get(w)); // Add wc to the dictionary. map.put(wc, dict_size++); w = + c; } } // Output the code for w. if (!w.equals()) result.append(map.get(w)); return result.toString(); } /** uncompress a string. */ public static String uncompressLZW(String compressed_text) { // Build the dictionary. // final ListString rmap = new ArrayListString(DICT_SIZE); final JsListString rmap = JsList.createInstance(); for (char i = 0; i DICT_SIZE; i++) { rmap.add( + i); } final
Re: GWT vs js performance: Collections and Strings
Why all the final variables in the Java version? You aren't passing the variables to anonymous inner classes or anything, so there should be no need to mark anything final. I'm not 100% sure what effect that will have on the output from the GWT compiler though as far as speed. As far as I can tell, the biggest difference is in the way you are checking if a value is already in your map. In java code you are calling : if (map.containsKey(wc)) w = wc; map.containsKey converts to: return (key in this) In javascript you are calling: if (dict[phrase + currChar] != null) { phrase += currChar; According to the below speed test, key in this is the slowest of the options for comparing if an object contains a key and would almost double the runtime. https://jsperf.com/checking-if-a-key-exists-in-a-javascript-array On Tuesday, May 5, 2015 at 5:34:46 AM UTC-7, Vassilis Virvilis wrote: Hi, At some point in time I needed to handle lzw compressing/uncompressing in the client so I found https://gist.github.com/revolunet/843889 Later on I rewrite the LZW in java. So I did. I benchmarked the difference and the new implementation was way slower when compressing. GWT/java is actually better when uncompressing. I changed the java collections to javascript collections JsMap, and JsList and the difference was greatly reduced but not enough to be able to scrap the js implementation. My guess any remaining gains are hidden in the StringBuilder but I may by wrong. Chrome Firefox IE Js 544/61 626/78 795/171 Java 750/48 1702/48 2401/468 JavaJsCollections 785/38 1398/38 1877/351 The numbers are compressing/uncompressing 1000 iterations with a random string multiplied 10 times I am using a single permutation with collapse-all. Can this be the culprit? Any idea what to change in order to increase the performance in the java code? Here is the code package com.biovista.lib.gwt.client; import com.google.gwt.core.client.JavaScriptObject; public class Util { private static final char DICT_SIZE = 256; public static class JsMapT extends JavaScriptObject { protected JsMap() { } public final native void put(String key, T value) /*-{ this[key] = value; }-*/; public final native boolean containsKey(String key) /*-{ return (key in this); }-*/; public final native T get(String key) /*-{ return this[key]; }-*/; public static JsMap createInstance() { return (JsMap) createObject(); } } public static class JsListT extends JavaScriptObject { protected JsList() { } public final native void add(T value) /*-{ this.push(value); }-*/; public final native int size() /*-{ return this.length; }-*/; public final native T get(char index) /*-{ return this[index]; }-*/; public static JsList createInstance() { return (JsList) createArray(); } } public static String compressLZW(String text) { // Build the dictionary. // final MapString, Character map = new HashMapString, Character( // DICT_SIZE); final JsMapCharacter map = JsMap.createInstance(); for (char i = 0; i DICT_SIZE; i++) { map.put( + i, i); } char dict_size = DICT_SIZE; String w = ; final StringBuilder result = new StringBuilder(); for (char c : text.toCharArray()) { final String wc = w + c; if (map.containsKey(wc)) w = wc; else { result.append(map.get(w)); // Add wc to the dictionary. map.put(wc, dict_size++); w = + c; } } // Output the code for w. if (!w.equals()) result.append(map.get(w)); return result.toString(); } /** uncompress a string. */ public static String uncompressLZW(String compressed_text) { // Build the dictionary. // final ListString rmap = new ArrayListString(DICT_SIZE); final JsListString rmap = JsList.createInstance(); for (char i = 0; i DICT_SIZE; i++) { rmap.add( + i); } final char[] compressed = compressed_text.toCharArray(); String w = + compressed[0]; final StringBuilder result = new StringBuilder(w); for (int i = 1; i compressed.length; i++) { final char k =
Re: GWT vs js performance: Collections and Strings
GWT already optimizes a HashMapString, ... similar to what you have implemented. You can see this in [1] and the specialized methods if the key type is String.class. Also ArrayList is backed by a native JS array. Of course GWT carries some overhead because it emulates the full Java API but because it's already quite optimized you don't see a huge improvement when switching from Java to JavaJsCollection. The largest improvement is on IE but IMHO thats not a surprise. StringBuilder in GWT is just appending strings and does not use any buffer array like in real Java. It is basically s += toAppend which is pretty fast in browsers. The biggest difference I see is that the Java / JavaJsCollection version use String.toCharArray() which actually creates a new array, walks the string and fills the array. It is probably faster to do for (int i = 0; i string.length(); i++) { char c = string.charAt(i); } because Java's String.charAt(i) is directly mapped to JavaScript's String.charCodeAt(i) (see [2]) and you avoid the char array creation. [1] https://gwt.googlesource.com/gwt/+/master/user/super/com/google/gwt/emul/java/util/AbstractHashMap.java [2] https://gwt.googlesource.com/gwt/+/master/user/super/com/google/gwt/emul/java/lang/String.java#609 -- You received this message because you are subscribed to the Google Groups Google Web Toolkit group. To unsubscribe from this group and stop receiving emails from it, send an email to google-web-toolkit+unsubscr...@googlegroups.com. To post to this group, send email to google-web-toolkit@googlegroups.com. Visit this group at http://groups.google.com/group/google-web-toolkit. For more options, visit https://groups.google.com/d/optout.
Re: GWT vs js performance: Collections and Strings
Jens, thanks do the suggestion, I tried it with minimal difference. Tomorrow I will try to profile the compression part. Vassilis On Tue, May 5, 2015 at 5:37 PM, Jens jens.nehlme...@gmail.com wrote: GWT already optimizes a HashMapString, ... similar to what you have implemented. You can see this in [1] and the specialized methods if the key type is String.class. Also ArrayList is backed by a native JS array. Of course GWT carries some overhead because it emulates the full Java API but because it's already quite optimized you don't see a huge improvement when switching from Java to JavaJsCollection. The largest improvement is on IE but IMHO thats not a surprise. StringBuilder in GWT is just appending strings and does not use any buffer array like in real Java. It is basically s += toAppend which is pretty fast in browsers. The biggest difference I see is that the Java / JavaJsCollection version use String.toCharArray() which actually creates a new array, walks the string and fills the array. It is probably faster to do for (int i = 0; i string.length(); i++) { char c = string.charAt(i); } because Java's String.charAt(i) is directly mapped to JavaScript's String.charCodeAt(i) (see [2]) and you avoid the char array creation. [1] https://gwt.googlesource.com/gwt/+/master/user/super/com/google/gwt/emul/java/util/AbstractHashMap.java [2] https://gwt.googlesource.com/gwt/+/master/user/super/com/google/gwt/emul/java/lang/String.java#609 -- You received this message because you are subscribed to the Google Groups Google Web Toolkit group. To unsubscribe from this group and stop receiving emails from it, send an email to google-web-toolkit+unsubscr...@googlegroups.com. To post to this group, send email to google-web-toolkit@googlegroups.com. Visit this group at http://groups.google.com/group/google-web-toolkit. For more options, visit https://groups.google.com/d/optout. -- Vassilis Virvilis -- You received this message because you are subscribed to the Google Groups Google Web Toolkit group. To unsubscribe from this group and stop receiving emails from it, send an email to google-web-toolkit+unsubscr...@googlegroups.com. To post to this group, send email to google-web-toolkit@googlegroups.com. Visit this group at http://groups.google.com/group/google-web-toolkit. For more options, visit https://groups.google.com/d/optout.