2012-04-09 2 views
6

많은 양의 데이터를 생성하고 쓰기 위해 대기열에 넣는 프로그램이 있습니다. 그러나 문제는 현재 데이터를 생성하는 것보다 빠릅니다 (메모리를 최대로하고 느려지 기 시작합니다). 나중에 파일을 구문 분석 할 계획이므로 순서는 중요하지 않습니다.메모리에서 파일로 대량의 데이터를 쓰는 가장 빠른 방법은 무엇입니까?

나는 약간 주위를 둘러 보았고 현재 프로세스를 설계하는 데 도움이되는 몇 가지 질문을 발견했다. (그러나 여전히 느리다). 여기 내 코드는 지금까지의 : 나는 어쩌면이 잘못된 (아마도 하드웨어 문제 나 EC2를 사용하고 같은)을 평가하지만,있는 매우 빠르게 큐 결과가 덤프 있도록

//...background multi-threaded process keeps building the queue.. 
FileWriter writer = new FileWriter("foo.txt",true); 
     BufferedWriter bufferWritter = new BufferedWriter(writer); 
     while(!queue_of_stuff_to_write.isEmpty()) { 
      String data = solutions.poll().data; 
      bufferWritter.newLine(); 
      bufferWritter.write(data); 
     } 
     bufferWritter.close(); 

내가 프로그래밍에 아주 새로운 해요 내 접근 방식이 괜찮 으면 어떻게 든 그것을 향상시킬 수 있습니까? 순서가 중요하지 않으므로 여러 드라이브의 여러 파일에 쓰기가 더 적합합니까? 스레딩이 더 빨라지는지, 등등. 최선의 접근 방법과 어떤 제안이 좋을지 확신 할 수 없습니다. 내 목표는 대기열의 결과를 저장하는 것입니다 (유감스럽게도/dev/null로 출력하지 않습니다 :-) 내 응용 프로그램에 대한 가능한 한 메모리 사용량을 낮게 유지합니다 (100 % 확신 할 수는 없지만 대기열이 15gig까지 채우므로 15gig + 파일로 가정).

Fastest way to write huge data in text file Java (실현 내가 버퍼 사용해야 작가) Concurrent file write in Java on Windows

+0

CPU 속도> 하드 드라이브 속도를 이해하므로 쓰기가 항상 처리되지 않을 수 있으므로 hd 속도를 처리하는 방법을 알아 내려고 노력하고 있습니다. –

+0

많은 것은 목에 무엇이 있는지에 달려 있습니다. 나는 당신이 최대의 디스크 IO (당신의 질문으로 보입니다)의 대역폭을 최대한 활용한다면 당신은 당신의 계정을 최대한 (비용면에서) 최대화 할 수 있다고 생각합니다. 필자는 멀티 쓰레딩이 많은 도움이되지 않을 것이라고 동의합니다. –

+0

대략적인 계산에 따르면 15GB는 매번 4 달러를 소비하게됩니다. –

답변

2

그 코드를 살펴보면, 마음에 떠오르는 것이 문자 인코딩입니다. 당신은 문자열을 쓰고 있지만 궁극적으로 스트림으로가는 바이트입니다. 후드 아래의 라이터 문자 대 문자 인코딩이며 쓰기 작업을 처리하는 동일한 스레드에서이 작업을 수행합니다. 즉, 쓰기 지연으로 인코딩 시간이 소요될 수 있으며 이로 인해 데이터를 쓰는 속도가 줄어들 수 있습니다.

간단한 변화는 BufferedOutputStream 오히려 BufferedWriter (A)보다를 사용하는 대신 Stringbyte[]의 큐를 사용하는 큐에 밀어 스레드에서 인코딩을 수행하고, IO 코드가하는 것입니다.

인코딩 된 텍스트가 평균 문자 당 2 바이트보다 적게 차지하는 경우 메모리 사용량을 줄일 수도 있습니다. 라틴 텍스트 및 UTF-8 인코딩의 경우 일반적으로 사실입니다.

그러나 IO 하위 시스템이 처리 할 수있는 것보다 빠른 속도로 데이터를 생성 할 가능성이 높습니다.보다 빠른 IO 서브 시스템을 만들 필요가 있습니다 (EC2를 사용하는 경우, 더 빠른 인스턴스를 빌려주거나 다른 백엔드에 쓰는 것, SQS 대 EBS 대 로컬 디스크 등) 또는 ganging 여러 IO 하위 시스템을 어떻게 든 병렬로 함께 사용할 수 있습니다.

0

내가 아니라 당신이 계산에서 데이터를 생산 할 추측 (나 어쩌면 멀티 스레딩 쓰기가 좋은 생각이 아니었다 참조했다) 다른 데이터 소스에서 데이터를로드하지 않으면 쓰기가 데이터를 생성하는 것보다 항상 느려집니다.

여러 파일 (동기화 문제로 인해 같은 파일이 아닌)에 여러 개의 파일로 데이터를 쓸 수는 있지만 여러 개의 스레드에서 데이터를 작성할 수는 있습니다.하지만 문제가 해결되지는 않습니다.

응용 프로그램의 작성 부분이 작업을 마치고 계산을 계속할 때까지 기다릴 수 있습니까?

또 다른 접근법은 다음과 같습니다. 대기열을 비 웁니 까? solutions.poll()이 솔루션 큐를 줄입니까?

0

여러 스레드를 사용하여 다른 파일에 쓰는 것이 좋습니다. 또한 생성자에서 수행 할 수있는 BufferedWriters 버퍼 크기를 설정해야합니다. 10MB 버퍼로 초기화 해보고 도움이되는지 확인하십시오.

+0

그것은 무엇입니까? 두 개의 파일을 동일한 기계식 HDD에 병렬로 쓰는 것은 첫 번째 파일을 쓰는 것보다 시간이 오래 걸릴 것입니다. –

1

예. 여러 드라이브에 여러 파일을 쓰면 도움이됩니다. 다른 드라이브에 동시에 쓰는 것이 없으면 I/O가 더 이상 병목 상태가되지 않을 때까지 성능이 드라이브 수에 따라 선형 적으로 조정됩니다. 성능을 더욱 향상시키기 위해 몇 가지 다른 최적화를 시도 할 수도 있습니다.

거대한 파일을 생성하고 있고 디스크가 계속 올라갈 수없는 경우 GZIPOutputStream을 사용하여 출력을 축소하면 디스크 I/O 양이 줄어 듭니다. 비 임의 텍스트의 경우 일반적으로 최소 2x-10x의 압축 비율을 기대할 수 있습니다. 예를 들어 데이터의 바이너리 인코딩 - 당신이 정기적으로 (즉, 반복) 데이터를 출력하는 경우

//...background multi-threaded process keeps building the queue.. 
    OutputStream out = new FileOutputStream("foo.txt",true); 
    OutputStreamWriter writer = new OutputStreamWriter(new GZIPOutputStream(out)); 
    BufferedWriter bufferWriter = new BufferedWriter(writer); 
    while(!queue_of_stuff_to_write.isEmpty()) { 
     String data = solutions.poll().data; 
     bufferWriter.newLine(); 
     bufferWriter.write(data); 
    } 
    bufferWriter.close(); 

은 또한 다른 출력 형식으로 전환하는 것을 고려할 수 있습니다. 데이터 구조에 따라 데이터베이스에 저장하는 것이 더 효율적일 수 있습니다. XML을 출력하고 XML을 계속 사용하려면 EXI 또는 Fast InfoSet과 같은 Binary XML 형식을 조사해야합니다.

관련 문제