2016-10-07 3 views
0

Правильно ли я предполагаю, что когда процесс вызывает malloc, может быть задействован I/O (свопинг кэшей и т. Д.), Чтобы сделать память доступной, что, в свою очередь, означает, что она может блокировать значительное время? Таким образом, не следует ли иметь две версии malloc в linux, скажем, «fast_malloc», которая подходит для получения меньших фрагментов. & гарантированно не блокирует (но может, конечно, все еще сбой с OUT_OF_MEMORY) и еще один async_malloc, где мы могли бы запросить произвольные -размер пространства, но требует обратного вызова?Не должно ли malloc быть асинхронным?

Пример: если мне нужен небольшой кусок памяти, чтобы освободить место для элемента в связанном списке, я могу предпочесть традиционный встроенный malloc, зная, что ОС сможет удовлетворить его 99,999% времени или просто выйти из строя , Другой пример: если я сервер БД, пытающийся выделить значительный кусок, чтобы поместить в него индексы, я могу выбрать async_malloc и обработать «сложность обратного вызова».

Причина, по которой я привел это, заключается в том, что я ищу для создания высококонкурентных серверов, обрабатывающих сотни тысяч веб-запросов в секунду и, как правило, избегая потоков для обработки запросов. Иными словами, в любое время в I/O я хочу, чтобы он был асинхронным (например, на основе libevent). К сожалению, я понимаю, что большинство C API не имеют надлежащей поддержки для одновременного использования. Например, вездесущая библиотека MySQL C полностью блокируется, и это всего лишь одна библиотека, которую используют мои серверы. Опять же, я всегда могу имитировать неблокирование путем выгрузки в другой поток, но это нигде не столь дешево, как ожидание результата через обратный вызов завершения.

+5

Вызов 'malloc' по своей сути не вызовет больше ввода-вывода. Возможно, вы сбиваете с толку использование возвращенной памяти и просто выделяете вам память. Просто потому, что вы просите 100 МБ, это не означает, что 'malloc' немедленно вызовет 100 Мбайт обмена. Это происходит только тогда, когда вы * получаете доступ к памяти. – kaylum

+0

C не указывает временные характеристики 'malloc()'. Конечно, это не первое приложение, которое имеет проблемы с сроками. Типичный 'malloc()' wohtin основной ОС избегает блокировки в течение длительного времени и вместо этого выделяет только при использовании. http://stackoverflow.com/q/19991623/2410359. – chux

ответ

3

Как kaylum сказал в комментарии:

Calling malloc не будет по своей сути вызывать больше IO. Возможно, вы сбиваете с толку использование возвращенной памяти и просто выделяете вам память. Просто потому, что вы просите 100 МБ, это не означает, что malloc сразу же вызовет обмен 100 Мбайт. Это происходит только при доступе к памяти.

Если вы хотите защитить от длительных задержек для замены и т.д. во время последующего доступа к выделенной памяти, вы можете вызвать mlock на нем в отдельном потоке (так что ваш процесс не застопорился ожидание для mlock). Как только mlock преуспел, память физически создается и не может быть заменена до munlock.

2

Помните, что вызов функции malloc() не обязательно приводит к тому, что ваша программа запрашивает ОС для большей памяти. Это связано с реализацией Cmalloc() в C.

Для glibc malloc() просто (в зависимости от того, сколько вы запрашиваете) возвращает указатель на память, который уже имеет среда выполнения из ОС. Аналогично free() не обязательно возвращает память в ОС. Это намного быстрее. Я думаю, что glallc malloc() тоже потокобезопасен.

Интересно, что это дает C, C++ (и все построено сверху) те же свойства, которые обычно ассоциируются с такими языками, как Java и C#. Возможно, построение среды выполнения, такой как Java или C#, поверх среды выполнения, например glibc, означает, что на самом деле больше работы, чем необходимо для управления памятью ... Если они не используют malloc() или вообще ничего.

Там есть различные распределители, и вы можете связать любой, который вы хотите, в свою программу, независимо от того, что обеспечивает ваша обычная среда C. Поэтому даже на таких платформах, как * BSD (которые, как правило, гораздо более традиционны в своем подходе к распределению памяти, запрашивая ОС каждый раз, когда вы вызываете malloc() или new), вы можете снять тот же трюк.

+0

* Я думаю, что glibc's malloc() тоже потокобезопасен. * Это правда. Фактически реализация glibc 'malloc' управляет локальной (частной) ареной потока для каждого потока, так что почти не происходит столкновений, когда несколько потоков, вызывающих' malloc' одновременно. –

1

Иными словами, в любое время в I/O происходит, я хочу, чтобы он был асинхронным (скажем, на основе libevent).

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

:

malloc сам по себе вряд ли будет заблокирован, потому что системные вызовы он использует, просто создайте запись в структуре данных, которая сообщает о «карте в какой-либо памяти здесь, когда к ней обращаются». Это означает, что malloc будет блокироваться только тогда, когда ему нужно спуститься к ядру, чтобы отобразить больше памяти, и либо в ядре нет памяти, чтобы он сам должен был ждать выделения своей внутренней структуры данных (вы можете подождать довольно долго, а затем) или вы используете mlockall. Фактическое выделение памяти, которая может вызвать обмен, происходит не до тех пор, пока вы не коснетесь памяти. И ваша собственная память может быть заменена в любой момент (или текст вашей программы может быть выгружен), и вы почти не контролируете ее.

Смежные вопросы