malloc против mmap в C

Я создал две программы, одну с использованием malloc, а другую с использованием mmap. Время выполнения с использованием mmap намного меньше, чем с использованием malloc.

Например, я знаю, что когда вы используете mmap, вы избегаете вызовов чтения/записи в систему. И доступ к памяти меньше.

Но есть ли другие причины преимуществ при использовании mmap перед malloc?

Большое спасибо


person Peter    schedule 15.11.2009    source источник
comment
Могу ли я предположить, что ваша программа malloc использует чтение/запись или fread/fwrite для выполнения некоторого ввода-вывода в файле, который вы mmap в другом случае?   -  person Suppressingfire    schedule 16.11.2009
comment
Да, на самом деле я использую чтение/запись с malloc, mmap и обычные вызовы R/W. использование вызовов R/W быстрее, чем использование malloc, я думаю, потому что доступ к диску быстрее, чем к памяти.   -  person Peter    schedule 16.11.2009
comment
Дело не в том, что доступ к диску быстрее, чем к памяти. Почти всегда память намного быстрее диска, и malloc не стоит времени. Код mmap быстрее, потому что для вашей программы mmap привел либо к меньшему доступу к диску, либо к более эффективному доступу к диску, чем любые операции чтения и записи, с которыми вы сравниваете. Например, write для всего файла фактически отправляет все эти байты на диск. mmap просто означает, что если вы измените mmap данные, тогда ОС запишет изменения. Поэтому, если вы в конечном итоге не измените весь файл, вы можете написать только его часть.   -  person Steve Jessop    schedule 16.11.2009
comment
Я думаю, это потому, что доступ к диску быстрее, чем к памяти. Это очень неверно. Поскольку вы не даете кода, я не уверен, о чем именно вы говорите, когда malloc медленнее, чем mmap. Обе функции отображают адресное пространство, они не обязательно выделяют какую-либо физическую память. И не читают файлы. Оба будут выделять физическую память по мере использования каждой страницы, но mmap будет делать это, читая ее с диска, что, безусловно, будет медленнее (ошибки жесткой страницы по сравнению с ошибками программной страницы). Системные вызовы чтения/записи могут быть или не быть быстрее, чем жесткие ошибки страницы, в зависимости от многочисленных факторов.   -  person Eloff    schedule 27.05.2010
comment
mmap допускает и другие применения, например, создание области разделяемой памяти, с которой ваш процесс может взаимодействовать с разветвленными прецессами.   -  person Patrick Schlüter    schedule 22.10.2010


Ответы (6)


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

Другое дело, что mmap не использует память, но занимает адресное пространство. На 64-битной машине большая часть адресного пространства памяти не будет иметь памяти, поэтому вы можете загружать огромные файлы, скажем, 5 ГБ, которые вам не хотелось бы malloc.

person Jeffrey Aylesworth    schedule 15.11.2009
comment
Еще один момент заключается в том, что mmap не использует никакой памяти, не будет ли он также включать какую-либо копию DMA? если он не использует память, то как процессор может что-либо сделать с данными, которые хранятся в файле? - person RaGa__M; 27.09.2019

Я предполагаю, что вы имеете в виду использование mmap и malloc для чтения данных из файлов. В этом случае вы в значительной степени поняли главное:

  • используя fread/fwrite, вы должны сделать много вызовов ОС.
  • используя mmap, вы, кажется, получаете доступ ко всему файлу за одну операцию. Это не совсем так, потому что ОС, вероятно, отображает файл на одну страницу памяти за раз, но это все еще намного быстрее.
person Anton    schedule 15.11.2009
comment
Чтобы добавить к этому, fread буферизуется, это означает, что если ему предшествует fseek, он всегда будет полностью заполнять его буфер. У меня была программа, которая читала файл последовательно, но перед каждой записью (размером 32) перед каждой записью (размером 32) читала 8192 байта. Таким образом, он считывал в 256 раз больше данных, чем необходимо, плюс чтение всегда занимало два обращения к ядру. С mmap у вас его нет (видимый). - person Patrick Schlüter; 22.10.2010

Послушайте, ребята, вопреки распространенному мнению, mmap действительно является функцией распределения памяти, похожей на malloc.

файл mmaped - это одно из его применений.. вы можете использовать его как функцию выделения памяти, передавая -1 в качестве дескриптора файла..

Итак, обычно используется malloc для крошечных объектов и mmap для больших.

это хорошая стратегия..

я использую alloca() только для переменных области видимости функции..

person user410034    schedule 21.10.2010
comment
Обычно распределитель будет использовать сам mmap в зависимости от размера области, запрашиваемой с помощью malloc. В Solaris при запросе более 128 КБ вы получите блок с отображением памяти MAP_ANON. В OS/X ограничение составляет 64 КБ, если я правильно помню, другие системы и библиотеки распределения будут иметь другие значения. - person Patrick Schlüter; 22.10.2010

И malloc, и mmap иногда работают медленно. В основном это зависит от схемы использования:

mmap: Подсистема пейджинга ядра работает в единицах размера страницы. Это означает, что если вы хотите прочитать целую страницу из файла и хотите делать это неоднократно (хорошая локализация), с mmap все будет в порядке. Напротив, если вы сопоставите этот 5-гигабайтный файл и сделаете разбросанный доступ, у вас будет много страниц подкачки ядра. В дополнение к фактическому вводу-выводу управление страницами займет некоторое время. Если у вас есть опасения по поводу задержки, избегайте этого шаблона доступа, поскольку механизм восстановления страниц в Linux имеет тенденцию к скачкообразной работе и вызывает заметные задержки, а отравление кеша замедляет другие процессы.

malloc: это нормально, когда вам нужна память не в единицах размера страницы. но вы не можете разумно делать такие вещи, как mlock(). С точки зрения ввода-вывода скорость очень сильно зависит от того, как вы это делаете. fread/fwrite может отображать страницы за кулисами или выполнять буферизацию в пользовательском пространстве. Локализованный доступ будет достаточно быстрым. чтение/запись проходят непосредственно через ядро, поэтому небольшие распределенные доступы по-прежнему будут вызывать ввод-вывод из-за промахов в кеше, но фактические данные, передаваемые из ядра-> пользовательского пространства, будут немного меньше. Я не знаю, измеримо ли это.

Если mlock() не используется, пользовательские страницы могут быть выгружены/записаны обратно в любое время. Это тоже требует времени. Таким образом, на системах с небольшим объемом памяти победит вариант, отображающий наименьшее количество памяти. С ядром Linux в каждой системе слишком мало памяти, так как неиспользуемые страницы используются для кэширования ввода-вывода, и ядру может потребоваться заметное время, чтобы сделать их доступными, если использование памяти или ввод-вывод неравномерны.

person prostatanus    schedule 02.03.2013

mmap на самом деле не читает файл. Он просто сопоставляет его с адресным пространством. Вот почему это так быстро, нет дискового ввода-вывода, пока вы не получите доступ к этой области адресного пространства.

malloc — это просто сопоставление адресного пространства с памятью.

person joemoe    schedule 15.11.2009

По mmap оперативная память не предоставляется. Адресное пространство предоставляется.

При доступе к адресному пространству возникает ошибка страницы. При сбое страницы в размере страницы, обычно 4096 байт, выделяется оперативная память.

Содержимое оперативной памяти также предоставляется. Если файлом резервируется адресное пространство, то появится содержимое файла. Если с помощью MAP_ANONYMOUS адресное пространство резервируется, появляется нулевое инициализированное ОЗУ.

Выше описаны два блага. Во-первых, именно так, как хотелось бы, ОЗУ можно инициализировать. Во-вторых, пока требуемой оперативной памяти не предусмотрено.

Для запроса адреса размером менее 2 мегабайт от malloc прерывание программы расширяется. Пока адреса, близкие к перерыву в программе, предоставляются, перерыв в программе не может быть сокращен. Следовательно, освобожденная оперативная память ядра может быть не возвращена. Далее следует аналогия. Можно ли снимать носки перед обувью?

При вызове munmap ядру немедленно возвращается оперативная память. При использовании mmap и munmap снижается вероятность подкачки. При прерывании программы malloc повышается вероятность подкачки расширения.

С помощью malloc можно выделить память меньше размера страницы. Прерывистая память становится. Память ядра также может фрагментироваться. Ни то, ни другое не идеально.

На любом неработающем процессоре с помощью ядра ОЗУ можно дефрагментировать. Создаются прозрачные огромные страницы размером 2 мегабайта. По сравнению с ошибкой 512 страниц для обеспечения 2M Когда сбой одной страницы 2M может быть обеспечен значительным преимуществом в производительности.

По mmap существует по крайней мере одно известное проклятие. Для поддержки mmap можно использовать дескриптор файла канала. Ошибки не становится. Однако в адресе памяти, предоставленном каналом, данные не отображаются.

Однако, если используется MAP_ANONYMOUS, данные могут быть прочитаны из дескриптора файла канала в адрес, предоставленный mmap. Хотя желаемый результат становится не таким эффективным. По неудачному возврату lseek и ошибке может быть идентифицирован дескриптор прикрепленного к каналу файла.

На компьютерах, которые могут адресовать весь мегабайт и запускать дисковую операционную систему, использование malloc необходимо. Если использование библиотеки C предоставляет функцию getline, то, вероятно, будут использоваться malloc и free.

В операционной системе, управляемой ядром, вместо mmap зачем использовать malloc? По сравнению с malloc; mmap кажется сложным? Для вызова munmap также необходимо указать ранее запрошенный объем адресного пространства. Использование malloc более портативно? malloc кажется более удобным?

Тем не менее, если требуется производительность, используется mmap.

И последнее, но не менее важное: если MAP_SHARED, то с дочерними процессами данные могут использоваться совместно. Избегать pthreads имеет первостепенное значение. Иногда клонирования также можно избежать.

Несмотря на то, что методы распределения переменных субъективны, они перечислены в порядке от наиболее предпочтительного до наименее предпочтительного: регистр/стек; ммап; Глобальный; маллок От каждого становятся разные блага и проклятия. достаточно сложной программой; используются три или, возможно, все четыре метода.

person loquacious    schedule 25.03.2016
comment
Нет, приятель, просто нужно говорить о пиратах, чтобы быть правдой в голове. - person Chris Reid; 14.04.2017
comment
Этот ответ на самом деле дает ценную информацию об управлении памятью в Linux. - person Richard; 25.10.2018