2015-01-22 4 views
4

Я провел тест производительности при записи 128 миллионов ints в память, выделенную с помощью malloc, и сопоставленному файлу памяти (с поддержкой файла на диске) с помощью mmap ... Я ожидал, что результаты будут несколько похожими на я понимаю, что при записи в сопоставленный файл памяти данные сначала записываются в память, а pdflush записывает на диск в фоновом режиме (с частотой, которую можно настроить). С malloc запись 128M ints заняла 0,55 секунды; mmap занял 1,9 секунды.malloc vs mmap performance

Так что мой вопрос: почему разница. Мои инициалы были в том, что pdflush переполняет автобус или что, когда pdflush обращается к памяти, он блокирует записи ... Однако запуск версии mmap во второй раз вызвал результат .52 секунд (из-за кэширования), который приводит мне кажется, что каждая страница за mmap не выделяется до тех пор, пока она не будет записана (несмотря на то, что она зарезервирована для вызова в mmap) ... также я понимаю, что память, созданная malloc, фактически не выделяется до первой записи. . Возможно, первоначальное различие состояло в том, что после первоначальной записи в память с помощью malloc весь кусок выделяется и с mmap, каждый раз, когда записывается новая страница, os должен сначала выделить его?

UPDATE:

ОС: релиз CentOS Linux 7.0.1406 (ядро) ядро ​​: 3.10.0-123.el7.x86_64 НКУ: 4.8.2

КОД:

int* pint = malloc(128000000 * sizeof(int)); 
int* pint_copy = pint; 

clock_t start = clock(); 

int i; 
for(i = 0; i < 128000000; ++i) 
{ 
    *pint++ = i; 
} 

clock_t end = clock(); 

double cpu_time_used = ((double) (end - start))/CLOCKS_PER_SEC; 
printf("%f\n", cpu_time_used); 

free(pint_copy); 

против

int fd = open("db", O_RDWR | O_CREAT, 0666); 
const size_t region_size = ((512000000/sysconf(_SC_PAGE_SIZE)) + 1) * sysconf(_SC_PAGE_SIZE); 

int return_code = ftruncate(fd, region_size); 

if (return_code < 0) 
    printf("mapped memory file could not be truncated: %u\n", return_code); 

int* pint = mmap(NULL, region_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 
int* pint_copy = pint; 
close(fd); 

clock_t start = clock(); 

int i; 
for(i = 0; i < 128000000; ++i) 
{ 
    *pint++ = i; 
} 

clock_t end = clock(); 

double cpu_time_used = ((double) (end - start))/CLOCKS_PER_SEC; 
printf("%f\n", cpu_time_used); 

fgetc(stdin); 

munmap(pint_copy, region_size); 

ДОБАВЛЕНИЕ:

int z = 512; 
while(z < 128000000) 
{ 
    pint[z] = 0; 

    z += 1024; 
} 

ДО:

clock_t start = clock();  

Производит .37 секунд для обоих испытаний, что приводит меня к мысли, что «трогательные» на каждой странице приводит к тому, ОС выделить физическую память (как для mmap и malloc) ... это также может быть частично связано с тем, что «прикосновение» к страницам перемещает часть памяти в кеш-память ... знает ли кто-нибудь, если во время интенсивной записи в память (в течение длительного периода времени) pdflush блокирует или записывается медленная память?

+2

Это очень специфичный для ОС (и специфичный для компилятора), но вы не говорите, что используете. – Hogan

+2

Malloc, скорее всего, использует mmap, а также внутренне, проверьте с помощью strace. Скорее всего, это сопоставление объекта общей памяти (см. Shm_open, в недавних Linuxes это открывает файл в/dev/shm, используя tmpfs). Также флаг MMAP_POPULATE в mmap, вероятно, связан. –

+2

Так много переменных, которые могут повлиять на это: другие вещи, количество процессоров, доступность памяти, прерывания, фоновые операции ввода-вывода, считывание вперед и/или предварительные ошибки, фактическое использование 'mmap()' (т. map '/ dev/zero' или реальный файл или что-то еще, и если реальный файл, он существовал до того, как он был назначен или должен быть выделен) и так далее ... – twalberg

ответ

1

Да, вы правы. Страницы, полученные с помощью mmap, не заполняются, пока вы не попытаетесь получить к ним доступ. У вас не может быть гарантии на это, но обычно для ОС используется write-back (для этого только усиления нет штрафа) и demand-paging (вы должны оплатить первый доступ).

1

Я не знаю ответа, но это выглядит так, как будто вы сравниваете яблоки с апельсинами.

К сожалению, с одной стороны вы пишете память (malloc'd), а с другой стороны, вы записываете в память и в (mmap'd) диск. Я бы ожидал, что вторая, которая влечет за собой операцию ввода-вывода устройства, будет на порядок медленнее, чем первая, которая не несет никаких операций ввода-вывода.