DEV Community

Cover image for Improving performance in Kotlin with string concatenation
Gabriel Menezes da Silva
Gabriel Menezes da Silva

Posted on

Improving performance in Kotlin with string concatenation

Context

I worked in a native android mobile application used by a logistic company. This app is used by operators to scan the labels of packages/containers in order to do the steps necessary in the system to sort them.

There's a function where it gets the label string/bytes, manipulates it and delivers to the back-end the correct string so they can process it.

This function is the heartbeat of the whole application, without it, the logistics will not work, so every improvement in it, it's always welcomed.

In this article, It will be explained which improvements were done and the reasons why they were implemented.

Which improvement was done?

A operation that is done numerous times in this function is the concatenation.

You might be asking, but why improving the concatenation is important? Depending on the concatenation that is being done, you literally can have problems of memory and time to get the result.

Problem

So before the improvement, the concatenation of the strings was being done like described in the code below, using the famous += operator, very commonly used in the daily basis:

 var result = ""
   val iterations = 1000
   for (i in 0 until iterations) {
       result += "Item $i "
  }
Enter fullscreen mode Exit fullscreen mode

Ok, but what's the problem of using it?:

  • String is a immutable object, that is, in every iteration a new instance of String is created, more memory is allocated.

That is, the more you increase the number of iterations, more memory is allocated and more time will be taken to get the result!!

Solution

Use StringBuilder instead of using the operator +=. The reason why will be described below:

  • StringBuilder is a mutable object, that is, no new instance of string is created in every iteration.
  • The same memory allocation is used for all the concatenation process, all the iteration.

The following code shows how this could be implemented:

  val result = buildString {
            for (i in 0 until iterations) {
                append("Item $i ")
            }
        }
Enter fullscreen mode Exit fullscreen mode

buildString uses StringBuilder under the hood. For reference checkout this kotlin doc link.

If you run the following code:

/**
 * You can edit, run, and share this code.
 * play.kotlinlang.org
 */
import kotlin.system.measureTimeMillis
fun main() {
  val iterations = 1000


    val timePlusEqual = measureTimeMillis {
        var result = ""
        for (i in 0 until iterations) {
            result += "Item $i "
        }
    }

    // StringBuilder
    // Kotlin is under the hood using a StringBuilder, 
    val timeBuildString = measureTimeMillis {
        val result = buildString {
            for (i in 0 until iterations) {
                append("Item $i ")
            }
        }
    }

    println("Time with +=: ${timePlusEqual}ms")
    println("Time with buildString: ${timeBuildString}ms")
}
Enter fullscreen mode Exit fullscreen mode

You'll get this BIG difference:

Time with +=: 21ms
Time with buildString: 0ms
Enter fullscreen mode Exit fullscreen mode

In this article I'm just writing a simple example, but imagine this in a big scale, with very big strings, this time difference and memory will increase.

Conclusion

Sometimes we think that to create huge impact in a project, It's necessary to do big things like changing the architecture of the whole app.
That's not true, simple things can bring huge impact and deliver real good value for the clients. It's necessary to have that in our minds, It creates a feeling of comfort.

Top comments (0)