2012-06-19 3 views
8

매우 큰 CSV 파일 (1GB 이상)이 있습니다.이 파일에는 100,000 개의 행이 있습니다.CSV 파일을 여러 청크로 분할하고 Java 코드에서 해당 청크를 병렬로 읽는 방법

보내려는 HTTP 요청의 본문을 만들기 위해 CSV 파일의 각 행을 구문 분석하는 Java 프로그램을 작성해야합니다.

즉, CSV 파일의 줄에 해당하는 100,000 개의 HTTP 요청을 보내야합니다. 단일 스레드에서 이러한 작업을 수행하면 시간이 오래 걸립니다.

i) CSV 파일에서 한 줄을 읽고, ii) 본문에 읽는 내용이 들어있는 HTTP 요청을 만들고, iii) HTTP 요청을 보내고 응답을 받기 위해 1,000 개의 스레드를 만들고 싶습니다.

이렇게하면 CSV 파일을 1,000 개의 청크로 분할해야하며 청크마다 서로 겹치는 선이 없어야합니다.

그런 분할 절차에 가장 좋은 방법은 무엇입니까?

+1

* 저는 매우 큰 CSV 파일 (1GB +)을 가지고 있습니다. 요즘 컴퓨터는 100,000 라인 *입니다. 모든 CPU를 포화 상태로 만들 수 있다면 CPU보다 스레드 수가 훨씬 많습니다. 결국 그것은 IO departement에 묶여 있으며 서버에 동시 요청 수를 보내면 의도적으로 DoS를 시도하지 않으면 현명하지 않습니다. – bestsss

답변

7

여러 위치에서 하나의 파일을 동시에 읽는다면 더 빨리 진행할 수는 없지만 속도가 느려질 수 있습니다 당신은 상당히 아래로).

여러 스레드에서 파일을 읽는 대신 단일 스레드에서 파일을 읽고이 줄의 처리 을 병렬 처리하십시오. 단일 스레드는 CSV를 한 줄씩 읽어야하며 각 줄을 대기열에 넣어야합니다. 다중 작업 스레드는 큐에서 다음 줄을 가져 와서 구문 분석하고 요청으로 변환하며 필요에 따라 요청을 동시에 처리해야합니다. 그런 다음 작업의 분할은 단일 스레드로 수행되어 누락 된 선이나 겹침이 없는지 확인합니다. 단일 스레드에서

+0

분할 작업을 수행하여 파일을 읽기 전에 동일한 크기의 여러 청크로 분할 할 수 있습니까? 그렇다면 파일을 쪼갠 후에 여러 스레드를 쳐다 보면서 병렬로 청크를 읽으면 단일 스레드가 전체 파일을 읽는 것보다 빠를까요? – JuliaLi

+0

@JuliaLi 아니요, 실제로는 아닙니다. 대용량 파일은 디스크에서 서로 가깝게 위치하는 여러 블록을 차지하는 경우가 많습니다.자기 헤드의 위치를 ​​다시 지정할 필요가 없기 때문에 디스크가 연속 블록을 액세스하는 데 훨씬 더 빠르기 때문에 디스크에서 큰 파일을 읽는 것이 연속적으로 수행 될 때 훨씬 빠르게 진행됩니다. – dasblinkenlight

4

CSV의 행을 읽고 읽은 행의 목록을 작성하는 스레드를 가질 수 있습니다. 이것이 소정의 한계에 도달하면. 100 줄을 고정 크기 스레드 풀에 전달하여 요청으로 보냅니다.

서버에 1000 개의 코어가 없으면 10-100 개의 동시 요청을 사용하는 것이 더 빠를 것이라고 생각됩니다.

+0

HTTP 응답을받는 데 걸리는 시간에 따라 다릅니다. 관련된 서버가 느린 경우 대부분의 스레드가 I/O를 기다리고 있습니다. – biziclop

+0

네트워크 또는 서버가 느린 경우 더 큰 배치 크기 또는 더 작은 요청을 사용하면로드 시간을 향상시킬 수 있습니다. 그것을 테스트하지 않고 무엇이 최적인지 말해주는 것은 불가능합니다. 내 요점은; 더 많은 스레드가 더 좋다고 가정하지 마십시오. –

+1

그것이 내가 의미했던 것입니다. 응용 프로그램이 I/O 바인딩 일 가능성이 높으므로 코어 수를 기반으로하는 고정 수식이 작동하지 않으므로 가장 잘 작동하는 것으로 실험해야합니다. (또는 적응 형 시스템을 쓰면 복잡해집니다.) – biziclop

1

하나의 스레드가 파일을 한 줄씩 읽고 읽는 모든 행에 대해 ExecutorService에 작업을 게시하여 각각에 대해 HTTP 요청을 수행하도록하십시오.

n 번째 줄을 읽으려면 여러 스레드에서 파일을 읽는 것이 효과가 없습니다. 먼저 다른 모든 파일을 읽어야합니다. 파일에 고정 폭 레코드가 포함되어 있지만 이론상 작동 할 수 있지만 CSV는 고정 폭 형식이 아닙니다.

+0

열을 알고있을 때 행의 끝을 추측 할 수 있지만 행할 수 있지만 노력할 가치는 거의 없습니다. 다중 디스크 배열과 매핑 된 파일이 여러 개있는 경우 (읽기 부분 용) – bestsss

+0

분할 작업을 수행하여 파일을 읽기 전에 동일한 크기의 여러 청크로 분할 할 수 있습니까? 그렇다면 파일이 스 플리트 된 후에 다중 스레드를 시작하여 병렬로 청크를 읽습니다. – JuliaLi

2

읽기 CSV 파일 당신은 당신의 Runnable Task의 목적을 구성하여 선 대표에게 풀에서 사용할 수있는 Thread 중 하나에이 줄을 얻고로 비동기 적으로 실행 것, Executors'ssubmit()에 합격 한 후. 여기

public static void main(String[] args) throws IOException { 

     String fName = "C:\\Amit\\abc.csv"; 
     String thisLine; 
     FileInputStream fis = new FileInputStream(fName); 
     DataInputStream myInput = new DataInputStream(fis); 
     ExecutorService pool=Executors.newFixedThreadPool(1000); 
     int count = 0; // Concurrent request to Server barrier 

     while ((thisLine = myInput.readLine()) != null) { 
      if (count > 150) { 
       try { 
        Thread.sleep(100); 
        count = 0; 
       } catch (InterruptedException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } 
      } 

      pool.submit(new MyTask(thisLine)); 
      count++; 
     } 

    } 
} 

당신의 작업 :

class MyTask implements Runnable { 
     private String lLine; 
     public MyTask(String line) { 
      this.lLine=line; 

     } 

     public void run() { 
      // 1) Create Request lLine 
      // 2) send the HTTP request out and receive response 
     } 
} 
0

자바 8, 이번 달에 출시 될 예정이다, 병렬 스트림 및 람다 통해 지원 을 개선합니다. 오라클의 tutorial 동시 스트림에서 스트림이 좋은 시작점 일 수 있습니다.

여기의 함정은 너무 많은 병렬성입니다.URL을 검색하는 예는 적은 수의 병렬 호출을 갖는 것이 좋습니다. 너무 많은 병렬 처리는 연결하는 대역폭과 웹 사이트뿐만 아니라 Java가 실행되는 대부분의 환경에서 엄격하게 제한된 리소스 인 파일 설명자가 부족할 위험에 처하게됩니다.

넷플 릭스 'RxJavaAkka은 당신을 도울 수있는 일부 프레임 워크입니다. 이러한 프레임 워크는 사소한 것이 아니며 배우려는 노력이 필요할 것입니다.

관련 문제