Swift — true to its name — is a fast language. It is just about as close-to-the-metal as any higher level programming language can be. Stack-allocated value types make efficient use of resources, and the lack of garbage collection means that memory allocation and deallocation is predictable, with controllable memory watermarks and minimal overhead from reference counting. Swift code is compiled down to architecture-specific machine instructions before being packaged into the app.ipa archive that is ultimately distributed to end users for installation on their iPhone.
Java (and, therefore, Kotlin) is not quite as fast or as efficient with memory as Swift. When a Kotlin Android app is built using gradle or an IDE, it processes the source code into Java bytecode, which is an intermediate representation of the program’s instructions. Next, the Java bytecode is re-processed into Dalvik Executable (DEX) bytecode for packaging into an app.apk for distribution to Android devices. Finally, when a user installs the app, the DEX is converted on the device into architecture-specific instructions, which is what is ultimately run during the program’s execution. The app’s code is run within Android’s managed runtime (ART), which provides automatic memory management using garbage collection (GC).
Skip is a tool that transpiles Swift into Kotlin, enabling the creation of SwiftUI apps for both iOS and Android. The transpiled Kotlin code maintains Swift’s semantics and behavior. But since Java lacks true value types, Swift struct and enumeration types can only be translated into Kotlin classes; this means that they will always be allocated on the heap and subject to indeterministic garbage collection, just like any other Java object. These, and other factors, contribute to the difference in performance and efficiency between the two languages.