멀티 스레딩은 서로 다른 하드 드라이브에있는 각각의 파일을 스캔하려는 경우를 제외하고는 속도가 느려지 게 만듭니다. 그렇지 않으면 당신은 단지 찾을 것입니다.
메모리 매핑 된 파일을 사용하여 간단한 테스트 함수를 작성했습니다. 단일 스레드로 1.4Gb 파일을 스캔하는 데 약 20 초가 걸렸습니다. 두 개의 스레드가 파일의 절반을 차지하고 (1MB는 한 스레드로, 다른 스레드는 홀수로), 80 초 이상 걸립니다.
- 1 실 : 20,015 밀리 초
- 2 스레드 : 83,985 밀리 초
맞아, 2 개 스레드 1 개 스레드가 아닌 네 배 느렸다!
여기는 내가 사용하는 코드입니다.이 코드는 단일 스레드 버전이며, 1 바이트 스캔 패턴을 사용하므로 맵 경계를 넘어선 일치하는 위치를 찾지 못하는 코드는 테스트되지 않았습니다.
HRESULT ScanForPattern(LPCTSTR pszFilename, LPBYTE pbPattern, UINT cbPattern, LONGLONG * pcFound)
{
HRESULT hr = S_OK;
*pcFound = 0;
if (! pbPattern || ! cbPattern)
return E_INVALIDARG;
// Open the file
//
HANDLE hf = CreateFile(pszFilename,
GENERIC_READ,
FILE_SHARE_READ, NULL,
OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN,
NULL);
if (INVALID_HANDLE_VALUE == hf)
{
hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
// catch an open file that exists but is in use
if (ERROR_SHARING_VIOLATION == GetLastError())
hr = HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION);
return hr;
}
// get the file length
//
ULARGE_INTEGER uli;
uli.LowPart = GetFileSize(hf, &uli.HighPart);
LONGLONG cbFileSize = uli.QuadPart;
if (0 == cbFileSize)
{
CloseHandle (hf);
return S_OK;
}
const LONGLONG cbStride = 1 * 1024 * 1024; // 1 MB stride.
LONGLONG cFound = 0;
LPBYTE pbGap = (LPBYTE) malloc(cbPattern * 2);
// Create a mapping of the file.
//
HANDLE hmap = CreateFileMapping(hf, NULL, PAGE_READONLY, 0, 0, NULL);
if (NULL != hmap)
{
for (LONGLONG ix = 0; ix < cbFileSize; ix += cbStride)
{
uli.QuadPart = ix;
UINT cbMap = (UINT) min(cbFileSize - ix, cbStride);
LPCBYTE pb = (LPCBYTE) MapViewOfFile(hmap, FILE_MAP_READ, uli.HighPart, uli.LowPart, cbMap);
if (! pb)
{
hr = HRESULT_FROM_WIN32(GetLastError());
break;
}
// handle pattern scanning over the gap.
if (cbPattern > 1 && ix > 0)
{
CopyMemory(pbGap + cbPattern - 1, &pb[0], cbPattern - 1);
for (UINT ii = 1; ii < cbPattern; ++ii)
{
if (pb[ii] == pbPattern[0] && 0 == memcmp(&pb[ii], pbPattern, cbPattern))
{
++cFound;
// advance by cbPattern-1 to avoid detecting overlapping patterns
}
}
}
for (UINT ii = 0; ii < cbMap - cbPattern + 1; ++ii)
{
if (pb[ii] == pbPattern[0] &&
((cbPattern == 1) || 0 == memcmp(&pb[ii], pbPattern, cbPattern)))
{
++cFound;
// advance by cbPattern-1 to avoid detecting overlapping patterns
}
}
if (cbPattern > 1 && cbMap >= cbPattern)
{
// save end of the view in our gap buffer so we can detect map-straddling patterns
CopyMemory(pbGap, &pb[cbMap - cbPattern + 1], cbPattern - 1);
}
UnmapViewOfFile(pb);
}
CloseHandle (hmap);
}
CloseHandle (hf);
*pcFound = cFound;
return hr;
}
(2) 패턴이 100MB 경계까지 확장됩니까? 검색 알고리즘을 직접 작성해야하고 검색 문자열이 비교적 길면 길수록 좋습니다! Boyer-Moore 알고리즘을 고려하십시오. http://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_string_search_algorithm – Kristen
@Kristen : 패턴은 100MB 경계를 넘지 않습니다. 패턴이 '1'비트이기 때문입니다. – Jichao
패턴은 무엇입니까? 실제로는 단일 세트 비트입니까? – GalacticJello