Добрый день, мы реализовали класс C ++ cKeyArray, чтобы проверить, можем ли мы использовать API больших файлов для экономии физической памяти. Во время тестирования Centos Linux мы обнаружили, что Linux File API работает так же быстро, как и использование кучи для обработки произвольного доступа. Вот числа: для базы данных SQL с 2700000 строк, где KeySize для каждой строки составляет 62 байта,
класс cKeyArray с использованием API-интерфейса LINUX File
BruteForceComparisons = 197275 BruteForceTimeElapsed = 1 763 504 445 микросекунд
Каждое сравнение BruteForce требует два произвольных доступа, то есть среднее время, необходимое для каждого произвольного доступа = 1 763 504 445 микросекунд / (2 * 197275) = 4470 микросекунд
Куча, без класса cKeyArray
BruteForceComparisons = 197275 BruteForceTimeElapsed = 1 708 442 690 микросекунд
среднее время, необходимое для каждого произвольного доступа = 4300 микросекунд.
В 32-битных Windows цифры:
класс cKeyArray с использованием Windows File API
BruteForceComparisons = 197275 BruteForceTimeElapsed = 9243787 миллисекунд
среднее время для каждого произвольного доступа составляет 23,4 миллисекун
Куча, нет класса cKeyArray
BruteForceComparisons = 197275 BruteForceTimeElapsed = 2,141,941 миллисек
среднее время, необходимое для каждого произвольного доступа, составляет 5,4 миллисекун
Нам интересно, почему числа cKeyArray в Linux так же хороши, как числа кучи Linux, тогда как в 32-битной Windows среднее время произвольного доступа к куче в 4 раза выше, чем в Windows File API cKeyArray. Есть ли какой-нибудь способ ускорить API-интерфейс Windows cKeyArray?
Ранее мы получили много хороших предложений от Stack Overflow по использованию API-интерфейса Windows Memory Mapped File. Основываясь на этих рекомендациях по переполнению стека, мы реализовали класс кэширования MRU для файла с отображенной памятью, который работает правильно.
Поскольку мы хотим разработать кроссплатформенное решение, мы хотим проявить должную осмотрительность, чтобы понять, почему Linux File API так быстр? Спасибо. Мы пытаемся опубликовать часть реализации класса cKeyArray ниже.
#define KEYARRAY_THRESHOLD 100000000
// Use file instead of memory if requirement is above this number
cKeyArray::cKeyArray(long RecCount_,int KeySize_,int MatchCodeSize_, char* TmpFileName_) {
RecCount=RecCount_;
KeySize=KeySize_;
MatchCodeSize=MatchCodeSize_;
MemBuffer=0;
KeyBuffer=0;
MemFile=0;
MemFileName[0]='\x0';
ReturnBuffer=new char[MatchCodeSize + 1];
if (RecCount*KeySize<=KEYARRAY_THRESHOLD) {
InMemory=true;
MemBuffer=new char[RecCount*KeySize];
memset(MemBuffer,0,RecCount*KeySize);
} else {
InMemory=false;
strcpy(MemFileName,TmpFileName_);
try {
MemFile=
new cFile(MemFileName,cFile::CreateAlways,cFile::ReadWrite);
}
catch (cException e)
{
throw e;
}
try {
MemFile->SetFilePointer(
(int64_t)(RecCount*KeySize),cFile::FileBegin);
}
catch (cException e)
{
throw e;
}
if (!(MemFile->SetEndOfFile()))
throw cException(ERR_FILEOPEN,MemFileName);
KeyBuffer=new char[KeySize];
}
}
char *cKeyArray::GetKey(long Record_) {
memset(ReturnBuffer,0,MatchCodeSize + 1);
if (InMemory) {
memcpy(ReturnBuffer,MemBuffer+Record_*KeySize,MatchCodeSize);
} else {
MemFile->SetFilePointer((int64_t)(Record_*KeySize),cFile::FileBegin);
MemFile->ReadFile(KeyBuffer,KeySize);
memcpy(ReturnBuffer,KeyBuffer,MatchCodeSize);
}
return ReturnBuffer;
}
uint32_t cKeyArray::GetDupeGroup(long Record_) {
uint32_t DupeGroup(0);
if (InMemory) {
memcpy((char*)&DupeGroup,
MemBuffer+Record_*KeySize + MatchCodeSize,sizeof(uint32_t));
} else {
MemFile->SetFilePointer(
(int64_t)(Record_*KeySize + MatchCodeSize) ,cFile::FileBegin);
MemFile->ReadFile((char*)&DupeGroup,sizeof(uint32_t));
}
return DupeGroup;
}