프로그래밍에서 최적화에 관한 세 가지 유명한 격언이 있다.
컴퓨터에서의 대부분의 죄악은 섣부른 효율성이라는 이름으로 저질러진다. - William A. Wulf
우리는 작은 효율성에 대해서는 잊어버려야 한다. 섣부른 최적화는 만악의 근원이다. - Donald E. Knuth
최적화라는 명목으로 우리는 다음 두 가지 규칙을 따른다. - M. A. Jackson
규칙 1. 최적화 하지 마라
규칙 2. (오직 전문가만) 아직 최적화 하지 마라, 즉 완벽하게 명백한 최적화되지 않은 해결책이 있지 않는 이상 최적화 하지마라
이 세 가지 격언은 지난 20년간 자바 프로그래밍 언어를 지배해왔다.
최적화를 미숙하게 했을 경우 이점보다 실이 많다는 것이다.
빠른 프로그램을 작성하기 보다, 좋은 프로그램을 작성하라.
좋은 프로그램이란 무엇인가? 좋은 프로그램은 정보은닉(information hiding)을 준수한다.
정보 은닉은 하나의 컴포넌트 내에 설계를 지역화하는 것이다. 하나의 컴포넌트가 변경되어도 시스템의 나머지 컴포넌트에 영향이 미치지 않는다.
성능을 고려하지 말라는 것이 아니다.
만연하게 영향을 미치는 설계 결함(pervasive architectural flaws)는 시스템을 수정하지 않고서는 구현을 수정하는 것이 불가능할 것이다.
성능을 제한하는 디자인 설계를 하지마라.
wire-level protocol은 변경이 어려운 API에 속한다. 이후에 변경이 어려울 것을 고려하여 성능을 제한하면 안된다.
API 설계의 성능 결과를 고려하라.
-
퍼블릭 타입을 변경가능하게 만드는 것은 불필요한 방어적 복사(defensive copying)을 요구한다.
-
합성이 적절해 보이는 설계에 상속을 사용하는 것은 슈퍼 클래스와 서브 클래스의 결합도를 상승한다.
-
인터페이스보다 구체적인 구현 타입을 사용하라.
다행히, 좋은 API 설계가 곧 좋은 성능과 일치한다.
- 성능을 올리기 위해서 API를 변형하지마라
- 해당 API의 이후 릴리즈에서 성능 문제가 발생할 수 있다.
성능 최적화를 시도한 구간에 성능 측정을 하라
- 프로파일링 도구는 최적화에 시간을 아껴준다.
- 런타임 정보를 제공한다.
- 시스템에 더 많은 코드가 작성될 수록, 프로파일러를 사용하는 것이 중요하다.
- 예를 들어, 건초더미 속에 바늘을 찾는 다고 생각해보자. 금속 탐지기로 찾는다면 훨씬 수월할 것이다.
- 자바는 C와 C++보다 최적화의 영향을 측정하는 것이 중요하다.
- 프로그래머가 작성하는 코드와 CPU가 실행하는 코드 사이의 간극을 *추상화 갭(abstraction gap)*이라고 한다.
- 이 추상화 갭이 커질 수록 최적화 성능 결과를 예측하는 것이 어렵다.
자바의 성능 모델은 잘못 정의되어 있으며, 구현마다 다르며, 릴리즈 마다, 프로세서마다 다르다는 것이 문제다.
이 아이템을 작성한 후부터 20년간 자바의 소프트웨어 스택의 모든 컴포넌트의 복잡성은 증가했다.
프로세서에서 VM으로, 라이브러리로 실행 환경이 넓어졌다.
2001년 이후로 자바 프로그램의 성능을 예측하는 것이 힘들어졌다는 것이다.
요약하자면, 빠른 프로그램을 작성하려고 하지마라. 다만, 좋은 프로그램을 작성하려고 하라.
속도는 알아서 따라올 것이다.
이것에 예외가 있다면 wire-level 프로토콜이나 영속성 데이터 모델을 작성할 때는 성능과 설계를 모두 고려해야 한다.
시스템을 설계하는 것이 완료되었다면, 성능을 고려하라.
- 속도가 빠르다면, 할일은 끝났다.
- 속도가 느리다면, 프로파일러의 도움을 얻어라. 가장 먼저 확인해야할 사항은 알고리즘 선택에 대해 검사하는 것이다.