- Java 9 performance enhancements
- JShell
- Writing good code in Java 9
- Performance testing with JMH
- Set up of benchmark suite
- Constructing benchmark
- Avoid dead code elimination in tests
- Complex benchmarks
- Compilers - Performance boosters
- Just in time compilation
- Ahead of time compilation
- Segmented code cache
- Summary of Java 9 performance improvement
- Topics
- Java 9 performance improvements
- Java 9 GC improvements
- Jshell - Interactive console in Java 9
- How to write good code in Java 9 - New Java 9 API
- Better Java 9 string performance
- Compact strings
- Stored strings in the Class-Data Sharing (CDS) archives
- Java concurrency - Reactive streams
- Why strings are so important?
- Most objects created by our programs are of string type
- Java already optimize usage of string using string pool
- Special memory region
-
There are shared strings
new String("Cat"); // new object is created - anti-pattern- s1 == s2 (works if the string is in string pool)
-
- Special memory region
- Java 9 and class-data sharing (CDS) archives
- Up to Java 8 string pool was per one per one JVM
- In Java 9 string and char[] objects are shared between JVMs
- It can reduce memory usage substantially
- Compact strings
- Up to Java 8, string was internally represented as char[]
- In Java 9, XX:- CompactStrings compactions can be enabled
- Using that flag, string is represented as byte[] (more effective because of size)
- It improves space efficiency of string class
- Reactive Streams
-
Java 9 adds reactive streams to the standard API
-
Publish-subscribe model
-
Flow
Publisher extends Flow
-
- Topics
- Java 9 change default garbage collection algorithm
- First choice
- Choosing G1 to be first choice
- How G1 is working
- Why it is a best general purpose GC
- Java 9 change default garbage collection algorithm
- G1 Characteristics
- Heap is divided into N equally sized regions
- Max 2048 regions
- Each region from 1 MB to 32 MB
- Eden, survivor, and old generation can occupy every region
- G1 Heap Allocation
- Eden Space - young objects live here
- Survivor space - all other objects live
- Old generation - old objects
- How young GC works in G1
- End of young GC
- Live objects from young generation have been evacuated (copied/moved) to
- Zero or more survivor regions
- Old generation regions
- Ecend and survivor possibly resized
- Live objects from young generation have been evacuated (copied/moved) to
- End of young GC
- G1 Introduces Metaspace
- Classes matadata and statics are stored in the native heap and this space is called Metaspace
- GC cannot use native heap
- By default metadata allocation is only limited by the amount of available native memory
- Upto 3 GB (dangerous) - app may crash
- Parameter
MaxMetaspaceSizeis used to set maximum amount of space- Native space is not exhausted
- Classes matadata and statics are stored in the native heap and this space is called Metaspace
- Garbage collection process
- Object is in Eden (Young generation)
- Object is moved to S0 - first pass if object survived (Young generation)
- Object is moved to S1 - second pass if object survived (Young generation)
- Object is moved to Tenured - third pass if object survived (Old Generation)
- Permanent - Metaspace (JDK 1.8 and later) - separate space (not seen by GC)
- Statics
- Classes
- Topics
- Setup Java 9
- Starting JShell
- REPL (Read Evaluate Print Loop) - What it is?
- Playing with Java code using JShell
- Iteractive shell (without main method)
- Steps:
-
Download JDK 9
-
cd jdk-9/bin -
jshell -
Example:
List<Integer> integers = new LinkedList<>() integers integers.add(1) (tab) temporary variable is created String a = "cat" String b = a integers.stream().filter(v -> v > 1).collect(Collectors.toList())-
We don't have to import anything
CompletableFuture.supplyAsync(() -> "hello").get()
-
-
-
Topics
- How Java 9 favors collections and immutability
- Treating optional as stream of one or zero elements
- Using dropWhile()/takeWhile()
- Parallel Files.lines() that use MappedByteBuffer
-
Java 8 way:
// given Set<String> set = new HashSet<>(); set.add("a"); set.add("b"); set.add("c"); // when Set<String> strings = Collections.unmodifiableSet(set); strings.add("a"); // Throws UnsupportedOperationException -
Java 9 way:
// given Set<String> set = Set.of("a", "b", "c"); //when set.add("a"); // Throws UnsupportedOperationException -
Map the Java 9 way:
// given Map<Integer, String> map = Map.of(k1: 1, v1: "a", k2: 2, v2: "b"); // when map.put(3, "a"); // Throws ...- Similarly
List.of
- Similarly
-
Example:
// given Optional<String> value = Optional.of("a"); // when List<String> collect = value.stream().map(String::toUpperCase).collect(Collectors.toList()); // then assertThat(collect).hasSameElementsAs(List.of("A")); -
takeWhilein Stream API// given Stream<Integer> integerStream = Stream.of(10, 5, 1); // when List<Integer> collect = integerStream.sorted(Comparator.reverseOrder()) .takeWhile(v -> v > 1) // beware of ordering stream!! takeWhile only gives determistic .collect(Collectors.toList()); // then assertThat(collect).hasSameElementsAs(List.of(10, 5));-
takeWhile: as long as the condition is being met it continues but as soon as condition fails, it quits. The elements are processed from lowest index to highest index -
dropWhile: as long as the condition is being met, the element is dropped. The elements are processed from lowest index to highest index// given Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5); // when List<Integer> collect = integerStream .sorted() //.parallel() // don't use this .dropWhile(v -> v < 4) // beware of ordering stream!! .collect(Collectors.toList()); // then assertThat(collect).hasSameElementsAs(List.of(4, 5));
-
-
Parallel Files.lines() that use MappedByteBuffer
- Up to Java 8, lines were read using Spliterator that divide work non-evenly
- Longest task took substantial amount of time, maling all parallel tasks waiting for its finish
- In Java 9, it chunks an input into N MappedByteBuffer of same size making computation faster
- Up to Java 8, lines were read using Spliterator that divide work non-evenly
-
Summary
- Explored Java 9 performance improvements
- Discussed Java 9 GC improvements
- Explained JShell - Interactive REPL in Java 9
- Constructed an efficient code using new Java 9 API
-
For high performance of application
-
Topics
- Setup benchmarks suite
- Constructing benchmarks with warm up period
- Avoid dead code elimination in tests
- Constructing complex benchmarks
-
Topics of this video
- Constructing project with JMH
- Looking at the pom.xml
- Constructing simple test suite
- Starting a performance test
-
Generating project
mvn archetype:generate \ -DinteractiveMode=false \ -DarchetypeGroupId=org.openjdk.jmh \ -DarchetypeArtifactId=jmh-java-benchmark-archetype \ -DgroupId=com.tomekl007 \ -DartifactId=packt_jmh \-
To start benchmark
java -jar target/benchmarks.jar
-