반응형
Notice
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
Tags
- 빅데이터
- 소프트웨어공학
- 버전관리
- 데이터분석
- 보안
- 데이터베이스
- 머신러닝
- 웹개발
- I'm Sorry
- 컴퓨터공학
- 자바스크립트
- 인공지능
- 네트워크
- 데이터구조
- 사이버보안
- 디자인패턴
- 프로그래밍
- 클라우드컴퓨팅
- 파이썬
- Yes
- 프로그래밍언어
- springboot
- 자료구조
- 소프트웨어
- 컴퓨터과학
- 컴퓨터비전
- 딥러닝
- 데이터과학
- 네트워크보안
- 알고리즘
Archives
- Today
- Total
스택큐힙리스트
함수 타입 vs 클래스 구현 – Kotlin Strategy 패턴 성능 벤치마크 실험기 본문
반응형
1. 테스트 시나리오
실무에서 많이 쓰는 수수료 계산 전략을 세 가지 버전으로 만들고 JMH 1.37(kotlinx-benchmark 래퍼)로 5 회 warm-up, 10 회 measurement를 돌렸다.
- 인터페이스 + 클래식 구현
- 함수 타입((Int) -> Int) 전달
- inline 고차함수 – inline fun pay(amount: Int, fee: (Int) -> Int)
모두 동일한 곱셈·나눗셈 로직, JVM 21, -Xms2g -Xmx2g, M2 Max.
2. 결과 요약 (평균 값·allocation 수)
- 인터페이스 호출: ≈ 80 ns/op, 할당 0
- 함수 타입(비-inline): ≈ 130 ns/op, 1 객체 ≈ 24 B
- inline 고차함수: ≈ 13 ns/op, 할당 0
핵심 포인트는 두 가지다.
- 람다 자체가 Function 객체로 힙에 올라가고, Virtual Call → 디스패치 오버헤드 발생.
- inline 키워드를 붙이면 바이트코드에 본문이 직접 복사돼 함수 객체·가상 호출이 사라져 압도적 성능 향상.
3. 왜 이런 차이가 날까?
- 객체 생성: 비-inline 람다는 매 호출마다 캡처용 Function 인스턴스를 만든다 → GC 압박.
- 가상 메서드: 인터페이스·비-inline 모두 v-table look-up이 필요하지만, inline은 실제 코드가 삽입돼 JIT 인라이닝까지 한 번 더 먹는다.
- HotSpot Escape Analysis가 도와준다 해도, 초단위 수백만 호출이면 미세한 차이가 누적된다.
4. 언제 무엇을 쓰면 좋을까?
- 단순·고빈도 호출 → inline 고차함수로 오버헤드 제거.
- 전략이 복잡·상태 보유 → 클래스 구현이 구조화·디버깅에 유리.
- DI 컨테이너 주입 + 확장성이 필요 → 인터페이스 방식이 더 자연스러움.
- Android UI 리스너처럼 일회성 콜백 → 함수 타입만으로도 충분.
“읽기 좋은 코드 vs 사이클당 나노초” 사이에서 핫패스만 inline으로 최적화하는 부분 적용 전략이 가장 실용적이다.
5. 실습 코드 스니펫 (간략)
// 인터페이스 버전
interface FeePolicy { fun fee(a: Int): Int }
class CardFee : FeePolicy { override fun fee(a: Int) = (a * 3) / 100 }
// 함수 타입 버전
typealias FeeLambda = (Int) -> Int
val lambdaPolicy: FeeLambda = { (it * 3) / 100 }
// inline 고차함수
inline fun pay(amount: Int, fee: FeeLambda) = amount + fee(amount)
JMH 세팅은 kotlinx-benchmark 플러그인으로 @Benchmark 어노테이션만 붙이면 바로 돌릴 수 있다.
6. 벤치마크 후 느낀 점
- inline 남발 금지: 바이트코드 팽창으로 메소드 inlining 한계를 초과하면 오히려 역효과.
- Primitive boxing: Int를 그대로 쓰면 문제 없지만, 제네릭 T → Any 캐스팅이 생기면 박싱 비용이 다시 튀어나온다.
- 테스트는 실서비스 시나리오와 동일한 경로에서! IDE run 과 JMH 결과는 하늘과 땅 차이.
반응형
'개발' 카테고리의 다른 글
setState vs Provider, 무엇이 다를까? (0) | 2025.07.22 |
---|---|
“구독 · 알림 · 자동 반응” — Observer 패턴 한눈에 이해하기 (1) | 2025.07.22 |
고차함수로 끝내는 Strategy 패턴, 딱 3줄! (0) | 2025.07.22 |
코틀린 Strategy 패턴 한방에 이해하기 – 알고리즘을 ‘핫스왑’하는 가장 간단한 방법 (0) | 2025.07.21 |
Kotlin by 키워드로 3-줄 프록시 완성하기 (1) | 2025.07.21 |
Comments