67. 최적화는 신중히 하라

📜 최적화에 대한 격언들

"효율성이라는 이름 아래 행해진 컴퓨팅 죄악이 (심지어 효율을 높이지도 못하면서) 다른 어떤 핑계보다 더 많다." - 월리엄 울프

"(전체의 97% 정도인) 자그마한 효율성은 모두 잊자. 섣부른 최적화가 만악의 근원이다." - 도널드 크누스

"최적화를 할 때는 다음 두 규칙을 따르라.

  1. 하지 마라.

  2. (전문가 한정) 아직 하지 마라. (명백하고 최적화되지 않은 해법을 찾을 때까지)" - M. A. 잭슨

  • 최적화의 어두운 진실

  • 좋은 결과보다 해로운 결과

  • 섣부른 최적화는 더욱 위험

✨ 좋은 프로그램을 먼저 작성하라!

  • 성능 때문에 좋은 구조를 희생하지 마라

    • 빠른 프로그램보다 좋은 프로그램

    • 읽기 쉽고, 유지보수하기 좋고, 재사용하기 좋은 코드가 우선

  • 견고한 구조가 최적화의 길 안내

    • 성능 문제 발생 시, 시스템 전체에 영향 없이 해당 부분 개선 용이

    • 특히 정보 은닉 원칙을 잘 따른 프로그램

🤔 설계 단계에서의 성능 고려

  • 성능 문제를 완전히 무시하라는 뜻은 아니다

    • 아키텍처 결함은 나중에 수정하기 매우 어렵거나 불가능

    • 완성된 설계의 기본 틀을 변경 시 복잡한 시스템 생성

    • 설계 단계에서 성능을 반드시 염두에 둬라

  • API 설계 시 성능 영향을 고려

    • 가변 public 타입: 불필요한 방어적 복사를 유발 가능성

    • 상속 남용: 컴포지션으로 가능한데 상속을 사용하면, 상위 클래스의 성능 제약까지 상속

    • 구현 타입 사용: 인터페이스 대신 특정 구현 타입을 사용하면, 더 빠른 구현체가 나와도 활용 어려움

  • API 설계 실수 사례: java.awt.ComponentgetSize() 메서드

    public Dimension getSize() {
      // ... 내부 로직 ...
      // 매번 새 객체 생성 (방어적 복사)
      return new Dimension(currentWidth, currentHeight)
    }
    • 가변 객체인 Dimension을 반환하도록 설계

      • 호출 시마다 방어적 복사본 생성 필요

    • 성능 문제 유발

      • 결국 getWidth(), getHeight() 메서드 추가

    • 기존 API는 여전히 남아있어, 잘못된 설계의 폐해 지속

  • 잘 설계된 API는 보통 성능도 좋습니다.

    • ⚠️성능 때문에 API를 왜곡하지 마세요!

    • 성능 문제는 플랫폼이나 라이브러리 버전업으로 해결 가능

    • 잘못 설계된 API는 영원히 고통

🚀 언제, 어떻게 최적화해야 하는가?

  1. 측정, 측정, 측정! 📊:

    • 최적화의 첫 규칙은 "하지 마라", 두 번째는 "아직 하지 마라"

    • 최적화 전후로 반드시 성능 측정

      • 추측에 기반한 최적화는 효과가 없거나 오히려 성능을 악화시킬 수 있습니다.

    • "90%의 시간은 10%의 코드에서 사용된다"는 사실 기억

      • 느릴 것이라 짐작한 부분이 실제 병목 지점이 아닐 수 있습니다.

  1. 프로파일링 도구 활용 🛠️:

    • 최적화 노력을 어디에 집중해야 할지 찾는 데 도움

    • 병목 지점을 정확히 체크하기

    • jmh (마이크로벤치마킹 프레임워크)

  1. 알고리즘을 먼저 살펴보세요 🧠:

    • 프로파일러로 병목 지점을 찾았다면, 가장 먼저 알고리즘의 효율성을 확인

    • 비효율적인 알고리즘을 사용하고 있다면, 다른 어떤 최적화보다 알고리즘 변경이 훨씬 효과적

  1. 반복적인 개선 🔁:

    • 병목 지점을 최적화하고, 다시 성능을 측정하세요. 만족할 때까지 이 과정을 반복합니다.

☕ 자바 환경에서의 최적화 특징

  • 예측의 어려움: 자바는 C/C++보다 추상화 수준이 높아(코드와 실제 CPU 명령어 간의 격차), 최적화 효과를 예측하기 더 어렵습니다. 성능에 대한 잘못된 통념도 많습니다.

  • 환경 의존성: 자바 성능 모델은 JVM 구현, 릴리스 버전, 하드웨어에 따라 달라집니다. 따라서 다양한 환경에서 프로그램을 실행한다면, 각각의 환경에서 성능을 측정하고 타협점을 찾아야 할 수도 있습니다.

  • 복잡성 증가: 현대 자바 소프트웨어 스택(프로세서, VM, 라이브러리, 하드웨어 등)은 매우 복잡해져 성능 예측이 더욱 어려워졌습니다. 측정의 중요성이 더욱 커졌습니다.


✨ 핵심 정리 ✨

섣부른 최적화는 금물! 좋은 설계를 우선하세요.

  1. 빠른 프로그램 < 좋은 프로그램:

    • 일단 깨끗하고 명확하며 구조가 좋은 프로그램을 작성하는 데 집중하세요.

  2. 설계 시 성능 고려

    • 아키텍처, API, 프로토콜, 데이터 포맷 등 설계 단계에서 성능 영향을 염두에 두세요.

    • 잘못된 설계는 나중에 수정하기 어렵습니다.

  3. 구현 후 측정

    • 시스템 구현 완료 후 성능을 측정하세요.

  4. 병목 지점 최적화

    • 성능이 만족스럽지 않다면 프로파일러로 병목 지점을 찾으세요.

  5. 알고리즘 확인

    • 가장 먼저 알고리즘 효율성을 검토하고 개선하세요.

  6. 반복 및 재측정

    • 최적화 후에는 반드시 다시 성능을 측정하고, 만족할 때까지 반복하세요.

Last updated