Effective Kotlin Item 58: Consider Arrays with primitives for performance-critical processing
This is a chapter from the book Effective Kotlin. You can find it on LeanPub or Amazon.
We cannot declare primitives in Kotlin, but they are used as an optimization under the hood. This is a significant optimization, as described already in Item 47: Avoid unnecessary object creation. Primitives are:
- Lighter, as every object adds additional weight.
- Faster, as accessing a value through accessors is an additional cost, and creating an object is also a cost.
Therefore, using primitives for a huge amount of data might be a significant optimization. One problem is that typical Kotlin collections like List
or Set
are generic. Primitives cannot be used as generic types, so we end up using wrapped types instead. This is a convenient solution that suits most cases as it is easier to do processing over standard collections. Having said that, in performance-critical parts of our code we should instead consider using arrays with primitives, like IntArray
or LongArray
, as they are lighter in terms of memory and their processing is more efficient.
Kotlin type | Java type |
---|---|
Int | int |
List | List |
Array | Integer[] |
IntArray | int[] |
How much lighter are arrays with primitives? Let’s say that in Kotlin/JVM we need to hold 1,000,000 integers, and we can choose to keep them either in IntArray
or in List<Int>
. If you make some measurements, you will find that on a typical machine IntArray
allocates 4,000,016 bytes, while List<Int>
allocates 20,000,040 bytes, which is 5 times more. If it is possible to optimize for memory use, choose arrays with primitives.
There is also a difference in performance. For the same collection of 1,000,000 numbers, calculating the average of these elements is around 25% faster when we use an array with primitives instead of a list with wrapped integers.
As you can see, primitives and arrays with primitives can be used as an optimization in performance-critical parts of your code. They allocate less memory, and their processing is faster. However, the improvement in most cases is not significant enough to use arrays with primitives by default instead of lists. Lists are more intuitive and we use them much more often, so in most cases, we should prefer them instead. Just keep this optimization in mind in case you need to optimize some performance-critical parts of code.
Summary
In a typical case, List
or Set
should be preferred over arrays. However, if you hold big collections of values that can be represented as primitives, using arrays of primitives might significantly improve your performance and memory use. This is especially important for library creators or developers who write games or do advanced graphic processing.