객체 풀링은 더 이상 사용되지 않는 기술입니까?


62

나는 객체 풀링의 개념에 매우 익숙하며 항상 가능한 한 많이 사용하려고합니다.

또한 Java 자체뿐만 아니라 다른 프레임 워크에서도 가능한 한 많이 풀링을 사용하는 것을 관찰 한 것처럼 객체 풀링이 표준 표준이라고 생각했습니다.

최근에 나는 완전히 새로운 (그리고 반 직관적 인) 것을 읽었지만.

이러한 풀링은 실제로 동시 응용 프로그램에서 실제로 프로그램 성능을 저하 new시키며, 새로운 JVM에서는 객체의 인스턴스화가 실제로 빠르기 때문에 대신 객체 를 인스턴스화하는 것이 좋습니다 .

나는 책에서 이것을 읽었다. Java Concurrency in Practice

이제 나는 책의 첫 부분이 새로운 인스턴스를 만드는 대신 Executors재사용 을 사용 하도록 권고 한 이래로 여기에서 무언가를 이해하지 못하고 있다고 생각하기 시작했습니다 Thread.

요즘 객체 풀링은 더 이상 사용되지 않습니까?

답변:


72

현대의 JVM에서는 수명이 짧은 객체 (예 : 메모리 할당 및 GC)의 생성 및 제거가 매우 저렴하기 때문에 일반적인 기술로 사용되지 않습니다. 따라서 일반 객체보다 손으로 쓴 객체 풀을 사용하면 속도가 느리고 복잡하고 오류가 발생하기 쉽습니다 new. *

그럼에도 불구하고 DB / 네트워크 연결, 스레드 등과 같이 생성 비용이 비교적 비싼 특수 객체에 대해서는 여전히 사용됩니다.

* 크롤링 Java 앱의 성능을 향상시켜야했습니다. 조사 결과 수백만 개의 객체를 할당하기 위해 객체 풀을 사용하려는 시도가 발견되었으며,이를 작성한 영리한 사람이 단일 전역 잠금을 사용하여 스레드를 안전하게 만들었습니다. 풀을 일반 new으로 교체하면 앱이 30 배 빨라졌습니다.


1
그렇다면 객체의 인스턴스화가 너무 비싼 지 어떻게 결정할 수 있습니까?
user10326

3
객체가 운영 시스템 자원 (스레드, I / O, 공유 메모리 등) 소모하는 경우
케빈 클라인

13
@ user10326, 측정 기준 :-) 객체를 만드는 데 시간이 오래 걸리거나 잠재적으로 제한된 비 메모리 리소스와 관련이있는 경우 풀링을 고려할 수 있습니다.
Péter Török

8
@ user10326, 95 %가 넘는 IMO의 경우 위의 기준을 통해 개체 풀이 필요한지 여부를 미리 쉽게 결정할 수 있습니다. 또한 풀이 필요한 거의 모든 경우에 기존 라이브러리 / 프레임 워크를 사용하는 경우가 많습니다. 기존 라이브러리 / 프레임 워크를 사용하는 경우도 있습니다. 여기에는 이미 오브젝트 풀이 이미 구현되어있을 것입니다. 공장은 나중에 어떤 방식 으로든 다시 구현할 수 있습니다.
Péter Török

2
@Peter Torok의 매우 중요한 요점 : 많은 프레임 워크와 라이브러리가 당신을 위해 풀링을 구현합니다. 자신을 구현하기 전에 항상 풀링 된 라이브러리를 사용하고 있지 않은지 확인하십시오.
hromanko

36

구체적인 질문에 대한 대답 : '객체 풀링은 더 이상 사용되지 않는 기술입니까?' 입니다 :

개체 풀링은 스레드 풀링, 데이터베이스 연결 풀링 등 특정 위치에서 널리 사용됩니다.

일반적인 객체 생성은 결코 느린 과정이 아닙니다. 풀링 자체는 리소스와 메모리를 소비합니다. 모든 최적화는 절충입니다.

규칙은 다음과 같습니다.

조기 최적화는 악입니다 !!!

그러나 주어진 최적화는 언제입니까?

조기 최적화는 철저한 프로파일 링을 통해 병목 현상발견 하기 전에 수행 된 모든 최적화 입니다.


2
과연. OP는 "언제나 가능한 한 많이 사용하려고한다"고 말했다. 이것이 문제이다. IMO.
nerdytenor

@Boris, 두 번째 문장에 따르면 프로파일 링을 통해 병목 현상으로 풀 DB 연결 및 스레드를 발견 할 때까지 풀링하지 않아야합니까?
Pacerier

1
일부 프로파일 링 결과는 일정하게 재 측정 :-) 필요가 없습니다 @Pac
데이비드 불락을

9

가비지 수집을 완전히 피하려는 상황에서는 객체 풀링이 유일하게 가능한 대안이라고 생각합니다. 따라서 더 이상 사용되지 않는 기술이 아닙니다.


1
또한 객체가 오래 전 세대에 옮겨 질만큼 오래 살 때마다 GC를 피하는 것이 좋습니다.
Zan Lynx

8

법안

사용 사례, 객체 크기, JVM, JVM 옵션, 활성화 한 GC 및 기타 여러 요인에 따라 달라집니다.

한마디로 : 그것을 전에 측정하고 후에 측정하십시오. Apache와 같은 객체 풀링 프레임 워크를 사용한다고 가정하면 구현간에 교체하기가 너무 힘들지 않아야합니다.

추가 성능 테스트 팁-JVM을 먼저 예열하고 실행중인 JVM에서 테스트를 여러 번 실행하면 다르게 작동 할 수 있습니다.


3
"JVM을 먼저 예열 시키십시오"– "워밍업"을해야 할 유일한 것이 모니터 일 때를 기억합니다. 야, 모든 새로운 것이 다시 낡았다.
kylben

내가 워밍업해야 할 유일한 것은 커피입니다!
환멸

@Marijn, 어떻게 "온난화"하게합니까?
Pacerier

전체 설명 ( openjdk.java.net/projects/code-tools/jmh ) 은 JMH 프레임 워크를 참조하십시오. 그러나 기본적으로 JVM은 코드를 JIT하고 벤치 마크 전에 GC를 실행할 수있는 기회를 제공해야합니다.
Martijn Verburg

8

이러한 풀링은 실제로 동시 응용 프로그램에서 실제로 프로그램 성능을 저하 시키며, 새로운 JVM에서는 객체의 인스턴스화가 실제로 빠르기 때문에 대신 새로운 객체를 인스턴스화하는 것이 좋습니다.

상황에 따라 다릅니다.


1
훌륭한 답변과 아늑함. "24 바이트"클레임은 4 바이트 부동 소수점 (16 바이트)의 4 개 인스턴스와 오브젝트 참조의 경우 4 바이트, 잠금 참조의 경우 4 바이트를 의미한다고 덧붙입니다 (아마도 별표?). 이는 설계에서 제거하는 정확한 오버 헤드입니다.
strickli

5

이 변화하는 추세가 여기에있다하지만 확실히 경우가 될 것 나도 몰라 가 달려있다 . Java 클래스가 RMI 연결 또는 리소스 파일로드와 같은 외부 리소스를 관리하는 경우 객체 인스턴스화 비용이 여전히 높을 수 있습니다 (이러한 리소스가 이미 풀링되어있을 수 있음). 일반적으로이 책에 동의합니다.


이 경우에도 풀링을 정의 할 때 어느 쪽 (이를 읽기 전에) 풀링을 사용해야하는지 설명하기 때문에 1) 풀링을 처리하는 새로운 구조 2) 가져 오기 / 릴리스 객체에 대한 동기화 풀에서 3) 풀 등을 유지 관리하므로 이제는 서버에 연결할 때마다 새 소켓을 여는 대신 소켓을 캐싱하는 것 외에는 유용한 유스 케이스가 없을 것이라고 생각합니다.이 경우 네트워크 때문에 대기 시간이 아닌 인스턴스 생성 오버 헤드
user10326

@ user10326 그렇습니다. 인스턴스화 오버 헤드의 일부로 소켓을 여는 것이 클래스의 작업이며 생성자에서 초기화 해야하는 경우 대기 시간 및 IO 영향이 중요합니다.
제레미
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.