2009-06-21 3 views
8

많은 I/O를 수행해야하는 매우 빠른 Java 코드를 작성하려고했습니다. I는 ByteBuffer를 반환하는 메모리 맵 파일을 사용하고 :Java에서 메모리 맵핑 된 파일

public static ByteBuffer byteBufferForFile(String fname){ 
    FileChannel vectorChannel; 
    ByteBuffer vector; 
    try { 
     vectorChannel = new FileInputStream(fname).getChannel(); 
    } catch (FileNotFoundException e1) { 
     e1.printStackTrace(); 
     return null; 
    } 
    try { 
     vector = vectorChannel.map(MapMode.READ_ONLY,0,vectorChannel.size()); 
    } catch (IOException e) { 
     e.printStackTrace(); 
     return null; 
    } 
    return vector; 
} 

제가하는 데 문제는 (바이트 [] 배열을 반환한다)에의 ByteBuffer .array() 메소드가 작동하지 않는다는 것이다 읽기 전용 파일의 경우. 내 코드를 작성하여 메모리에 구성된 메모리 버퍼와 디스크에서 읽은 버퍼 모두에서 작동합니다. 하지만 ByteBuffer.wrap() 함수는 모든 버퍼를 감싸고 싶지 않습니다. 그래서 저는 두 가지 버전의 모든 것을 작성했습니다. 하나는 byte []를 사용하고, 다른 하나는 ByteBuffer를 사용합니다.

모든 것을 포장해야합니까? 아니면 모든 것을 이중으로 써야합니까?

+3

벤치마킹하여 결과를 게시하십시오. 전문가가 한 방향으로 당신을 지시 할 수 있다고하더라도 방향이 귀하의 상황에 맞지 않을 수도 있습니다. 기준!!!! – basszero

답변

10

아무도 실제로 ByteBuffers이 처음으로 .array()을 호출하는 메모리 매핑 지원으로 생성되었는지 확인 했습니까? readonly/readwrite에 관계없이?

내가 말할 수있는 한 내 대답은 입니다.입니다. 직접 byte[] 배열을 ByteBuffer.array() 통해 반환 할 수있는 ByteBuffer의 능력은 ByteBuffer.hb (byte[])의 존재에 의해 결정되며 MappedByteBuffer이 생성 될 때 항상 null로 설정됩니다.

필자는 질문 작성자가 원했던 것과 비슷한 일을하기를 원했기 때문에 나를 괴롭혔다.

+0

동의합니다. 그것은 빤다. 나는 ByteBuffer가 array()를 구현하지 않는다고 믿을 수 없다. 반면에 우리는 약간의 성능 테스트를 수행했으며, 프로그램 된 -io를 사용하는 것보다 메모리 매핑 된 파일을 사용하는 것이 더 빠르다는 것을 알았습니다. 때때로 프로그램 된 -io를 사용하는 것이 더 빠릅니다. 그것은 매우 이상합니다. 그러나 프로그램 매핑에는 메모리 매핑 파일보다 많은 차이가 있습니다. – vy32

+3

'byte [] '가 힙에 있어야합니다. 메모리 매핑 된 메모리 블록은 힙 외부에 있어야합니다. 구별이 투명하면 좋지만 어쨌든 ByteBuffer의 getLong/putLong 메소드를 사용하는 편이 더 좋습니다 (기본 네비게이션을 사용하면 훨씬 빠릅니다) –

1

ByteBuffer.wrap() 기능을 사용하더라도 높은 부담을주지 않습니다. 그것은 간단한 객체를 할당하고 몇 개의 정수를 초기화합니다. 따라서 ByteBuffer에 대한 알고리즘을 작성하는 것이 읽기 전용 파일로 작업해야하는 경우 가장 좋습니다.

4

바이트를 감싸는 것이 느려지지는 않을 것입니다 ... 커다란 배열 복사본이나 기타 작은 성능 악조건은 없을 것입니다. JavaDocs에서 : java.nio.ByteBuffer .wrap()

바이트 배열을 버퍼로 랩핑합니다.

새로운 버퍼가 지정된 바이트 배열 뒷받침한다; 즉, 버퍼를 수정하면 배열이 수정되고 이됩니다 새 버퍼의 용량과 제한은 array.length가되고 위치는 0이되고 해당 표시는 이 정의되지 않습니다. 그 배킹 배열 은 지정된 배열이되고 배열 오프셋은 0이됩니다.

+0

감사합니다. 나는 .get (i)가 메소드 호출을 포함하고 [i]는 바이트 코드에서 수행되기 때문에 [i] 대신에 .get (i)로 모든 바이트를 읽어야한다는 것에 관심이있다. – vy32

+4

그건 성능이 아주 좋지 않은 것 같아서 조기 최적화와 같은 냄새가 난다. JVM은 이와 같은 것들에 좋은 점이있다. 벤치마킹을 통해 어느 방향 으로든 자신을 증명할 수 있습니다. –

+0

사실 저는 수 테라 바이트의 정보를 처리하는 컴퓨터 법의학을하고 있습니다. 지금까지의 경험에서 JVM은 내가 원하는만큼 최적화하지 않았습니다. – vy32

5

그것의 항상 좋은 바퀴를 재발견 할 수 없습니다. Apache는 I/O 작업 수행을위한 멋진 라이브러리를 제공합니다. 여기가 지원하는 시나리오입니다 http://commons.apache.org/io/description.html

를 살펴 보자. 이 약간의 데이터를 가지고 있다고 가정하면, 얼마나 많은 데이터가 남아 있는지 미리 알 수 없습니다. . 너무 많이가 있다면, 당신은 디스크 대신 잡아 먹는 메모리에 기록하기를 원하지만 당신은 당신이 때까지 디스크에 기록하지 않으 에 대한 필요성을, 디스크가 느리고 정리에 대한 추적을 필요로하는 자원이기 때문이다.

그래서 임시 버퍼를 만들고 그 버퍼에 쓰기 시작합니다. 이 메모리에 보관하려는 임계 값에 도달하면 파일을 만들고 버퍼에있는 내용을 해당 파일에 쓰고 버퍼 대신 모든 파일 을 파일에 쓸 필요가 있습니다 .

그건 뭐니? DeferredOutputStream입니다. 스위치 오버 할 때마다 주위의 모든 엉망을 숨 깁니다. 처음에 지연된 스트림을 만들고 임계 값을 구성한 다음 콘텐츠를 작성하면됩니다.

편집 : 난 그냥 구글을 사용하여 작은 재 검색을했고,이 링크를 발견 http://lists.apple.com/archives/java-dev/2004/Apr/msg00086.html (번개 빠른 파일 읽기/쓰기). 매우 인상적.

+0

내가 잘못하면 나를 수정하십시오. 빠른 I/O 작업 방법을 찾고 있습니다. 옳은?? –

+0

사실 저는 빠른 방법을 찾고 있습니다 만, 최소한의 버퍼 복사본으로 버퍼를 처리하는 방법을 찾고 있습니다. – vy32

+0

@GauravSaini : Apache commons-io에서'DeferredOutputStream'을 참조합니까? Javadoc에서 v2.3 및 v2.2의 클래스를 찾을 수 없습니다. –