2011-12-16 1 views
0

파일 본문에서 특정 패턴을 찾으려면 디스크의 파일 트리를 통과해야하는 간단한 Java 응용 프로그램을 고려하십시오.파일에서 텍스트 패턴을 찾는 다중 스레드 접근 방식

멀티 스레딩을 사용하면 더 나은 성능을 얻을 수 있습니다. 예를 들어 새 폴더를 찾으면 고정 된 ThreadPool에서 새로운 Runnable을 제출합니다. Runnable 작업은 새 폴더 등을 찾기 위해 폴더를 통과해야합니다. 제 생각에는이 작업은 CPU 바인딩이 아닌 IO 바인딩이어야하며 새 스레드를 생성하면 성능이 향상되지 않습니다.

하드 드라이브 유형에 따라 다릅니 까? (HDD 등 ...) OS 유형에 따라 다릅니 까?

IMHO 유일한 것은 파일 본문에서 패턴을 찾기 위해 파일 내용을 구문 분석하기위한 새 스레드를 생성하는 것입니다.

이 문제를 해결하기위한 일반적인 패턴은 무엇입니까? 다중 스레드 또는 단일 스레드 여야합니까?

+1

이다 적지 물질 (당신이 SSD를 사용하지 않는 경우 즉,), 그래서 여기에 멀티 스레딩을 사용하는 이점은 없습니다. 두 파일의 경우 병렬로 읽으면 OS가 파일 1을 읽은 다음 파일 2를 찾은 다음 파일 2에서 읽은 다음 다시 읽어야합니다. – fge

+0

왜 사용하지 않으시겠습니까?파일 버퍼에서 패턴을 검색하면 꽤 CPU 집약적 인 것처럼 들립니다. 기존의 하드 디스크를 사용하는 시간은 실제로 디스크를 네트워크로 연결하는 경우 더 작은 문제입니다. 하나의 버퍼에 대한 탐색 시간이 다른 버퍼의 패턴을 스캔하는 것과 병행하여 실행되면 합리적인 향상이 될 것입니다. 그것을 내고 무엇이 일어나는가를보십시오! 그것이 더 좋든, 더 나쁠 지 알려주십시오. –

답변

2

테스트 프로젝트에서 작업하는 동안이 분야에 대한 연구를 수행 했으므로 github의 프로젝트를 http://github.com/4ndrew/filesearcher에서 볼 수 있습니다. 물론 주된 문제는 디스크 I/O 속도이지만, 병렬로 읽기/검색을 수행하기 위해 최적의 스레드 수를 사용하면 더 나은 결과를 얻을 수 있습니다.

UPD :는 또한 내가 몇 시간 전에 바로이 질문에 대한 몇 가지 실험을 한이 문서 http://drdobbs.com/parallel/220300055

1

작업이 CPU 또는 IO 바운드인지 확인한 다음 멀티 스레딩의 이점 여부를 결정해야한다고 말한 적이 있습니다. 일반적으로 디스크 작업은 꽤 느리기 때문에 복잡한 데이터를 구문 분석하고 파싱해야만 멀티 스레딩의 이점을 얻지 못할 수 있습니다. 난 그냥 간단한 테스트를 작성 - 단일 스레드에서 파싱 w/o 파일을 읽고, 그것을 측정하고 파싱을 추가하고 훨씬 느린 지 확인한 다음 결정할 수 있습니다.

아마도 좋은 디자인은 파일을 읽고 데이터를 (제한된) 대기열에 놓은 다음 다른 스레드 (또는 더 나은 ExecutorService 사용)가 데이터를 구문 분석하는 두 개의 스레드를 사용하는 것입니다. 걱정하고 항상 파싱을 수행하는 스레드 수를 조정할 수 있습니다. 여러 스레드에서 디스크를 읽는 것이 많은 의미가 있는지 잘 모르겠다. (여러 개의 물리적 디스크 등을 읽을 필요가 없다면).

1

당신이 할 수있는 일은 하나의 스레드가 디스크를 검색하고 파일을 검색 한 다음 소비자 스레드가 처리하는 단일 생산자 다중 소비자 패턴을 구현하는 것입니다.

이 경우 디스크를 스캔하기 위해 여러 스레드를 사용하는 것이 좋지 않을 것입니다. 실제로 디스크가 매번 다음 읽기 위치를 탐색해야하기 때문에 성능이 저하 될 수 있습니다. 디스크 사이의 디스크.

2

봐. 결국 나는 파일에 액세스하는 방식을 변경함으로써 훨씬 더 나은 개선을 달성 할 수 있다고 결론을 내렸다. 여기

내가 결국 사용하여 종료 파일 워커의 : 탐색 시간 ... 그것은 확실히 디스크 종류에 따라 달라집니다

// 4k buffer size ... near-optimal for Windows. 
static final int SIZE = 4 * 1024; 

// Fastest because a FileInputStream has an associated channel. 
private static void ScanDataFile(Hunter h, FileInputStream f) throws FileNotFoundException, IOException { 
    // Use a mapped and buffered stream for best speed. 
    // See: http://nadeausoftware.com/articles/2008/02/java_tip_how_read_files_quickly 
    FileChannel ch = f.getChannel(); 
    // How much I've read. 
    long red = 0L; 
    do { 
    // How much to read this time around. 
    long read = Math.min(Integer.MAX_VALUE, ch.size() - red); 
    // Map a byte buffer to the file. 
    MappedByteBuffer mb = ch.map(FileChannel.MapMode.READ_ONLY, red, read); 
    // How much to get. 
    int nGet; 
    // Walk the buffer to the end or until the hunter has finished. 
    while (mb.hasRemaining() && h.ok()) { 
     // Get a max of 4k. 
     nGet = Math.min(mb.remaining(), SIZE); 
     // Get that much. 
     mb.get(buffer, 0, nGet); 
     // Offer each byte to the hunter. 
     for (int i = 0; i < nGet && h.ok(); i++) { 
     h.check(buffer[i]); 
     } 
    } 
    // Keep track of how far we've got. 
    red += read; 
    // Stop at the end of the file. 
    } while (red < ch.size() && h.ok()); 
    // Finish off. 
    h.close(); 
    ch.close(); 
    f.close(); 
} 
관련 문제