Introduction: Why Profiling Kotlin Code is Important for Beginners
\nModern Kotlin applications run fast, but without performance monitoring, even a small project can turn into a slow application. Profiling is the process of measuring execution time, memory usage, and other resources to find bottlenecks. For beginner developers, the ability to profile code is a key skill that helps write efficient programs.
\nIn this article, we will look at how to find slow sections in Kotlin code using built-in tools and popular libraries. You will learn how to measure function execution time, analyze memory usage, and optimize critical sections.
\n\nBasic Kotlin Profiling Tools
\nSeveral approaches are available for profiling Kotlin code — from simple time measurements to professional profilers. Let's look at three main methods suitable for beginners.
\n\n1. Built-in measureTimeMillis Function
\nThe simplest way to measure execution time is to use the standard measureTimeMillis function from the Kotlin standard library. It returns the time in milliseconds spent executing a block of code.
import kotlin.system.measureTimeMillis\n\nfun main() {\n val time = measureTimeMillis {\n // Simulating heavy work\n var sum = 0L\n for (i in 1..1_000_000) {\n sum += i\n }\n println("Sum: $sum")\n }\n println("Execution time: $time ms")\n}\nThis method is ideal for quick tests, but it does not show which part of the code inside the block consumes the most resources. For more detailed analysis, use profilers.
\n\n2. Using System.nanoTime()
\nFor more precise measurements (nanoseconds), you can use System.nanoTime(). This is useful when you need to measure micro-optimizations.
fun main() {\n val start = System.nanoTime()\n // Your code\n Thread.sleep(100) // Simulating a delay\n val end = System.nanoTime()\n println("Time: ${(end - start) / 1_000_000} ms")\n}\nNote: nanoTime() is not tied to system time, so it is only suitable for measuring intervals, not absolute time.
3. Professional Profilers: JProfiler and VisualVM
\nFor serious performance work, use tools that operate at the JVM level (Kotlin compiles to JVM bytecode). Two popular free options:
\n- \n
- JProfiler — a powerful commercial tool with a trial version. It allows profiling CPU, memory, threads, and databases. \n
- VisualVM — a free tool included with the JDK. Suitable for beginners: it shows memory usage, object counts, and method execution times. \n
To run VisualVM, simply download it from the official website and connect it to your Kotlin process. You will see the real-time execution time of each method in real time.
\n\nPractical Example: Finding a Bottleneck in an Algorithm
\nImagine you wrote a function to find duplicates in a list. It works, but slows down on large data. Let's find the bottleneck using profiling.
\n\nStep 1. Write Slow Code
\nfun findDuplicates(list: List<Int>): List<Int> {\n val duplicates = mutableListOf<Int>()\n for (i in list.indices) {\n for (j in i + 1 until list.size) {\n if (list[i] == list[j] && !duplicates.contains(list[i])) {\n duplicates.add(list[i])\n }\n }\n }\n return duplicates\n}\n\nfun main() {\n val data = (1..10_000).toList() + (1..100).toList() // 100 duplicates\n val time = measureTimeMillis {\n val result = findDupli