Java Performance Tips (So Code Camp San Diego 2014)

1,682 views

Published on

Slides for my presentation at SoCal Code Camp, June 29, 2014 (http://www.socalcodecamp.com/socalcodecamp/session.aspx?sid=68942cd0-6714-4753-a218-20d4b48da07d)

Published in: Technology, Education
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,682
On SlideShare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
35
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide
  • tips covered here:
    * most are learned and tested in production
    * some are not (but interesting enough)

    performance goals:
    * finish a task in less time, given same amount of parallelization
    * use less memory

    language war:
    * there are places for that
    * use the right tool for the right job
    * programmers can make things work better

    exhaustive list or really in-depth analysis:
    * there are books for that
    * we only have 1 hour
    * get you interesting in this topic, if you are not already
  • some truth for the saying that the compiler uses StringBuilder behind the scene
  • some truth for the saying that the compiler uses StringBuilder behind the scene
  • * when the concatenation is done inside a loop, things become more complex
    * here’s how the code looks like if you use StringBuilder explicitly
  • * what if you use the + or += operator and hope the compiler optimizes things for you?
  • * turns out, the compiler rewrites the code into this
  • * note these 3 operations within the loop
    * if you think all these object creation and copying slow things down, you’re probably right
  • * using StringBuilder explicitly results in much less copying of data
    * in short, if you’re concatenating strings inside a loop, use StringBuilder explicitly
  • * CharSequence: a less well-known interface
  • * however, the Writer support writing a CharSequence’s content to a file, etc.
    * CharSequenceReader (in Apache Commons IO library) to read from CharSequence
  • * whenever we have a method that returns a String, and we have to convert something into a String return value, ask: do we really have to do the conversion?
    * might be able to modify to method to return another type, like CharSequence
    * might be able to avoid the conversion
  • http://www.ibm.com/developerworks/library/j-codetoheap/
  • * a lot of overhead incolved
  • * no built-in implementation, but 3rd party implementations
  • * unlike Trove, fastutil has sorted maps and asets
    * downside is size (so many classes in the library)
  • * no automatic conversion/cast from int[] into List<Integer>
  • slow approach * create an ArrayList<Integer>
    * copy elements, one at a time, from the int[]
  • * no copying of array elements
  • https://commons.apache.org/proper/commons-collections/apidocs/org/apache/commons/collections4/map/LRUMap.html
  • https://commons.apache.org/proper/commons-collections/apidocs/org/apache/commons/collections4/map/LRUMap.html
  • Zip and GZip use same algorithm
    Deflate
    zlib: open-source implementation
    compression saves more space than ever
    compression ! == slow anymore
    CPU much faster than I/O
    compressed data: less I/O
  • * MappedByteBuffer: get from RandomAccessFile and FileChannel

    http://www.onjava.com/pub/a/onjava/2002/10/02/javanio.html?page=3
  • SIZE = 100000
  • Java Performance Tips (So Code Camp San Diego 2014)

    1. 1. Java Performance Tips Kai Chan SoCal Code Camp, June 2014 http://bit.ly/sdcodecamp2014java
    2. 2. This Talk ● is about… o several Java performance tips I have learned ● is NOT about… o language war o exhaustive list o really in-depth analysis
    3. 3. The Usual Caveats ● performance not your only concern ● opportunity cost ● premature optimization ● test in your environment
    4. 4. String Manipulation
    5. 5. Ways to Concatenate Strings ● operators (+ and +=) ● String’s concat method ● StringBuilder
    6. 6. String s = a + b + c + d same bytecode as: String s = new StringBuilder().append(a).append(b) .append(c).append(d).toString()
    7. 7. String s = s + a + b + c + d String s += a + b + c + d same bytecode as: String s = new StringBuilder().append(s).append(a) .append(b).append(c).append(d).toSt ring()
    8. 8. String s = a.concat(b).concat(c).concat(d) String s = s.concat(a).concat(b).concat(c) .concat(d) ● not translated to use StringBuilder ● only accepts String, can’t call method of null
    9. 9. StringBuilder result = new StringBuilder(); while (stillRunning()) { … result.append(a); … }
    10. 10. String result = “”; while (stillRunning()) { … result += a; … }
    11. 11. String result = “”; while (stillRunning()) { … result = new StringBuilder() .append(s).append(a).toString(); … }
    12. 12. String result = “”; while (stillRunning()) { … result = new StringBuilder() .append(s).append(a).toString(); … } copy characters from String to StringBuilder copy characters from StringBuilder to String create a new object
    13. 13. String Concatenation Example ● 100000 iterations ● a 1 byte String appended per iteration ● 100 KB of data appended // initialize result variable … for (int i = 1; i <= 100000; i++) { // append 1-byte string to result }
    14. 14. + or += operator ● iteration i: o copy (i - 1) bytes from String to StringBuilder o append 1 byte to StringBuilder o copy i bytes from StringBuilder to String ● total: copy 1.4 GB of data
    15. 15. String’s concat method ● iteration i: o copy (i - 1) bytes from the old String, plus 1 byte to append with, to a new String ● total: copy 672 MB of data
    16. 16. StringBuilder ● when needed to expand o create a new buffer at least 2x as large o copy data over ● to grow the buffer from 1 byte to >= 100000 bytes: copy 128 KB of data ● plus, copy 98 KB of data from outside StringBuilder ● total: copy 226 KB of data
    17. 17. CharSequence ● implemented by String, StringBuffer, StringBuilder ● methods o charAt o length o subSequence ● does not define equals and hashCode
    18. 18. CharSequence ● Writer o append(CharSequence) o append(CharSequence, int, int) // seq, start, end ● CharSequenceReader
    19. 19. public String getText() { StringBuilder result = new StringBuilder(); … return result.toString(); } copies all characters in the StringBuilder to a String
    20. 20. public CharSequence getText() { StringBuilder result = new StringBuilder(); … return result; }
    21. 21. Primitive Collections
    22. 22. ● no direct support o cannot have List<int>, Map<int, long> ● indirect support via boxing o “wrapper” classes, e.g. Integer, Long o can have List<Integer>, Map<Integer, Long> ● memory cost Primitives Collection in Java
    23. 23. Object Metadata ● object’s class ● lock/synchronization state ● array size (if the object is an array) ● total: ~8-12 bytes for 32-bit JVM (more for 64-bit JVM)
    24. 24. metadat a element 999element 0 12 bytes 4 bytes 4 bytes 4 bytes … int[] with 1000 Elements element 1 size = 4012 bytes
    25. 25. ArrayList<Integer> w/ 1000 Elements metadat a size 8 bytes 4 bytes 4 or 8 bytes metadata value metadata value metadata value 8 bytes 8 bytes 8 bytes 4 bytes 4 bytes 4 bytes size = 16028 bytes (if OOP size = 32 bits) size = 20032 bytes (if OOP size = 64 bits) metadat a element 999element 0 12 bytes 4 or 8 bytes 4 or 8 bytes 4 or 8 bytes …element 1 elementData
    26. 26. Map: Even More Overhead ● both key and value can be boxed primitives ● some types of map half-full by design ● e.g. HashMap<Integer, Integer>
    27. 27. Primitive Collection Implementations ● Trove o http://trove.starlight-systems.com/ o does NOT implement Java’s Collection interface o iteration by callback object/method
    28. 28. Primitive Collection Implementations ● fastutil o http://fastutil.di.unimi.it/ o type-specific maps, sets, lists o sorted maps and sets o implement Java’s Collection interface o primitive iterators o latest version’s binary JAR file is 17 MB
    29. 29. Convert Primitive Array To List ● you have an int[] ● some method only takes a List (e.g. List<Integer>) ● Arrays.asList(int[]): type mismatch
    30. 30. // someFunc takes a List, read-only // a: int[] list = new ArrayList<Integer>(a.length); for(int i = 0; i < a.length; i++){ list.add(a[i]); } someFunc(list);
    31. 31. // someFunc takes a List, read-only // a: int[] someFunc(Ints.asList(a)); ● Ints.asList: returns a fixed-size list backed by the specified array ● Ints provided by Guava (from Google)
    32. 32. Regular Expression
    33. 33. Regular Expression // input, regex: String input.matches(regex) does the following: Pattern.compile(regex) .matcher(input) .matches()
    34. 34. while (stillRunning()) { … // str and regex: String if (str.matches(regex)) { … } … }
    35. 35. while (stillRunning()) { … // str and regex: String if (Pattern.compile(regex) .matcher(input) .matches()) { … } … }
    36. 36. while (stillRunning()) { … // str and regex: String if (Pattern.compile(regex) .matcher(input) .matches()) { … } … } generate a Pattern object from the RE pattern (expensive)
    37. 37. java.util.regex.Pattern ● feature-rich ● not the fastest
    38. 38. RE Benchmark ● Java Regular expression library benchmarks o http://tusker.org/regex/regex_benchmark.html ● many alternative implementations ● speed and capability vary
    39. 39. BRICS Automaton ● http://www.brics.dk/automaton/ ● much faster than java.util.regex.Pattern ● basic functionality ● adopted by Lucene 4.x for RE query
    40. 40. Caching
    41. 41. Caching: Example Scenario ● calculate file checksums ● calculation is expensive ● lots of files ● repeated calculations ● solution: cache the checksum o key: file path
    42. 42. Possible Solution: HashMap ● implement cache with HashMap<String, byte[]> ● problem: o assume cache will be “small enough”, or o need to remove entries (how?)
    43. 43. Possible Solution: WeakHashMap ● implement cache with WeakHashMap<String, byte[]> ● problem: o keys are weak references o if no strong reference on a key, the entry is eligible for GC
    44. 44. Solution: Libraries ● Apache Commons Collections o LRUMap class o LRU (least recently updated) cache algorithm o fixed max size
    45. 45. Solution: Libraries (cont.) ● Guava o CacheBuilder and Cache classes o accessible by multiple threads o eviction by: max size, access time, write time, weak keys, weak values, soft values o CacheLoader class: creates entry on demand o remove listeners
    46. 46. Data Compression
    47. 47. Lossless Compression Today ● compression saves more space than ever ● store more in faster medium (memory, SSD) ● compression ! == slow anymore ● new algorithms target high throughput o > 300 MB/s compression o > 1000 MB/s decompression
    48. 48. LZ4 ● faster than Deflate with zlib ● decent ratio ● LZ4_HC o slower compression speed o higher compression ratio o decoding side unchanged ● ported to Java o https://github.com/jpountz/lz4-java
    49. 49. Memory-Mapped File
    50. 50. Memory-Mapped File Intro ● MappedByteBuffer ● content: memory-mapped region of a file ● OS handles reading, writing, caching ● can be used as persistent, shared memory
    51. 51. Memory-Mapped File Caveats ● file size limited by address space o 64-bit JVM: not an issue o 32-bit JVM: file size limited to <= 2 GB ● no “close function” o you can’t control when resources are free o not suitable for opening many files at/around the same time
    52. 52. Performance Measurement
    53. 53. VisualVM ● bundled with Java SE ● local or remote (JMX) applications ● monitor o CPU usage o heap and PermGen usage o class and thread counts
    54. 54. VisualVM ● heap dump o instance and size by class o biggest object by retain size ● sampler (fast) ● profiler (slow)
    55. 55. Sampling Example ● run 4 methods o concatByAppendresult.append(x()); o concatByConcatresult = result.concat(x()); o concatByPlusOperatorresult = result + x(); o concatByPlusEqualOperatorresult += x(); ● if same speed, each would get 25% CPU
    56. 56. Thanks for Coming! ● slides available o http://bit.ly/sdcodecamp2014java ● please vote for my conference session o http://bit.ly/tvnews2014 ● questions/feedback o kai@ssc.ucla.edu ● questions?

    ×