아이템 67. 최적화는 신중히 하라. - ksw6169/effective-java GitHub Wiki

최적화는 신중히 하라.

  • 최적화는 좋은 결과보다는 해로운 결과로 이어지기 쉽다. 섣불리 진행하면 특히 더 그렇다.
  • 즉, 빠르지도 않고 제대로 동작하지 않으면서 수정하기는 어려운 소프트웨어를 탄생시킬 수 있다.

성능 때문에 견고한 구조를 희생하지 말자.

  • 빠른 프로그램보다는 좋은 프로그램을 작성하라. 좋은 프로그램이지만 원하는 성능이 나오지 않는다면 그 아키텍처 자체가 최적화할 수 있는 길을 안내해줄 것이다.
  • 좋은 프로그램은 정보 은닉 원칙을 따르므로 개별 구성 요소의 내부를 독립적으로 설계할 수 있다. 즉, 시스템의 나머지에 영향을 주지 않고도 각 요소를 다시 설계할 수 있다.

성능을 제한하는 설계를 피하라.

  • 변경이 가장 어려운 설계 요소는 바로 컴포넌트끼리 혹은 외부 시스템과의 소통 방식이다. (API, 네트워크 프로토콜, 영구 저장용 데이터 포맷 등)
  • 이런 설계 요소들은 완성 후에는 변경하기 어렵거나 불가능할 수 있다. 또한 동시에 시스템 성능을 심각하게 제한할 수 있다.

API를 설계할 때 성능에 주는 영향을 고려하라.

잘 설계된 API는 성능도 좋은게 보통이다. 그러니 성능을 위해 API를 왜곡하지 말자. 다음은 API를 설계할 때 고려할만한 사항들이다.

  • public 타입을 가변으로 만들면(=내부 데이터를 변경할 수 있게 만들면) 불필요한 방어적 복사를 수없이 유발할 수 있다.
  • 컴포지션으로 해결할 수 있음에도 상속 방식으로 설계한 public 클래스는 상위 클래스에 영원히 종속되며 성능 제약까지도 물려받게 된다.
  • 인터페이스도 있는데 굳이 구현 타입을 사용하는 것 역시 좋지 않다. 개선된 구현체가 나오더라도 이를 이용하지 못하게 되기 때문이다.

각각의 최적화 시도 전후로 성능을 측정하라.

  • 구조가 잘 잡힌 프로그램을 작성했다면 최적화를 고려하라.
  • 시도한 최적화 기법이 오히려 성능을 더 나빠지게 만들 수도 있다. 주요 원인은 프로그램에서 시간을 잡아먹는 부분을 추측하기가 어렵기 때문이다.
  • 이 때 프로파일링 도구(profiling tool)는 최적화 노력을 어디에 집중해야 할지 찾는 데 도움을 준다.
  • 그 외에 jmh도 프로파일러는 아니지만 자바 코드의 상세한 성능을 알기 쉽게 보여주는 마이크로 벤치마킹 프레임워크로 이 역시 성능 측정에 도움을 준다.

핵심 정리

  • 좋은 프로그램을 작성하다 보면 성능은 따라오기 마련이다. 하지만 시스템을 설계할 때, 특히 API, 네트워크 프로토콜, 영구 저장용 데이터 포맷을 설계할 때는 성능을 염두에 두어야 한다.
  • 시스템 구현을 완료했다면 성능을 측정하라. 충분히 빠르면 그것으로 끝이다.
  • 그렇지 않다면 프로파일러를 사용해 문제의 원인을 파악하고 최적화를 수행하라.
  • 가장 먼저 어떤 알고리즘을 사용했는지 살펴보자. 알고리즘을 잘못 골랐다면 다른 저수준 최적화는 의미가 없다. 만족할 때까지 이 과정을 반복하고, 모든 변경 후에는 성능을 측정하라.

참고 자료

  • Effective Java 3/E