Il multithreading sta solo andando a rallentare se non si desidera eseguire la scansione di più file con ciascuno su un disco rigido diverso. Altrimenti stai andando a cercare.
Ho scritto una semplice funzione di test utilizzando i file mappati in memoria, con un singolo thread un file da 1,4 GB richiedeva circa 20 secondi per la scansione. Con due thread, ognuno dei quali prendeva metà del file (anche un chilo di 1 MB in un thread, dispari rispetto all'altro), ci sono voluti più di 80 secondi.
- 1 discussione: 20015 millisecondi
- 2 Discussioni: 83985 millisecondi
Proprio così, 2 filetti era Quattro volte più lento di 1 filo!
Ecco il codice che ho usato, questa è la versione a thread singolo, ho usato un modello di scansione da 1 byte, quindi il codice per individuare le corrispondenze che si trovano tra i confini della mappa non è stato verificato.
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) È possibile che il modello si estenda per un limite di 100 MB? Se devi scrivere tu stesso l'algoritmo di ricerca e la stringa di ricerca è ragionevolmente lunga (più è lunga meglio è!), Considera l'algoritmo di Boyer-Moore http://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_string_search_algorithm – Kristen
@Kristen: il pattern non si estende su un limite di 100 MB, perché il pattern è bit '1'. – Jichao
Qual è lo schema, è davvero un singolo bit impostato? – GalacticJello