2017-10-17 7 views
0

독자적인 이진 데이터 파일 형식을 읽습니다. 형식은 기본적으로 헤더, 데이터, size_of_previous_data, header, data, size_of_previous_data, header, data, size_of_previous_data, ... 헤더의 일부는 다음 데이터 청크의 바이트 수와 그 직후에 나열된 크기 자료. 헤더는 256 바이트이고, 데이터는 일반적으로 ~ 2MB이고 size_of_previous_data는 32 비트 int입니다.큰 파일의 작은 분리 된 청크 읽기 (C++)

파일의 크기는 일반적으로 ~ GB이며, 원하는 데이터를 찾기 위해 수십 개의 파일을 수시로 검색해야합니다. 이렇게하기 위해서 내가 제일 먼저하는 일은 각 파일의 idex 즉, 헤더를 읽고 관련 데이터 (파일 및 바이트 번호)의 위치를 ​​기록하는 것입니다. 내 코드는 기본적으로 fstream :: read()를 사용하여 헤더를 준비하고, 데이터 크기를 검사하고, fstream :: seekg()를 사용하여 데이터를 건너 뛴 다음 size_of_previous_data를 읽은 다음 파일의 끝에 도달 할 때까지 반복합니다.

제 문제는이 색인 생성이 너무 느리다는 것입니다. 데이터는 내 Windows 10 노트북의 내부 7200rpm 하드 드라이브에 있으며 작업 관리자는 내 하드 드라이브 사용량이 초과되었음을 보여 주지만 응답 속도가 일반적으로> 70ms 인 응답 속도가 약 1.5MB/s에 불과합니다. fstream :: get()을 사용하여 std :: fstream을 사용하여 파일을 읽고 있는데 헤더를 읽고 fstream :: seekg()를 사용하여 다음 헤더로 이동합니다.

나는 내 코드를 프로파일 링했으며 거의 ​​전체 시간이 fstream :: read() 코드에서 size_of_previous_data 값을 읽는 데 소비된다. 나는이 작업을 수행 할 때 바로 다음 데이터가 버퍼링되어 다음 헤더를 가져 오는 fstream :: read()가 실제로 시간이 필요 없다고 추정합니다.

그래서 이것을 최적화하는 방법이 있는지 궁금합니다. 버퍼링 된 모든 읽기의 전체 버퍼가 거의 낭비 될 것입니다 (이 중 97 %가 8kB 버퍼 인 경우). 이 방법을 줄이는 방법이 있을까요? (아마도 기본 OS 버퍼도 변경할 수없는 방식으로 버퍼링 할 수 있습니다.)

+0

처음에는 모든 파일을 읽지 않는 이유는 무엇입니까? GB 크기의 파일 검색 속도가 느리다는 것은 놀라운 일은 아니지만 보통 GBs의 RAM이 적당합니다. – user463035818

+0

데이터의 크기가 이미 헤더에 저장되어있는 경우 데이터를 검색 할 때'size_of_previous_data '도 건너 뛰지 마십시오. ? 데이터 자체를 읽을 필요가있을 때까지 독서를 저장할 수 있으며이를 일종의 체크섬으로 사용할 수 있습니다. 그리고 한 번에 256 바이트 만 읽으면 그보다 더 큰 버퍼는 필요 없습니다. –

+1

운영 체제에서 지원하는 경우 파일 매핑을 시도하십시오. 운영 체제는 청크 읽기를 메모리로 처리합니다. –

답변

1

디스크 탐색에 약 10ms (Latency Numbers Every Programmer Should Know에서)가 소요된다고 가정하면 파일은 2MB 청크로 구성된 11GB이고 이론적 인 최소 실행 시간은 5500 * 10ms = 55 초입니다.

이미 큰 문제가있는 경우 SSD를 구입하는 것이 가장 효과적입니다.

+0

* 디스크 검색에 약 10 밀리 초가 걸린다 고 가정합니다. * 실제로 꽤 낙관적입니다. 일반적으로 7,200 RPM SATA 디스크는 15 밀리 초 범위에 있으며 5,400 RPM 드라이브는 20 밀리 초를 훨씬 넘을 수 있습니다. 하지만 디스크에서 대역폭에 대해 궁금해. 70ms에서 2MB는 초당 28MB입니다. 70ms 중 20ms가 탐색 시간이라고 가정해도 디스크가 40MB/sec 만 움직이는 것을 의미합니다. 그것은 낮으며 데이터 경로를 따라 다른 하드웨어 병목 현상이있을 수 있습니다. SSD가 많은 도움을주지는 않습니다. –

+0

질문을 올바르게 이해했다면 전체 2MB가 아니라 색인을 구성하기 위해 256 바이트 만 읽을 필요가 있습니다. 그래서 시간을 찾으면 대역폭이 아니라 병목이됩니다. – Thomas