itsource

ByteBuffer.allocate()와ByteBuffer.allocateDirect()

mycopycode 2022. 8. 28. 09:55
반응형

ByteBuffer.allocate()와ByteBuffer.allocateDirect()

로 으로.allocate() 「」로allocateDirect()그게 질문입니다.

년 나는 그 .DirectByteBuffer으로, Get/Put보다합니다.HeapByteBuffer까지 이 에 대한 데 . 나는 지금까지 그 상황에 대한 정확한 세부사항을 찾는 것에 관심이 없었다. 중 이 있는지 .ByteBuffer아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 맞다.

Ron Hatches는 그의 훌륭한 책 Java NIO에서 당신의 질문에 대한 좋은 답변이 될 수 있을 것으로 생각되는 것을 제안하고 있는 것 같습니다.

운영체제는 메모리 영역에서 I/O 작업을 수행합니다.운영체제에 관한 한 이들 메모리 영역은 연속된 바이트 시퀀스입니다.따라서 I/O 작업에 참여할 수 있는 것은 바이트 버퍼뿐입니다.또, operating system이 데이터의 전송을 위해서 프로세스의 주소 공간(이 경우는 JVM 프로세스)에 직접 액세스 하는 것에 주의해 주세요.즉, I/O 허가 대상이 되는 메모리 영역은 연속된 바이트 시퀀스여야 합니다.JVM에서는 바이트 배열이 메모리에 연속적으로 저장되지 않거나 가비지 컬렉터가 언제든지 이동할 수 있습니다.어레이는 Java의 개체이며, 해당 개체 내에 데이터를 저장하는 방법은 JVM 구현마다 다를 수 있습니다.

이 때문에 다이렉트버퍼의 개념이 도입되었습니다.직접 버퍼는 채널 및 네이티브 I/O 루틴과의 상호작용을 목적으로 합니다.이들은 네이티브 코드를 사용하여 운영체제에 메모리 영역을 직접 비우거나 채우도록 지시함으로써 채널이 직접 또는 원시 액세스에 사용할 수 있는 메모리 영역에 바이트 요소를 저장하기 위해 최선의 노력을 기울입니다.

일반적으로 직접 바이트 버퍼는 I/O 작업에 가장 적합합니다.설계상 JVM에서 사용할 수 있는 가장 효율적인 I/O 메커니즘을 지원합니다.비직접 바이트버퍼는 채널에 전달할 수 있지만 그렇게 하면 성능 저하가 발생할 수 있습니다.일반적으로 비직접 버퍼는 네이티브 I/O 작업의 대상이 될 수 없습니다.비다이렉트 ByteBuffer 객체를 쓰기 위해 채널에 전달하면 채널은 각 콜에 대해 암묵적으로 다음 작업을 수행할 수 있습니다.

  1. 임시 직접 ByteBuffer 개체를 만듭니다.
  2. 비직접 버퍼의 내용을 임시 버퍼에 복사합니다.
  3. 임시 버퍼를 사용하여 낮은 수준의 I/O 작업을 수행합니다.
  4. 임시 버퍼 개체가 범위를 벗어나 가비지가 수집됩니다.

이로 인해 모든 I/O에서 버퍼 복사 및 객체 전환이 발생할 수 있습니다. 이는 바로 우리가 피하고자 하는 것입니다.다만, 실장에 따라서는, 상황이 이 정도로 나쁜 것은 아닐 수도 있습니다.런타임은 직접 버퍼를 캐시하여 재사용하거나 다른 교묘한 묘기를 수행하여 throughput을 향상시킵니다.단순히 일회용으로 버퍼를 작성하는 경우 차이는 크지 않습니다.한편 고성능 시나리오에서 버퍼를 반복적으로 사용하는 경우에는 직접 버퍼를 할당하여 재사용하는 것이 좋습니다.

직접 버퍼는 I/O에 최적이지만 직접 바이트 버퍼가 아닌 경우보다 작성 비용이 더 많이 들 수 있습니다.다이렉트 버퍼에 의해 사용되는 메모리는 표준 JVM 힙을 바이패스하여 네이티브 운영체제 고유의 코드를 호출함으로써 할당됩니다.호스트 운영 체제 및 JVM 구현에 따라 직접 버퍼를 설정 및 해체하는 데 힙 상주 버퍼보다 훨씬 많은 비용이 소요될 수 있습니다.직접 버퍼의 메모리 스토리지 영역은 표준 JVM 힙 외부에 있으므로 가비지 수집의 대상이 되지 않습니다.

직접 버퍼와 비직접 버퍼의 성능 단점은 JVM, 운영 체제 및 코드 설계에 따라 크게 다를 수 있습니다.힙 외부에 메모리를 할당하면 애플리케이션에 JVM이 인식하지 못하는 추가 힘이 적용될 수 있습니다.추가 가동 부품을 사용할 때는 원하는 효과를 얻을 수 있는지 확인하십시오.저는 오래된 소프트웨어 격언을 추천합니다.처음에는 동작하게 하고, 그 다음에는 빠르게 하는 것입니다.사전에 최적화에 대해 너무 걱정하지 말고 우선 정확성에 집중하십시오.JVM을 구현하면 불필요한 작업 없이 필요한 성능을 제공하는 버퍼 캐싱 또는 기타 최적화를 수행할 수 있습니다.

jvm 내에서 직접 버퍼가 더 빠를 것으로 예상할 필요는 없습니다.그 장점은 네이티브 코드, 예를 들어 모든 종류의 채널 뒤에 있는 코드 등에 전달하면 나타납니다.

DirectByteBuffer는 OS 수준에서 직접 메모리 매핑이기 때문에

그들은 아니에요.이들은 일반적인 애플리케이션 프로세스 메모리일 뿐이지만 Java GC에서는 재배치 대상이 되지 않기 때문에 JNI 레이어 내의 작업이 상당히 단순해집니다.설명하신 내용은MappedByteBuffer.

get/put 호출을 통해 더 빠른 성능을 얻을 수 있습니다.

결론은 전제에서 나오는 것이 아니다; 전제는 거짓이다; 그리고 결론 또한 거짓이다.JNI 레이어 내에 들어가 같은 레이어에서 읽고 쓰는 경우 속도가 빨라집니다.DirectByteBuffer데이터가 JNI 경계를 넘을 필요가 없기 때문에 훨씬 더 빠릅니다.

직접 측정하는 것이 가장 좋습니다.빠른 답변은 다음에서 보내는 것 같습니다.allocateDirect()버퍼에 걸리는 시간은 25~75%로 단축됩니다.allocate()variant(파일을 /dev/variate에 복사하는 것으로 간주됩니다)는 크기에 따라 다르지만 할당 자체가 상당히 느려질 수 있습니다(배율 100배).

출처:

언급URL : https://stackoverflow.com/questions/5670862/bytebuffer-allocate-vs-bytebuffer-allocatedirect

반응형