반응형

아이템 45: 불필요한 객체 생성을 피하라

객체 생성은 언제나 비용을 요구한다.
일반적으로는 큰 비용이 들어가진 않지만 상황에 따라선 큰 비용이 들어갈 수도 있다.
따라서 불필요한 객체의 생성을 피하는 것이 최적화의 관점에서 좋다.

 

JVM에서 문자열과 범위가 작은 기본 자료형은 자동으로 재사용 된다. 
하지만 범위가 큰 자료형은 wrap되기 때문에 재사용되지 않는다.

val str1 = "Lorem ipsum dolor sit amet"
val str2 = "Lorem ipsum dolor sit amet"
print(str1 == str2)  // true
print(str1 === str2) // true

val i1: Int? = 1
val i2: Int? = 1
print(i1 == i2)  // true
print(i1 === i2) // true

val j1: Int? = 1234
val j2: Int? = 1234
print(j1 == j2)  // true
print(j1 === j2) // false

wrapper클래스는 기본 자료형보다 더 많은 기능을 제공하고 편리하지만, 더 많은 비용이 발생한다.

 

어떤 객체를 wrap했을 때의 비용

  • 객체는 더 많은 용량을 차지한다.
    (64비트 운영체제 기준으로 기본형에 비해 5배 이상의 공간을 차지함)
  • 요소가 캡슐화 되어있다면 접근에 추가적인 함수 호출이 필요하다.
    -> 비용이 크진 않지만, 티끌 모아 태산!
  • 객체는 생성되고 메모리 영역에 할당, 레퍼런스를 만드는 작업의 비용이 발생

 

비용을 줄이는 방법

1. 싱글톤

2. 캐시(메모이제이션)

3. 무거운 객체를 외부 스코프로

// bad
fun<T: Comparable<T>> Iterable<T>.countMax(): Int = 
	count { it == this.max() }
    
// good
fun<T : Comparable<T>> Iterable<T>.countMax(): Int = {
	val max = this.max()
    return count { it == max }
}

4. 지연 초기화(by lazy)
백엔드 어플리케이션에서는 좋지 않음(초기 실행시간이 중요한 경우)

// bad
class A{
	
    val b = B()
    val c = C()
    val d = D()
    
    // ...
    
}

// good
class A{
	
    val b by lazy{ B() }
    val c by lazy{ C() }
    val d by lazy{ D() }
    
    // ....
    
}

5. 기본 자료형 사용
auto wrapping 되는 경우를 유의해야 함
라이브러리를 개발하는 정도의 수준이 아니라면 큰 의미는 없긴 함…

 

정리

방법들은 최적화 뿐만 아니라, 가독성 측면에서도 도움이 되기 때문에 경우에 따라 적극적으로 사용하는것을 권장함.

아이템 46: 함수 타입 파라미터를 갖는 함수에 inline 한정자를 붙여라

 

아이템 47: 인라인 클래스의 사용을 고려하라

 

아이템 48: 더 이상 사용하지 않는 객체의 레퍼런스를 제거하라

반응형

+ Recent posts