9 tips to Increase your Java performance
Any fool can write code that a computer can understand. Good programmers write code that humans can understand. - Martin Fowler
But the itch to write a high performance code is always there for any developer. Let us see how to make Java code to run even faster.
Note: The JVM optimizes the code efficiently. So you do not need to optimize it for a general use cases. But if you want to drain the maximum performance out of JVM. Here we go.
All the tests are taken in OpenJDK 12.0.1 in a Macbook Pro 2017 laptop.
1. Instantiate in constructor
If your collections are initialized only once, it is better to initialize the values in the collection constructor
itself rather than instantiating the collections and setting the values using addAll
.
// Slower πΆββοΈ
Set<String> set = new HashSet<>();
set.addAll(Arrays.asList("one", "two", "three"));
// Faster π
Set<String> set = new HashSet<>(Arrays.asList("one", "two", "three"));
Let us verify this using JMH benchmarks.
The results unit is
operations/second
(op/s
). More the number higher the performance is.
@State(Scope.Thread)
public static class MyState {
@Setup(Level.Trial)
public void doSetup() {
var arr = new Integer[100000];
for (var i = 0; i < 100000; i++) {
arr[i] = i;
}
list = Arrays.asList(arr);
}
public List list;
}
// Faster π > ~148,344 op/s
@Benchmark
public HashSet usingConstructor() {
var set = new HashSet<>(list);
return set;
}
// Slower πΆββοΈ > ~112,061 op/s
@Benchmark
public HashSet usingAddAll() {
var set = new HashSet<>();
set.addAll(list);
return set;
}
The
construtor
version provides ~36000 op/s more than theaddAll
version.
2. AddAll is faster than Add
Similarly, addAll
provides higher operations per second when compared with add
. So next time when you are adding something to an array make sure that you pile them and add it using addAll
.
// Slower πΆββοΈ ~116116op/s
@Benchmark
public ArrayList<Integer> usingAdd() {
var a = new int[1000];
for (var i = 0; i < 1000; i++) {
a[i] = i;
}
var arr = new ArrayList<Integer>();
for (var i = 0; i < 1000; i++) {
arr.add(a[i]);
}
return arr;
}
// Faster π ~299130 op/s
@Benchmark
public ArrayList<Integer> usingAddAll() {
var a = new Integer[1000];
for (var i = 0; i < 1000; i++) {
a[i] = i;
}
var arr = new ArrayList<Integer>();
arr.addAll(Arrays.asList(a));
return arr;
}
The addAll
is almost twice as fast as the add
version.
3. Use EntrySet
for Map over KeySet
Do you iterate a lot over the map? Then use entrySet
over the keySet
.
// Slower πΆββοΈ ~37000 op/s
@Benchmark
public HashMap<Integer, Integer> keySetIteration(Blackhole blackhole) {
var someMap = new HashMap<Integer, Integer>();
for (var i = 0; i < 1000; i++) {
someMap.put(i, i);
}
var sum = 0;
for(Integer i: someMap.keySet()) {
sum += i;
sum += someMap.get(i);
}
blackhole.consume(sum);
return someMap;
}
// Faster π ~45000 op/s
@Benchmark
public HashMap<Integer, Integer> entrySetIteration(Blackhole blackhole) {
var someMap = new HashMap<Integer, Integer>();
for (var i = 0; i < 1000; i++) {
someMap.put(i, i);
}
var sum = 0;
for(Map.Entry<Integer, Integer> e: someMap.entrySet()) {
sum += e.getKey();
sum += e.getValue();
}
blackhole.consume(sum);
return someMap;
}
The entrySet
can run 9000
operations more than its keySet
variant in a second.
4. Use SingletonList
instead of an array
with single element.
// Faster π
var list = Collections.singletonList("S");
// Slower πΆββοΈ
var list = new ArrayList(Arrays.asList("S"));
5. Use EnumSet
instead of HashSet
. EnumSet
is much faster.
// Faster π
public enum Color {
RED, YELLOW, GREEN
}
var colors = EnumSet.allOf(Color.class);
// Slower πΆββοΈ
var colors = new HashSet<>(Arrays.asList(Color.values()));
More about EnumSet here.
6. Do not initialize objects at will. Try to reuse at the maximum.
// Faster π
var i = 0 ;
i += addSomeNumber();
i -= minusSomeNumber();
return i;
// Slower πΆββοΈ
var i = 0 ;
var j = addSomeNumber();
var k = minusSomeNumber();
var l = i + j - k;
return l;
7. Use String.isEmpty()
method to check whether the String
is empty.
String is a byte[]
and isEmpty
just checks the length of an Array
. So it is much faster.
public boolean isEmpty() {
return value.length == 0;
}
8. If you are using String with a single character replace them with a Character
// Faster π
var r = 'R' ;
var g = 'G' ;
var b = 'B' ;
// Slower πΆββοΈ
var r = "R" ;
var g = "G" ;
var b = "B" ;
9. Use StringBuilder wherever you can.
// Faster π
StringBuilder str = new StringBuilder();
str.append("A");
str.append("B");
str.append("C");
str.append("D");
str.append("E");
....
// Slower πΆββοΈ
var str = "";
str += "A";
str += "B";
str += "C";
str += "D";
str += "E";
....
But when you have to do a single concatenation. instead of using a StringBuilder it is faster to use
+
.