6 main highlights👨🏽💻 of Kotlin 1.9.20
👨🏽💻1. New default hierarchy template for setting up multiplatform projects
In Kotlin version 1.9.20 and onwards, the Kotlin Gradle plugin simplifies the setup for multiplatform projects by automatically generating shared source sets for common scenarios. This eliminates the need for manual configuration of the source set hierarchy in certain project setups. Instead, developers can explicitly specify the necessary targets for their projects. The Kotlin Gradle plugin introduces a default hierarchy template, streamlining the setup process. This template is a predefined structure of source sets embedded within the plugin, incorporating intermediate source sets that Kotlin automatically generates based on the declared targets. This feature enhances the ease of setup for multiplatform projects. For more details, refer to the full template provided by the Kotlin Gradle plugin.
🚀Kotlin 1.9.0 and earlier
kotlin {
androidTarget()
iosArm64()
iosSimulatorArm64()
sourceSets {
val commonMain by getting
val iosMain by creating {
dependsOn(commonMain)
}
val iosArm64Main by getting {
dependsOn(iosMain)
}
val iosSimulatorArm64Main by getting {
dependsOn(iosMain)
}
}
}🚀Kotlin 1.9.20
kotlin {
androidTarget()
iosArm64()
iosSimulatorArm64()
// The iosMain source set is created automatically
}👨🏽💻2. Full support for the Gradle configuration cache in Kotlin Multiplatform
In Kotlin version 1.9.20, the Kotlin Multiplatform plugin extends support for the Gradle configuration cache. This enhancement includes compatibility with the Kotlin CocoaPods Gradle plugin and integration tasks crucial for Xcode builds, such as `embedAndSignAppleFrameworkForXcode`. Now, all multiplatform projects can benefit from improved build times as the Gradle configuration cache accelerates the build process by reusing configuration phase results in subsequent builds. This optimization contributes to faster and more efficient multiplatform project development.
🚀Enabling the configuration cache
By default, Gradle does not use the configuration cache. To enable the cache at build time, use the configuration-cache flag:
❯ gradle --configuration-cacheYou can also enable the cache persistently in a gradle.properties file using the org.gradle.configuration-cache property:
org.gradle.configuration-cache=trueIf enabled in a gradle.properties file, you can override that setting and disable the cache at build time with the no-configuration-cache flag:
❯ gradle --no-configuration-cache👨🏽💻3. Custom memory allocator enabled by default in Kotlin/Native
In Kotlin 1.9.20, the new custom memory allocator is now enabled by default, replacing the previous default allocator, mimaloc. This update is designed to enhance garbage collection efficiency and improve the runtime performance of the Kotlin/Native memory manager.
The custom allocator divides system memory into pages, enabling independent sweeping in consecutive order. Each allocation forms a memory block within a page, with the page tracking block sizes. Different page types are optimized for various allocation sizes, ensuring efficient iteration through allocated blocks.
When a thread allocates memory, it searches for a suitable page based on the allocation size, maintaining a set of pages for different size categories. If the current page cannot accommodate the allocation, the thread requests a different page from the shared allocation space, which may need sweeping or creation.
The new allocator allows multiple independent allocation spaces simultaneously, facilitating experimentation with different page layouts to further improve performance.
🚀How to enable the custom memory allocator?
Enabling the custom memory allocator is automatic in Kotlin 1.9.20. If high memory consumption issues arise, users can switch back to mimaloc or the system allocator using -Xallocator=mimalloc or -Xallocator=std in the Gradle build script. Any issues can be reported in YouTrack to contribute to the ongoing improvement of the new memory allocator. For technical details, refer to the README.
👨🏽💻4. Performance improvements for the garbage collector in Kotlin/Native
In Kotlin 1.9.20, the Kotlin team introduces notable performance improvements for the garbage collector (GC) in the Kotlin/Native memory manager. Two key enhancements are highlighted:
🚀1. Full Parallel Mark for Reduced Pause Time:
Previously, the default garbage collector only performed a partial parallel mark, where the mutator thread marked the GC’s start from its own roots while a separate GC thread marked from global roots. This approach was effective in certain scenarios but less so for typical iOS applications. The new release adopts a full parallel mark strategy, combining paused mutators, the GC thread, and optional marker threads to process the mark queue. This change enhances the efficiency of the marking process, resulting in reduced GC pause times.
🚀2. Memory Tracking in Big Chunks for Improved Allocation Performance:
In earlier versions, the GC scheduler tracked the allocation of each object individually, which didn’t align with the allocation strategy of the new custom allocator or the mimalloc memory allocator. These allocators assign large areas for multiple objects at once. Kotlin 1.9.20 introduces the tracking of memory areas instead of individual objects. This adjustment accelerates the allocation of small objects by minimizing the tasks performed on each allocation, leading to improved allocation performance and reduced memory usage by the garbage collector.
👨🏽💻5. New and renamed targets in Kotlin/Wasm
In the latest release, Kotlin/Wasm introduces a new target, wasm-wasi, and renames the existing wasm target to wasm-js. In the Gradle DSL, these targets can be accessed using wasmWasi {} and wasmJs {}. To implement these targets in your project, update the build.gradle.kts file as follows:
kotlin {
wasmWasi {
// ...
}
wasmJs {
// ...
}
}🚀The deprecated wasm {} block has been replaced by wasmJs {}. To migrate an existing Kotlin/Wasm project, follow these steps:
- In the build.gradle.kts file, change the wasm {} block to wasmJs {}. - In your project structure, rename the wasmMain directory to wasmJsMain.
👨🏽💻6. Support for the WASI API in the standard library for Kotlin/Wasm
In the latest release, Kotlin introduces support for the WebAssembly System Interface (WASI) API in the standard library. WASI is a system interface designed for the Wasm platform, providing a standardized set of APIs for accessing system resources. This support enables the usage of Kotlin/Wasm beyond web browsers, making it suitable for server-side applications. WASI also brings capability-based security, adding an additional layer of security when interacting with external resources.
To run Kotlin/Wasm applications, a VM supporting Wasm Garbage Collection (GC) is required, such as Node.js or Deno. Notably, Wasmtime, WasmEdge, and other VMs are actively working to achieve full Wasm GC support.
To import a WASI function, developers can utilize the `@WasmImport` annotation, as demonstrated in the example code:
import kotlin.wasm.WasmImport
@WasmImport("wasi_snapshot_preview1", "clock_time_get")
private external fun wasiRawClockTimeGet(clockId: Int, precision: Long, resultPtr: Int): IntIt’s important to note that interoperability with JavaScript is not possible while targeting `wasmWasi`. For a comprehensive example, refer to the Kotlin GitHub repository.
