N>>Добрый день, коллеги.
N>>Подскажите самый быстрый способ обнулить блок памяти (1000000 байт)?
R>самый бйстрый способ его просто выкинуть и выделить новый через virtualalloc
R>там он гарантированно будет забит нулями и занимается этим system idle process
VirtualAlloc то сам по себе может и окажется быстрее чем memset на уже выделенную память, но вот последующее первое обращение к этой памяти... Ой ой ой. Поясняю на живом примере:
int wmain(int argc, wchar_t* argv[])
{
volatile char *p = (volatile char *)malloc(0x100000);
DWORD ticks = ::GetTickCount();
for (int i = 0; i<10000; ++i)
{
memset((void *)p, 0, 0x100000);
}
printf("memset time: %u msec\n", ::GetTickCount() - ticks);
free((void *)p);
ticks = ::GetTickCount();
for (int i = 0; i<10000; ++i)
{
volatile char *p = (volatile char *)::VirtualAlloc(0, 0x100000, MEM_COMMIT, PAGE_READWRITE);
::VirtualFree((void *)p, 0, MEM_RELEASE);
}
printf("VM time: %u msec\n", ::GetTickCount() - ticks);
return 0;
}
Результаты:
memset time: 641 msec
VM time: 47 msec
Смеемся и плачем от счастья.. Потом думаем — ведь Virtual* теоретически подразумевают собой нехиый оверхед.. Идти в ядро, ковыряцца в таблицах страниц, дереве VAD процесса, Чота тут не так..
Слегка модифицируем тест:
void TouchMemory(volatile char *p, size_t l)
{
while (l>=0x1000)
{
*p = *p;
l-= 0x1000;
p+= 0x1000;
}
};
int wmain(int argc, wchar_t* argv[])
{
volatile char *p = (volatile char *)malloc(0x100000);
DWORD ticks = ::GetTickCount();
for (int i = 0; i<10000; ++i)
{
memset((void *)p, 0, 0x100000);
TouchMemory(p, 0x100000);
}
printf("memset time: %u msec\n", ::GetTickCount() - ticks);
free((void *)p);
ticks = ::GetTickCount();
for (int i = 0; i<10000; ++i)
{
volatile char *p = (volatile char *)::VirtualAlloc(0, 0x100000, MEM_COMMIT, PAGE_READWRITE);
TouchMemory(p, 0x100000);
::VirtualFree((void *)p, 0, MEM_RELEASE);
}
printf("VM time: %u msec\n", ::GetTickCount() - ticks);
return 0;
}
Теперь результаты:
memset time: 688 msec
VM time: 2953 msec
Вот все и встало на свои места.. Итак винда похоже тоже практикует ленивую отдачу страниц, так что постоянный VirtualAlloc будет быстрее однократного malloc + многократного memset тока если не не планируете этой памятью пользоваться Справедливости ради, если делать многократные malloc/memset/free то оно все же медленее чем VM... Во всяком случае пока у винды не наступит жесткий голодняк свободных и уже обнуленных в бэкграундее страниц.
O>Вот все и встало на свои места.. Итак винда похоже тоже практикует ленивую отдачу страниц
валлок будет все время выдавать разные блоки памяти.
Ты всего лишь сравнил скорость зануления 1мб блока в кэше процессора vs 1мб блок в оперативке.
Понятно что в кэше-то их занулять намного быстрее.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
O>>Вот все и встало на свои места.. Итак винда похоже тоже практикует ленивую отдачу страниц
R>валлок будет все время выдавать разные блоки памяти.
R>Ты всего лишь сравнил скорость зануления 1мб блока в кэше процессора vs 1мб блок в оперативке.
R>Понятно что в кэше-то их занулять намного быстрее.
Даже если и изза кэша, все равно медленно ведь