Kotlin logo

Kotlin

A concise multiplatform language developed by JetBrains

Ecosystem

K2 컴파일러 성능 벤치마크 및 사용자 프로젝트에서 성능을 측정하는 방법

Read this post in other languages:

이제 K2 컴파일러가 공개되어 사용해 보실 수 있습니다! 이번 블로그 글에서는 K2 컴파일러의 성능을 다양한 프로젝트에서 살펴보고 고유한 성능 통계를 수집할 수 있는 도구를 보여 드립니다.

K2 컴파일러가 안정화 버전에 이르기까지 오랜 시간이 걸렸습니다. 컴파일러를 완전히 다시 만들기로 한 이후, 새로운 타입 추론 알고리즘, 새로운 JVM 및 JS IR(중간 표현) 백엔드, 그리고 마지막으로 새로운 프런트엔드를 추가했습니다.

프런트엔드의 핵심 변경 사항은 보강된 의미 정보가 포함된 단일 통합 데이터 구조가 사용된다는 것입니다. 덕분에 컴파일링이 더욱 효율화되고 IntelliJ IDEA의 Kotlin 코드 분석이 개선됩니다.

Kotlin K2 컴파일러

이번 이니셔티브의 목적은 새로운 언어 기능의 개발 속도를 높이고, Kotlin이 지원하는 모든 플랫폼을 통합하고, Kotlin 개발자들을 위해 성능을 개선하는 것이었습니다.

IntelliJ IDEA에서 K2 컴파일러의 장점을 모두 활용하려면 K2 Kotlin 모드를 활성화하세요. K2 Kotlin 모드는 현재 알파 단계에 있기 때문에 모든 IDE 기능이 지원되지는 않습니다.

주요 성능 개선 사항

  • K2 컴파일러는 컴파일링 속도를 최대 94% 높입니다. 예를 들어 Anki-Android 프로젝트는 Kotlin 1.9.23에서 클린 빌드 시간이 57.7초였지만 Kotlin 2.0.0에서는 29.7초로 단축되었습니다.
  • K2 컴파일러의 초기화 단계가 최대 488% 빨라졌습니다. 예를 들어 Anki-Android 프로젝트는 Kotlin 1.9.23에서 증분 빌드의 초기화 단계가 0.126초 걸렸지만 Kotlin 2.0.0에서는 0.022초로 단축되었습니다.
  • Kotlin K2 컴파일러는 이전 컴파일러 대비 분석 단계가 최대 376% 빠릅니다. 예를 들어 Anki-Android 프로젝트는 Kotlin 1.9.23에서 증분 빌드의 분석이 0.581초 걸렸지만 Kotlin 2.0.0에서는 단 0.122초로 단축되었습니다.

설정

성능 테스트에 사용된 Kotlin 프로젝트는 GitHub에 있습니다. 이 프로젝트를 활용해 자신의 Kotlin 프로젝트에서 자체 통계를 수집하고 싶은 경우, 고유한 측정 수치 수집을 참조하세요.

프로젝트

다음의 오픈 소스 프로젝트에서 성능 테스트를 실행했습니다.

도구

성능 측정 수치를 수집하기 위해 Gradle Profiler를 사용했습니다.

Kotlin 빌드 보고서도 사용하여 여러 컴파일링 단계에서 상세한 측정 수치를 수집했습니다.

테스트 시나리오

Kotlin 프로젝트에서 가장 일반적인 컴파일링 활동을 다루기 위해 세 가지 시나리오를 만들었습니다.

  1. 클린 빌드: 사전 설정된 구성이나 빌드 캐시를 사용하지 않고 전체 프로젝트를 처음부터 빌드하는 시나리오입니다. 이 시나리오는 프로젝트를 처음으로 컴파일링하거나 프로젝트 구성을 변경한 후 컴파일링하는 경우입니다.
  2. ABI(애플리케이션 바이너리 인터페이스) 변경 사항이 없는 증분 빌드: 파일 하나를 변경했으나 이러한 변경 사항으로 인해 하위 프로젝트를 다시 컴파일링할 필요는 없는 시나리오입니다.
  3. ABI 변경 사항이 있는 증분 빌드: 파일 하나를 변경했으나 이러한 변경 사항으로 인해 모듈의 외부 인터페이스가 변경되어 모듈을 다시 컴파일링해야 하는 시나리오입니다.

Kotlin 1.9.23과 Kotlin 2.0.0에서 수집된 성능 데이터를 비교하였으며 Gradle 8.5를 계속 사용하였습니다.

Gradle 구성 캐시, 프로젝트 분리 및 빌드 캐시는 모든 시나리오에서 비활성화되었습니다. 성능 측정 수치가 수집되기 전에 워밍업을 10회 완료했습니다. 측정은 총 10회 실시했습니다.

수집된 측정 수치 종류

전체 Kotlin 컴파일링 시간 및 Gradle 빌드 시간에 더해 테스트에서 빌드 보고서를 사용하여 컴파일러가 각 컴파일링 단계에서 소요한 시간에 관한 데이터를 수집했습니다.

단계 설명
초기화 컴파일러가 컴파일링 클래스 경로의 모든 가용한 심볼을 초기화하고 읽습니다.
분석 컴파일러가 소스 코드를 문자 단위로 읽고 이를 유의미한 토큰으로 분해합니다. 이러한 토큰은 코드 구조를 파악하기 위해 분석되며, 분석이 완료되면 컴파일러가 의미 검사를 실행합니다.
IR 변환 컴파일러가 의미 정보를 내부 표현으로 변환합니다.
IR 단순화 컴파일러가 내부 표현을 더 간단한 형태로 변환하고 모든 특수 언어 구조체를 단순화합니다.
IR 생성 컴파일러가 최적화된 내부 표현을 최종 바이트코드로 변환합니다.

결과

여러 시나리오와 프로젝트에서 결과를 비교하였을 때 Gradle 빌드 속도가 일관적으로 최소 9% 빠르다는 것이 확인되었습니다. Anki-Android 프로젝트에서 가장 큰 개선이 보였으며, 컴파일러 시나리오에 관계없이 빌드 속도가 약 20% 개선된 것이 확인되었습니다.

클린 빌드 시나리오의 Gradle 빌드 시간 그래프 – Anki-Android 증분 빌드 시나리오의 Gradle 빌드 시간 그래프 – Anki-Android

클린 빌드

새로운 K2 컴파일러 아키텍처의 장점은 클린 빌드 시나리오에서 가장 두드러졌으며, Kotlin 2.0.0에서 두 프로젝트의 컴파일링이 유의미하게 빨랐습니다.

Exposed 프로젝트에서는 컴파일러 속도가 80% 개선되었으며, Kotlin 1.9.23에서는 5.8초 걸리던 컴파일링 시간이 Kotlin 2.0.0에서는 3.22초로 단축되었습니다. 이와 유사하게 Anki-Android 프로젝트에서도 컴파일러 성능이 94% 개선되어 Kotlin 1.9.23에서는 58초 걸리던 컴파일링 시간이 Kotlin 2.0.0에서는 30초로 단축되었습니다.

클린 빌드 시나리오의 Kotlin 컴파일링 시간 그래프 – Exposed 클린 빌드 시나리오의 Kotlin 컴파일링 시간 그래프 – Anki-Android

여러 컴파일링 단계의 성능을 살펴보니, 분석 단계에서 성능 개선이 가장 크다는 사실이 확인되었습니다(Exposed 및 Anki-Android 프로젝트에서 성능이 각각 156%, 194% 개선). 이는 K2 프런트엔드에 구현된 새로운 통합형 데이터 구조로 달성한 직접적 결과입니다. 새로운 컴파일러는 두 개가 아닌 하나의 데이터 구조를 관리하는 동시에 추가적인 의미 정보를 제공하므로 이 정도의 개선은 놀라운 일이 아닙니다.

클린 빌드 시나리오의 컴파일링 분석 그래프 – Exposed

파란색 = 분석 단계
클린 빌드 시나리오의 컴파일링 분석 그래프 – Anki-Android

파란색 = 분석 단계

증분 빌드

증분 빌드 시나리오에서도 컴파일러 성능 개선을 볼 수 있었습니다. 특히 Anki-Android 프로젝트에서는 컴파일링 속도가 두 증분 빌드 시나리오에서 275% 증가하였습니다.

증분 빌드 시나리오의 Kotlin 컴파일링 시간 그래프 – Anki-Android

그러나 Exposed 프로젝트의 결과는 그만큼 인상적이지는 않았습니다. ABI 변경이 있는 증분 빌드에서는 35% 높아졌고 ABI 변경이 없는 증분 빌드에서는 7% 높아지는 데 그쳐, 아직 이 분야는 계속 개선되어야 합니다.

여러 컴파일링 단계에서 성능을 조사하면서 확인된 가장 큰 성능 개선은 Anki-Android 프로젝트에서 각각 400% 가량 더 빨라진 초기화와 분석 단계에서 이뤄졌습니다.

ABI 시나리오의 증분 빌드 컴파일링 성능 분석 그래프 – Anki-Android
비 ABI 시나리오의 증분 빌드 컴파일링 성능 분석 그래프 – Anki-Android

Exposed 프로젝트는 초기화 및 분석 단계에서도 상대적으로 낮은 12~55%의 성능 개선이 이루어져 작은 성과를 내는 데 그쳤습니다. 사실 IR 단순화 및 IR 생성 단계에서 ABI 변경 사항이 있는 증분 빌드의 경우 성능 하락이 있었습니다. 그러나 이러한 단계에서 걸린 시간은 처음부터 매우 적어서 그 영향은 미미하다고 생각합니다. 예를 들어 IR 단순화는 Kotlin 1.9.23에서 0.01초가 걸렸고, Kotlin 2.0.0에서는 0.014초가 걸렸습니다.

고유한 측정 수치 수집

Kotlin 2.0.0 릴리스와 더불어 K2 컴파일러에 대한 관심이 커지고 있습니다. 이제는 여러분이 테스트해 볼 차례입니다. 이 섹션에서는 사용자가 Kotlin 프로젝트 성능 통계를 수집하는 방법을 알려 드립니다.

사용자의 Kotlin 프로젝트에서 쉽고 빠르게 벤치마크를 진행할 수 있도록 특별히 성능 관리 도구를 준비했습니다. 이는 원격으로든 로컬로든 모든 Kotlin 프로젝트에서 성능 측정 수치를 수집할 수 있도록 도와주는 Kotlin 기반의 프로젝트입니다. 기본적으로 이 프로젝트는 Kotlin 1.9.23 버전과 2.0.0-RC1 버전에서 벤치마크 테스트를 실행합니다. 그러나 필요에 따라 자신에게 맞는 테스트 시나리오를 맞춤 설정할 수 있습니다. 시각화를 위해 이러한 시나리오에서 생성된 원시 데이터를 분석할 수도 있고, 제공된 Kotlin Notebook을 사용하여 좀 더 편리하게 시각적인 표현을 확인할 수도 있습니다.

1단계: IntelliJ IDEA에서 프로젝트 열기

  1. k2-performance-metrics 저장소를 복제합니다.
  2. IntelliJ IDEA 최신 버전을 다운로드하고 설치합니다.
  3. IntelliJ IDEA 시작 화면에서 Open(열기)을 클릭하거나 메뉴 바에서 File(파일) | Open(열기)을 선택합니다.
  4. k2-performance-metrics 폴더로 이동한 다음 Open(열기)을 클릭합니다.

2단계: 프로젝트 설정

  1. 환경 변수를 검증합니다.
    1. JAVA_HOME 변수가 프로젝트를 컴파일링할 때 사용되므로 설정되었는지 확인합니다.
    2. 프로젝트에 Android 개발이 포함된 경우 ANDROID_HOME이 설정되었는지 확인합니다.
  2. gradle.properties 파일에서 측정 수치를 수집하려는 프로젝트를 다음 중 하나의 방법으로 추가합니다.
    • project.path에 로컬 경로를 추가합니다.
    • project.git.url에 GitHub URL을 추가하고 테스트를 실행하려는 커밋을 project.git.commit.sha에 추가합니다.
  1. 증분 빌드 시나리오의 경우 변경 사항이 있는 파일의 경로를 다음과 같이 추가합니다.
    1. scenario.abi.changes: ABI 변경 사항이 있는 증분 빌드 시나리오의 경우.
    2. scenario.non.abi.changes: ABI 변경 사항이 없는 증분 빌드 시나리오의 경우.

3단계: 측정 수치 수집

  1. IntelliJ IDEA에서 View(보기) | Tool Windows(도구 창) | Gradle을 선택하여 Gradle 도구 창을 엽니다.
  2. Tasks(작업) | benchmarks(벤치마크)에서 runBenchmarks(벤치마크 실행) 작업을 선택하고 실행합니다.
Tasks(작업) | benchmarks(벤치마크)에서 runBenchmarks 작업을 선택하고 실행합니다.

혹은 k2-performance-measurement 루트 디렉터리로부터 다음의 명령어를 터미널에서 실행해도 됩니다.

./gradlew runBenchmarks -t

빌드 보고서는 기본적으로 reports/{kotlin-version}/{scenario-name} 폴더에 있습니다.

사용자 지정 테스트 시나리오를 만들고 싶은 경우, 작업 클래스를 build.gradle.kts 파일에서 확장하면 됩니다. 자세한 정보는 k2-performance-metrics 저장소의 README.md 파일에서 사용자 지정 빌드 시나리오 만들기 섹션을 참조하세요.

4단계: Kotlin Notebook으로 결과 분석

Kotlin Notebook을 사용하려면 IntelliJ IDEA Ultimate이 필요합니다.

  1. IntelliJ IDEA에서 Settings(설정)/Preferences(환경 설정)| Plugins(플러그인)으로 이동한 다음 Marketplace 탭으로 이동합니다.
  2. 검색창에서 “Kotlin Notebook”을 검색하고 Install(설치)을 선택합니다.
  3. benchmarkResult.ipynb를 열고 여백에서 Run All(전체 실행)을 눌러 모든 셀을 실행합니다.
모두 실행

결론

요약하자면 새로운 K2 컴파일러 아키텍처는 프로젝트의 컴파일링 시간을 크게 줄입니다. 클린 빌드와 컴파일링의 분석 단계가 특히 빨라지며, Gradle 빌드 시간도 새로운 컴파일러에서 감소합니다. 그러나 실제 개선 정도는 특정 프로젝트에 따라 달라질 수 있습니다. 어떤 프로젝트는 성능이 크게 개선될 수 있지만, 어떤 프로젝트에서는 효과가 미미할 수 있습니다.

새로운 K2 컴파일러를 만드는 과정에서 내부 프로젝트로 컴파일러의 성능을 끊임없이 테스트했습니다. 또한 EAP 옹호자들과 얼리어답터들도 자체 프로젝트로 테스트하면서 성능과 사용 편의성에 관한 값진 피드백을 제공해 주었습니다.

이제는 여러분께 K2 컴파일러를 사용해 보고 피드백을 주시기를 부탁드립니다. 공개 Slack(여기에서 초대 받기)의 #k2-early-adopters 채널에 참여하고 지원을 받거나 논의에 참여해 보세요.  특정 문제나 버그가 발생하는 경우 Kotlin YouTrack 프로젝트에서 이슈를 생성해 주세요. 여러분의 피드백은 K2를 개선하고 커뮤니티의 기준과 요구 사항에 맞추는 데 매우 중요한 역할을 합니다.

기타 유용한 글과 동영상

게시물 원문 작성자

Jessie Cho

Sarah Haggarty

image description

Discover more