Mobile Development 30 min read

Cross‑Platform Language Benchmark and Interoperability Analysis

The study benchmarks Kotlin, JavaScript, Dart, C++ and Swift across iOS, Android and HarmonyOS using 237 protobuf files, finding Kotlin’s performance and binary size rival native Swift, JavaScript slower with higher memory, while C++/Rust excel but need more effort, leading to a recommendation of Kotlin Multiplatform with a three‑repo structure for optimal reuse and maintainability.

Bilibili Tech
Bilibili Tech
Bilibili Tech
Cross‑Platform Language Benchmark and Interoperability Analysis

This article presents a comprehensive benchmark of several cross‑platform languages (Kotlin, JavaScript, Dart, C++, Swift) on three mobile platforms: iOS, Android, and HarmonyOS. The evaluation focuses on execution efficiency, application size before and after adding test cases, peak memory usage, and memory overhead.

The test set consists of 237 protobuf files (total size 2.2 MB) collected from Bilibili’s production environment. Each protobuf is serialized and deserialized to form the test case.

Test Process

1. Build a minimal test project for each language on each platform, providing a UI to trigger the test case and collect statistics. 2. Generate language‑specific protobuf code using custom protoc plugins (one plugin per language). The generated code iterates over all messages, creates an instance, serializes it to a byte array, and deserializes it back.

Example C++ test module:

// fission.proto corresponding C++ test module
namespace bilibili_::account_::fission_::v1_::fission_::proto {
    template
inline void TestMessage() {
        auto str = Message().SerializeAsString();
        auto msg = Message().ParseFromString(str);
    }

    inline void Test() {
        TestMessage<::bilibili::account::fission::v1::EntranceReq>();
        TestMessage<::bilibili::account::fission::v1::EntranceReply>();
        TestMessage<::bilibili::account::fission::v1::AnimateIcon>();
        TestMessage<::bilibili::account::fission::v1::WindowReq>();
        TestMessage<::bilibili::account::fission::v1::WindowReply>();
        TestMessage<::bilibili::account::fission::v1::PrivacyReq>();
        TestMessage<::bilibili::account::fission::v1::PrivacyReply>();
    }
}

Example Kotlin test module:

// fission.proto corresponding Kotlin test module
@file:OptIn(ExperimentalSerializationApi::class)

package bilibili_account_fission_v1_fission

import kotlinx.serialization.*
import kotlinx.serialization.protobuf.*
import com.bapis.bilibili.account.fission.v1.*

fun doTest() {
    ProtoBuf.decodeFromByteArray
(ProtoBuf.encodeToByteArray(KEntranceReq()))
    ProtoBuf.decodeFromByteArray
(ProtoBuf.encodeToByteArray(KEntranceReply()))
    ProtoBuf.decodeFromByteArray
(ProtoBuf.encodeToByteArray(KAnimateIcon()))
    ProtoBuf.decodeFromByteArray
(ProtoBuf.encodeToByteArray(KWindowReq()))
    ProtoBuf.decodeFromByteArray
(ProtoBuf.encodeToByteArray(KWindowReply()))
    ProtoBuf.decodeFromByteArray
(ProtoBuf.encodeToByteArray(KPrivacyReq()))
    ProtoBuf.decodeFromByteArray
(ProtoBuf.encodeToByteArray(KPrivacyReply()))
}

Example Swift test module:

import Foundation
import SwiftProtobuf

fileprivate func testMessage
(type: T.Type) {
    let message = T()
    do {
        let encoded = try message.serializedData()
        let decoded = try T(serializedData: encoded)
    } catch {
        print("Error: \(error)")
    }
}

func testBilibiliPmmsV1PmmsProto() {
    testMessage(type: Bilibili_Pmms_V1_GetPullMessagesReq.self)
    testMessage(type: Bilibili_Pmms_V1_GetPullMessagesResponse.self)
    testMessage(type: Bilibili_Pmms_V1_Position.self)
    testMessage(type: Bilibili_Pmms_V1_ControlParams.self)
    testMessage(type: Bilibili_Pmms_V1_Message.self)
}

Compilation and execution steps differ per platform: C++ uses -Os -fvisibility=hidden -fvisibility-inlines-hidden -dead_strip; other languages use default Release builds. Dart tests run via Flutter AOT; JavaScript on iOS uses JavaScriptCore, on HarmonyOS uses ArkRuntime.

Results (illustrated in the original article) show that Kotlin’s performance and binary size are comparable to native Swift on iOS and to Java on Android. JavaScript exhibits lower execution speed and higher memory footprint due to its garbage collector. C++ and Rust achieve the best size and speed but require more engineering effort for interop.

Interoperability Discussion

The article classifies languages into two groups: those without an independent runtime (C++, Rust, Kotlin) and those with a runtime (JavaScript, Dart). For the former, interop relies on compiler/linker capabilities and platform bindings (e.g., extern "C" for iOS, JNI for Android, napi for HarmonyOS). For the latter, interop is provided by the language runtime’s bridge mechanisms (e.g., QuickJS, JSCore, ArkRuntime) and method‑channel patterns for Dart.

Key observations include:

Bidirectional interop is essential for core modules (playback, networking, rendering) that need stable, low‑level APIs.

Kotlin Multiplatform (KMP) offers native interop on all three platforms, making it the preferred choice for Bilibili’s business‑logic layer.

Performance measurements confirm that Kotlin’s runtime overhead is acceptable for core modules, while Dart’s AOT performance is sufficient when used within Flutter.

Community support, tooling, and modern language features (coroutines, async/await) further justify Kotlin’s selection.

The article also explores repository strategies (One repo, Two repo, Three repo) for managing cross‑platform codebases, ultimately recommending a “Three repo” approach (separate monorepos for Android, iOS, HarmonyOS, plus a shared KMP repo) to balance reuse and tool‑chain complexity.

Finally, the author reflects on broader topics such as the trade‑off between code reuse and communication overhead, the impact of economic cycles on team structure, and future directions like cross‑platform UI and dynamic configuration.

References and further reading are listed at the end of the original document.

mobile developmentPerformancecross‑platformKotlinBenchmarkinteroperability
Bilibili Tech
Written by

Bilibili Tech

Provides introductions and tutorials on Bilibili-related technologies.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.