2011-03-01 5 views
0

mmap-ed 파일을 통해 구문 분석하는 가장 빠른 (가장 빠른) 방법은 무엇입니까? 그것은 데이터 쌍 (문자열 int)을 포함하고 있지만 그것들 사이의 공백/탭/개행 문자의 수를 늘릴 수는 없습니다.mmap() 파일을 구문 분석

+1

"파싱"이란 무엇을 의미합니까? 파일에 저장된 내용과 수행하려는 작업은 무엇입니까? 이 질문은 대답하기에는 너무 모호합니다 ... – Nim

+1

@Martin strtok이 "소스"를 수정한다는 것을 알고 있습니까? 그래서 당신이 당신의 mmap에 그것을 사용한다면, 당신은 파일을 수정하고 있습니다! 파일 텍스트 만 또는 바이너리 또는 무엇입니까? 어떤 파싱 유형을 원하십니까? – xanatos

+0

투표 끝내기. 여기서 질문하는 것을 이해하는 것은 불가능합니다. –

답변

4

당신이 (awefully 복잡한 것을 만들 것 생명과 같이 오히려 덩어리보다는에게)에서 전체 파일을 mmaped 한 가정 ...

경고 경고는 this answer입니다.

+0

'std :: basic_streambuf :: setbuf'가 보호되어있다. – ildjarn

+0

@ildjarn, 그것을 고쳤습니다. 메소드는'pubsetbuf'이어야합니다 - 작동해야합니다 ... – Nim

+3

이것은 구현에 따라 정의 된 것입니다 : http://stackoverflow.com/a/13059195/636019 – ildjarn

0

귀하의 질문에 대답하기에는 너무 애매합니다. 당신이해야 할 모든 파일에서 일부 데이터를 얻을 경우

그럼에도 불구하고, 당신이하지이 원하는 무엇을 하면 mmap 에드 지역에서 메모리를 수정하는 것이 방법을 사용하는 것입니다.

편집 이제는 질문을 편집 한 것이 훨씬 분명해졌습니다. 출발점으로, 하나의 char 포인터를 사용하여 mmap 전체 파일을 반복 할 수 있습니다. 문자열을 추출하는 것은 매우 간단합니다 (정확한 방법은 결과로 수행해야하는 작업에 따라 다름) atoi 등으로 정수를 추출 할 수 있습니다.

0

std::string을 통해 액세스하고 std::istringstream을 사용하여 순차적으로 읽을 수 있습니다. 또는 좀 더 편리한 라이브러리를 사용하십시오. Qt에서 mmaped 메모리로 구성된 QByteArrayQTextStream을 사용할 수 있습니다.

+0

그래, 그 생각하지만 std :: string mmap 수 없습니다. 내가 어떻게 할 수 있니? – Marin

+0

죄송합니다, 나는'string :: string (const char * s, size_t n);'생성자가 단지 참조 할 것이라고 생각했습니다. 하지만 분명히 복사 ('const char *'...)를합니다. 'QByteArray :: fromRawData()'를 사용하면 기존 메모리 덩어리에서 작업 할 수 있습니다. 그러나,'QByteArray'의 수명 동안 그 청크의 수명을 보장해야합니다. –

2

코드 작성이 가장 쉽다는 것이 가장 빠르다면 이것은 희귀 한 경우 일 것입니다. 더 이상 사용되지 않을 경우 std::istrstream은 청구서를 완벽하게 기입합니다. istrstream::istrstream(char const*, std::streamsize) 생성자 오버로드를 호출하고 다른 std::istream에서와 같이 스트림에서 데이터를 추출하십시오. (std::istringstream와 같은 기본 메모리를 복제하지 않습니다.)

최상의/가장 빠른 런타임 성능을 의미하는 경우 사용자가 boost을 이길 수 있다고 생각하지 않습니다. spirit. qi 또는 손으로 쓴 파서를 사용하는 것이 좋습니다. 필자의 의견으로는 훨씬 쉽게 작성하고 유지할 수 있습니다 (이전에 boost.spirit을 사용한 적이없는 경우 라이브러리 학습 곡선을 제쳐두어 두십시오). 나는 ...

// Effectively this wraps the mmaped block 
std::istringstream str; 
str.rdbuf()->pubsetbuf(<pointer to start of mmaped block>, <size of mmaped block>); 

std::string sv; 
std::string iv; 

while(str >> sv >> iv) 
{ 
    // do stuff... 
} 

을 다음과 같은 일을 할 거라고 나는 생각 작동합니다 -

+0

eugh - 권장되지 않는 클래스를 추천합니다 - tsksksk ... – Nim

+0

@Nim 맞는 경우 적합합니다. : -] – ildjarn

+0

더 이상 비 사용되지 않는 클래스를 사용하는 것이 더 좋습니다 - 내 대답은 아래를 참조하십시오 ... – Nim

2

공백으로 구분 된 문자열/정수 쌍 (즉, foo 50 bar 20 baz 123)을 구문 분석하는 것이 번개가 빠른 방법이어야합니다. 에 의해 훨씬 더 중요한 요인 캐시 라인은 L1 캐시에있는)
가) 페이지가 RAM에 실제로
B를 보장하지 않습니다 만 메모리 매핑하는 것이 될 것입니다

mmap에 이미 순차 액세스 기본적으로 선행 읽기 않지만 디스크 액세스는 수십 밀리 초이며, 4k 페이지의 메모리에 대한 구문 분석은 수십 마이크로 초 (이상적)입니다.
따라서 프리 페처는 속도를 유지할 것으로 기대할 수 없습니다. 특히 더 많은 디스크가 필요할 때만 미리 가져 오기 때문에 (특히 시크 타임이 0이라고 가정해도 기계 디스크의 회전 지연으로 인해 초기 비용이 실질적으로 보장됩니다) .
따라서 전체 데이터가 단지 12 킬로바이트 (가능한 경우 빨리 수행하는 방법에 대한 질문은 아무리해도 무의미한 경우)가 아니면 스캔을 시작하기 전에 madvise (MADV_WILLNEED)하는 것이 좋습니다. 운영 체제는 액세스 패턴에 의해 트리거 된 휴리스틱을보기 위해 기다리지 않고 중단하지 않고 순차적으로 읽을 수 있습니다. 디스크 대역폭 (순차적)은 액세스 시간이 지나면 엄청납니다. 따라 잡기는하지만 나중에는 많이 따라 잡을 것입니다. 데이터 세트가 충분히 커서 RAM에 들어 가지 않을 정도로 크다면 이미 보았던 데이터에 대해 MADV_DONTNEED를 호출하는 것이 좋습니다.

페이지 폴트에 해당하는 것은 캐시 누락에 해당됩니다. 캐시의로드는 1-2 사이클이며, 메모리의로드는 약 200-500 사이클입니다.
CPU에는 순차 액세스 패턴에 대한 자동 프리 페치가 있지만 제한적입니다.
먼저 페이지 경계에서 프리 페치가 발생하지 않습니다. 이는 자동 프리 페치가 정기적으로 페이지 폴트를 유발하여 매우 불쾌 할 수 있기 때문입니다.
둘째, 프리 페치는 두 번의 연속 된 누락 이후에만 발생합니다. 이는 프리 페칭이 실제로 의미가있는 경우에만 실제로 시작되도록 보장하기위한 것입니다. 임의의 모든 읽기에 대해 인접한 캐시 라인을 프리 페치하는 것은 불필요한 캐시 라인을 낭비 할 수 있기 때문에 어리석은 행동입니다.
셋째, 프리 페칭에는 시간이 걸리며 CPU 트리거의 휴리스틱 스가 이미 데이터를 위해 이미 레이싱하고 있으므로 나중에 사용하는 것이 더 좋습니다. 다행히도 은 어떤 데이터를 원하는지을 알고 있으며 앞으로 오랜 시간이 걸릴 것입니다. 따라서 프리 페치 힌트를 제공하면 CPU가 중요한 출발점이 될 수 있습니다 (예 : 반 킬로바이트 전의 프리 페치).