Skip to main content

11. 자바 언어의 성능 향상 기법

  • 성능 개발자는 코드 설계 또한 구상을 잘 해야합니다.
  • 자료 구조에 대해 아는 것은 중요합니다.
  • 도메인 객체가 무엇인지 시스템 내부에서 도메인 객체의 수명이 어떠한지 아는 것은 성능에 매우 큰 영향을 미칩니다.

컬렉션 최적화#

대부분의 프로그래밍 언어 라이브러리는 최소한 두 가지 컨테이너를 제공합니다.

  • 순차 컨테이너(sequential container) : 수치 인덱스로 표기한 특정 위치에 객체를 저장합니다.
  • 연관 컨테이너(associative container) : 객체 자체를 이용해 컬랙션 내부에 저장할 위치를 결정합니다.

자바 컬렉션 API는 다음과 같습니다.

image


List 최적화#

자바에서는 리스트를 ArrayListLinkedList, 두가지 기본 형태로 나타냅니다.

참고로 Stack이나 Vector는 사용하지 않는 것이 좋습니다.

ArrayList#

  • 고정 크기 배열에 기반한 리스트
  • 용량은 가급적 미리 설정하는 게 좋습니다.
  • 일반적으로 ArrayList 크기를 정확히 결정하고 시작하는 게 성능이 좋습니다.
@Benchmark
public List<String> properlySizedArrayList() {
List<String> list = new ArrayList<>(1_000_000);
for(int i=0; i < 1_000_000; i++) {
list.add(item);
}
return list;
}
@Benchmark
public List<String> resizingArrayList() {
List<String> list = new ArrayList<>();
for(int i=0; i < 1_000_000; i++) {
list.add(item);
}
return list;
}

LinkedList#

  • LinkedList는 동적으로 증가하는 리스트입니다.
  • 이중 연결 리스트로 구현되어서 리스트에 덧붙입니다. (O(1))

ArrayList vs LinkedList#

  • 둘 중 선택하는 것은 데이터 접근/수정 패턴에 따라 다릅니다.
  • 삽입이나 삭제하는 경우에는 LinkedList가 좋습니다.
  • 다만 리스트를 주로 랜덤 액세스하는 경우에는 ArrayList가 정답닙니다.
  • LinkedList의 고유 기능이 꼭 필요한 경우가 아니면, ArrayList를 사용하는 것이 좋습니다.

Map 최적화#

  • 매핑이란 키와 연관된 값 사이의 관계를 뜻합니다.

HashMap#

image

  • 버킷 엔트리를 리스트에 저장합니다.
  • 값을 찾으려면 키 해시값을 계산하고, equals() 메서드로 리스트에서 해당 키를 찾습니다. (이때 키 중복은 허용되지 않습니다.)
  • 자바의 최근 버전은 상위 비트를 아래쪽 해시 부분에 분산시켜 재해시를 줄이고, 트리화 기술도 나왔습니다.

LinkedHashMap#

  • LinkedHashMap 은 HashMap의 서브 클래스, 이중 연결 리스트를 사용해 원소의 삽입 순서를 관리합니다.
  • 일반적으로 LinkedHashMap을 써야할 일은 비교적 드문 편입니다. (순서를 쓸일이 없으므로)

TreeMap#

  • 레드-블랙 트리를 구현한 Map입니다.
  • 다양한 키가 필요할 때 아주 유용합니다.
  • 데이터 분할에서 장점을 가집니다.

MultiMap#

  • 자바에서는 제공하지 않습니다.
  • Map<K, List<V>> 형태로 충분히 구현 가능합니다.

Set 최적화#

  • HashSet
    • HashMap으로 구현되어 있습니다.
    • 삽입, 삭제, contains 작업 복잡도는 O(1)입니다.
  • LinkedHashSet
    • LinkedHashMap으로 구현되어 있습니다.
    • 삽입, 삭제, contains 작업 복잡도는 O(1)입니다.
  • TreeSet
    • TreeMap을 사용합니다.
    • 순서대로 정렬된 키 순서를 유지합니다.
    • 삽입/삭제 복잡도는 log(n)이며 원소 순서는 유지됩니다.

도메인 객체#

  • 도메인 객체는 애플리케이션에 유의미한 비지니스 컨셉트를 나타낸 코드입니다.
  • 일반적으로 메모리 접유량과 인스턴스 개수가 모두 보통 코어 JDK에 있는 자료 구조가 상위권을 형성하는 것이 보통이며, 도메인 객체가 30위 정도에 있다면 메모리 누수가 발생한 신호로 볼 수 있습니다.

종료화 안 하기#

  • close() 함수를 잊고 놓치기 쉽습니다.
  • 이를 해결하기 위해 객체가 지닌 리소스를 자동으로 없애는 일은 플랫폼이 처리할 수 있습니다.
  • 어떤 객체가 더 이상 자신을 참조하지 않는다고 가비지 수집기가 판단하면 그 객체에 있는 finalize() 메서드를 호출한다. 서브클래스는 finalize() 메서드를 오버라이드해서 시스템 리소스를 처분하는 등 기타 정리 작업을 수행한

메서드 핸들#

  • 메서드 핸들
    • invokedynamic 호출부에부에 의해 호출되는 메서드를 나타내는 객체
    • 허용하는 호출 유형 및 적용되는 변환 유형을 제어합니다.
Last updated on