java-squid/effective-java

[아이템 67] 최적화는 신중히 하라

Closed this issue · 8 comments

[아이템 67] 최적화는 신중히 하라

프로파일러에 대한 내용이 나와서 제가 추천하는 도서는 이상민 개발자님의 자바 성능 튜닝 이야기입니다.
조금 더 최신의 내용을 알고 싶다 -> 네이버 개발 블로그에서 이상민을 검색하면 자바 튜닝, 측정도구, 최적화에 대한 내용이 있습니다.
https://d2.naver.com/search?keyword=%EC%9D%B4%EC%83%81%EB%AF%BC
이 내용은 네이버를 만든 기술 에서도 나옵니다. 코드스쿼드에 있는데 오프라인은 막아놓은 상태라 슬프네요. 또 하필 절판이라서 더 슬픔.

제가 자바 성능 튜닝 이야기, 네이버를 만든 기술, 이펙티브 자바의 아이템 67을 보면서 공통점은

가능하면 건드리지 마라. 건드릴생각이면 무조건 측정하고 측정 데이터의 근거로 건드리자.

였습니다.

프로파일러에 대한 내용이 나와서 제가 추천하는 도서는 이상민 개발자님의 자바 성능 튜닝 이야기입니다.
조금 더 최신의 내용을 알고 싶다 -> 네이버 개발 블로그에서 이상민을 검색하면 자바 튜닝, 측정도구, 최적화에 대한 내용이 있습니다.
https://d2.naver.com/search?keyword=%EC%9D%B4%EC%83%81%EB%AF%BC
이 내용은 네이버를 만든 기술 에서도 나옵니다. 코드스쿼드에 있는데 오프라인은 막아놓은 상태라 슬프네요. 또 하필 절판이라서 더 슬픔.

좋은 글 감사합니다. 아쉽게도 BTrace 링크는 막힌것 같은데 다른 자바 성능 측정도구를 이용해서 해봐야겠네요.

이번 본문에서 전 아이템에서 나왔던 방어적 복사에 대한 내용이 나왔는데, 방어적 복사도 객체를 생성하는 비용이 드니까, 성능 측정에 영향을 줄 수 있으니 그런 부분이 많아 지지 않도록 최대한 설계 과정에서 고려되어야 한다는 것도 깨닫게 된것 같네요.. 근데 궁금한 것은 방어적 복사 코드로 인해성능에 문제가 일어난다면, 어떤 방식으로 줄일 수 있을지 궁금합니다

이번 본문에서 전 아이템에서 나왔던 방어적 복사에 대한 내용이 나왔는데, 방어적 복사도 객체를 생성하는 비용이 드니까, 성능 측정에 영향을 줄 수 있으니 그런 부분이 많아 지지 않도록 최대한 설계 과정에서 고려되어야 한다는 것도 깨닫게 된것 같네요.. 근데 궁금한 것은 방어적 복사 코드로 인해성능에 문제가 일어난다면, 어떤 방식으로 줄일 수 있을지 궁금합니다

p378쪽에 하단에 이에 대한 설명이 나오는 듯 해요.

  1. 해당 인스턴스를 반환할 때 불변으로 만들어서 반환하거나 (이 부분이 어떻게 성능을 최적화할 수 있을지 아직 잘 모르겠네요)
  2. Dimension 객체의 기본 타입 값을 따로 반환하거나.
    2번 같은 경우, 인스턴스를 반환하는 것이 아니라 기본 타입 값을 반환함으로 성능상 문제를 줄일 수 있다고 이해했습니다.

https://www.notion.so/277e98c2afdc4ecfb7f123e53d800538

스터디간 간단하게 발표할 내용 정리해 보았습니다.
사실 최적화에 관한 부분은 경험이 없어서 다른 포스트를 읽거나 책의 내용을 정리하는데 중점을 뒀네요.

@tmdgusya

방어적 복사 코드로 인해성능에 문제가 일어난다면, 어떤 방식으로 줄일 수 있을지 궁금합니다

[아이템 17] 변경 가능성을 최소화하라[아이템 50] 적시에 방어적 복사본을 만들라와 같이 연결해서 생각해보면 좋을 거 같습니다. 만약에 객체가 처음부터 불변객체였다면 (예를 들어 java.time.Instant) 객체를 복사해야할 필요 자체를 원천적으로 차단할 수 있었겠지요. 한이 말한 것처럼 객체의 기본 타입 값을 따로 반환하는 것도 한 가지 방법이고요.

객체가 근본적으로 가변성을 가지고 있는 경우에는 두 가지 전략의 트레이드오프에 대해서 생각해볼 수 있을 거 같습니다.

  1. 객체를 불변객체를 만들고 변할 때마다 변화를 적용한 새로운 불변객체를 만든다.
  2. 객체의 가변객체로 만들고 내부적으로는 자유롭게 변경하되 퍼블릭 API를 통한 접근에는 방어적 복사본을 만들어주어 반환한다.

이 객체에 대한 변화가 더 자주 일어나느냐, 아니면 퍼블릭 API를 통한 접근이 더 많이 일어나느냐에 따라 시나리오에 맞게 전략을 선택할 수 있을 거 같습니다.

저는 개인적으로 예전에는 1번 전략이 너무 비효율적인 거 아닌가 라고 생각을 했었는데 가변객체를 사용하게 되는 경우에도 방어적 복사본을 만들어야 하기 때문에 (결국 두 가지 전략 모두 객체의 복사는 일어나죠) 1번 전략도 합리적으로 보여집니다. 또 2번 전략을 취했을 경우에 퍼블릭 API가 아니라 내부적으로 사용하는 경우에도 스스로, 또 사내 팀원들이 실수를 할 수도 있고 또 함수형 프로그래밍 / 분산 컴퓨팅 등의 환경에서도 불변객체가 유리하기 때문에 대부분의 경우 1번 전략을 선택하는 것이 맞다고 느껴집니다.

하지만 트레이드오프에 대해서 생각을 해봤을 때:

  1. 내부적으로만 사용하는 private 객체이고
  2. 이 객체에 대한 변경이 자주 일어나며
  3. 이 변경이 performance bottleneck이다

라는 시나리오라면 필요에 따라 방어적 복사본도 만들지 않는 극단적(?)인 선택도 합리적일 수 있겠다고 생각합니다.