Пытаюсь сам реализовать безразмерный саморасширяемый массив, вначале на 2Gb, затем больше. Т.е. при обращении к элементу массива чтобы проверялось, есть ли кластер в оперативке, и выдавался кластер, если нет - чтобы кластер грузился из файла. Если кластеров много - менее используемые выгружались. Т.е. как некая неисчерпаемая виртуальная память. Цель - закешировать результат выборки из любой СУБД, например, если она вернула миллион строк.
Может, есть готовая библиотека реализующая это через IStream интерфейс работы с файлами, или что-то такое? Часть СУБД бывают 32bit, чтобы решение могло работать и в 32bit, и 64bit. VirtualAlloc не подходит (адресное пространство в 32bit ограничено).
В идеале нечто такое
class BigArea{
operator char& [] (__int64 index) {
char * tmp_buff;
//...
return &tmp_buff[ index & 4095]; // Т.к. блок памяти 4096 байт.
}
}
Как источник "неисчерпаемой" памяти.
Есть ли библиотека, которая позволит закешировать 2-4-10 Gb памяти, разместив "лишнее" на диске, а наиболее используемую память в оперативной памяти?
Ответ
Поскольку реализации до сих пор нету, собрал такой "скелет".
class TBigMem{
private:
HANDLE hFile;
HANDLE hMap;
__int64 hIndex; //можно переназначить тип на тот, который в вашей IDE
__int64 maxsize;
void * mWnd;
DWORD AllocationGranularity; // Размер кратным которого должно быть окно
bool DoMap(unsigned long * index){
if (hIndex >=0)
UnmapViewOfFile(mWnd);
hIndex = *(__int64*)index;
void * wnd = MapViewOfFileEx(hMap, FILE_MAP_ALL_ACCESS, index[1],
index[0],AllocationGranularity,mWnd); /*Окно*/
if (wnd == 0) wnd=MapViewOfFileEx(hMap,FILE_MAP_ALL_ACCESS,
index[1], index[0],AllocationGranularity,NULL);/*Новое окно*/
if (wnd == 0) {
/*Обработать ошибку - не хватает памяти скорее всего*/};
if (wnd!=0) mWnd = wnd;
return wnd != 0;
};
public:
TBigMem (__int64 size) {// Размер можно сделать константой
char buff[512];
SYSTEM_INFO si;
GetSystemInfo(&si);
AllocationGranularity = si.dwAllocationGranularity;
GetTempPathA(sizeof(buff),buff);
GetTempFileNameA(buff,"bigmem",0,buff); // Тут задать префикс для временного файла
hFile = CreateFileA(buff,GENERIC_READ | GENERIC_WRITE ,0,NULL,CREATE_ALWAYS,
FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE,0);
hIndex = -1;
Realloc(size);
}
bool Realloc(__int64 size){
if (!hFile) return 0;
if (hIndex >=0) UnmapViewOfFile(mWnd);
if (hMap) CloseHandle(hMap);
hMap = 0;
hIndex = -1;
hMap = CreateFileMappingA(hFile,0, PAGE_READWRITE,
((unsigned long*)&size)[1], ((unsigned long*)&size)[0] ,0);
if (hMap !=0) maxsize = size;
return hMap != 0;
}
bool isValid() { return hMap !=0; };
~TBigMem(){
CloseHandle(hMap);
CloseHandle(hFile);
};
char& operator[](__int64 index){
union {
__int64 i;
unsigned long w[2];
} u;
if (index >= maxsize)// Авторасширение с выравниванием
Relloc(index - (index & AllocationGranularity)+AllocationGranularity);
if (hMap == 0) return *(char*)NULL; // Не возможно, обработать ошибку
unsigned long offs;
int err = 0;
u.i = index;
offs = u.w[0] & (AllocationGranularity-1);
u.w[0] &= ~(AllocationGranularity-1);
//TODO: тут можно дописать сдвиг индекса, что б окно было шире
if (u.i != hIndex) DoMap(&u.w[0]);
//err = GetLastError();
return *((char*)mWnd + offs);
};
unsigned int GetAvalible(__int64 index) { // Колличество байт, доступных в окне
return AllocationGranularity-((unsigned int)(index & (AllocationGranularity-1)));
}
};
Протестировал на небольших обьёмах так:
char c;
TBigMem data(1000000);
data[0]=1;
data[65536]=2;
с = data[0]; // переключить на первую страницу
с = data[65536]; // переключить другую станицу
Данные сохраняются. Пришлось разобраться с тем, как делать мапинг, с грануляцией страниц, с переключением отображения (во многих примерах переключения страниц отсутствует).
P.S. Ожидаю более удобную реализацию. На сейчас момент это единственный пример реализации.
Для char такое решение подходит, а для более емких типов нужно добавить "двойной" буфер, потому что при размере более одного байта тип может оказаться на "разрезе двух страниц".
Я столкнулся с тем, что не нашёл толкового описания как зарезервировать память для MapViewOfFileEx.
Для "расширеного" функционала, возможно нужны шаблоны template, это на будущее.
Комментариев нет:
Отправить комментарий