버퍼의 클래스를 정의하십시오. 각 페이지 크기의 몇 배인 큰 버퍼 공간과 전달/종료 인덱스, 전달 된 스트림에서 버퍼를 읽는 메소드 및 다른 * 버퍼 인스턴스를 매개 변수로 사용하는 'lineParse'메소드를 제공하십시오.
일부 버퍼를 만들고 생성자 - 소비자 풀 대기열에 저장합니다. 파일을 열고 풀에서 버퍼를 가져오고 처음부터 끝까지 버퍼 공간을 읽습니다 (오류/EOF에 대한 부울 반환). 풀에서 다른 * 버퍼를 가져 와서 이전 버퍼의 lineparse()에 전달합니다. 거기에서, 데이터의 끝에서 뒤로 검색하여 newLine을 찾습니다. 발견되면 마지막 인덱스를 다시로드하고 마지막 라인의 조각을 memcpy (새로운 행이있을 경우 때때로 운이 좋을 수도 있습니다 :), 전달 된 새 버퍼에 넣고 시작 인덱스를 설정합니다. 첫 번째 버퍼는 이제 전체 라인을 가지며 라인을 처리 할 스레드/s에 큐에 넣을 수 있습니다. 두 번째 버퍼는 첫 번째부터 복사 된 라인 조각을 가지고 있으며 더 많은 데이터를 디스크의 시작 인덱스에서 버퍼 공간으로 읽을 수 있습니다.
줄 처리 스레드는 'used'버퍼를 다시 풀로 재활용 할 수 있습니다.
EOF까지 계속 진행하십시오 (또는 오류 :).
가능한 경우 버퍼 처리를 수행하는 버퍼 클래스에 메서드를 추가하십시오.
큰 버퍼 클래스를 사용하고 끝에서 파싱하는 것은 작은 비트를 계속해서 읽는 것보다 효율적입니다. 처음부터 줄 바꿈을 찾습니다. 스레드 간 통신이 느리고 전달할 수있는 버퍼가 클수록 좋습니다.
버퍼 풀을 사용하면 지속적으로 새로운/삭제를 제거하고 흐름 제어를 제공합니다. 디스크 읽기 스레드가 처리보다 빠르면 풀이 비워지고 일부 사용 된 버퍼가 재활용 될 때까지 디스크 읽기 스레드가 블록을 차단합니다 . 이것은 메모리 폭주를 방지합니다.
처리 스레드를 두 개 이상 사용하는 경우 버퍼가 순서없이 처리 될 수 있습니다. 이는 문제가 될 수도 있고 아닐 수도 있습니다.
디스크 읽기 대기 시간과 병행하여 처리되는 라인의 이점이 스레드 간 통신의 오버 헤드보다 큰지 확인하여 스레드간에 작은 버퍼를 통신 할 경우에만 이점을 얻을 수 있습니다. 생산적인.
전반적으로 빠르지 만 대기 시간이 긴 네트워크 디스크의 경우 가장 빠른 속도 향상을 경험할 수 있습니다.
이런 종류의 구성표는 의도 한대로 작동하지 않습니다. 여러 개의 코어를 가진 프로세서가있어 여러 스레드의 생산성을 높이는 좋은 방법입니다. 하지만 여전히 디스크는 하나 뿐이며 스레드는 디스크를 읽는 것을 기다리고 있습니다. –
@HansPassant : OP가 해당 작업이 CPU 바운드임을 알고있는 경우 해당되지 않을 수 있습니다. 그러나 그렇습니다, 당신은 틀림없이 정확하다. 'pbzip'과'xz' 둘 다 블록 레벨에서이 기술을 사용하지만 큰 효과가 있습니다. – Omnifarious
사실 나는 그것에 대해 생각하지 않았습니다. 나는 내가 제기 한 질문을 사용하는 것을 포함하지 않는 나의 거시적 인 문제를 해결하는 더 깨끗한 방법을 생각 해왔다. 나는 아직도 대답이 무엇인지 궁금하다. – Ken