Уменьшение суммы malloc () вызовы улучшает производительность?

Рассмотрите два заявления: один (цифра. 1) это вызывает malloc () много раз, и другой (цифра. 2) это вызывает malloc () несколько раз. Оба приложения выделяют тот же объем памяти (примите 100 МБ).
Для которого приложения следующий malloc () вызов будет быстрее, № 1 или № 2?
Другими словами: malloc () имеют индекс выделенных местоположений в памяти?

28
задан Jonathan Leffler 17 January 2010 в 03:59
поделиться

8 ответов

Вот SSCCE :

<!doctype html>
<html lang="en">
    <head>
        <title>SO question 2079185</title>
        <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
        <script type="text/javascript">
            $(document).ready(function() {
                $(':input.remember').each(function() {
                    $(this).attr('data-remember', $(this).val());
                });
                $('button.reset').click(function() {
                    $(':input.remember').each(function() {
                        $(this).val($(this).attr('data-remember'));
                    });
                });
            });
        </script>
    </head>
    <body>
        <input type="text" class="remember" value="foo">
        <button class="reset">Reset</button>
    </body>
</html>

Это в основном сохраняет исходное значение каждого входного элемента с классом remember во время загрузки и инструктирует кнопку с классом reset восстановить его при каждом нажатии.

-121--4746502-

Теоретический максимум (без учета ограничений файловой системы) - Int64.MaxValue , как вы и предполагали. Я не уверен, что произойдет, если вы прочитаете файл дольше, но это кажется очень маловероятным;)

-121--4667842-

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

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

Предполагается, что память, выделенная для кучи, достаточно велика в обоих случаях. В случае No1 вам будет выделено больше общей памяти, так как каждое распределение включает в себя накладные расходы на память для хранения метаданных, в результате вам может потребоваться вызов sbrk () или эквивалент для увеличения кучи в случае No1, что добавит дополнительные накладные расходы.

Они, вероятно, будут отличаться из-за эффекта кэша и других эффектов второго порядка, так как выравнивания памяти для нового распределения не будут одинаковыми.

Если вы освобождаете некоторые блоки памяти, то, скорее всего, # 2 будет быстрее из-за меньшей фрагментации и, следовательно, меньшего списка свободных блоков для поиска.

Если вы освободили все блоки памяти, то они должны быть абсолютно одинаковыми, поскольку любая разумная свободная реализация объединит блоки обратно в единую область памяти.

10
ответ дан 28 November 2019 в 03:24
поделиться

Malloc должен просмотреть связанный список свободных блоков, чтобы найти тот, который нужно распределить. Это требует времени. Таким образом, #1, как правило, будет медленнее:

  • Чем чаще вы будете вызывать malloc, тем больше времени это займет - так что сокращение количества вызовов даст вам повышение скорости (хотя, будет ли это важно, будет зависеть от ваших конкретных обстоятельств).

  • Кроме того, если вы злоумышленник заблокирует много маленьких блоков, то по мере того, как вы освободите эти блоки, вы будете фрагментировать кучу гораздо больше, чем если бы вы только выделили и освободили несколько больших блоков. Таким образом, вы, скорее всего, закончите с большим количеством маленьких свободных блоков на вашей куче, а не с несколькими большими блоками, и, следовательно, ваши mallocs, возможно, придется искать дальше по спискам свободного пространства, чтобы найти подходящий блок, чтобы выделить. Что опять же сделает их медленнее.

6
ответ дан 28 November 2019 в 03:24
поделиться

Вы задали 2 вопроса:

  • для какого приложения следующий вызов malloc() будет быстрее, #1 или #2?
  • Другими словами: Имеет ли malloc() индекс выделенных ячеек в памяти?

Вы подразумевали, что это один и тот же вопрос, но это не так. Ответ на последний вопрос - YES.

Что касается того, что будет быстрее, сказать невозможно. Это зависит от алгоритма аллокации, машинного состояния, фрагментации в текущем процессе и так далее.

Ваша идея звучит вполне обоснованно: надо подумать о том, как использование malloc повлияет на производительность. Однажды я писал приложение, в котором использовалось много маленьких блоков памяти, каждый из которых выделялся с помощью malloc(). Оно работало корректно, но медленно. Я заменил множество вызовов malloc только на один, а затем нарезал этот большой блок внутри своего приложения. Это было намного быстрее.

Я не рекомендую такой подход, это всего лишь иллюстрация того, что использование malloc может существенно повлиять на производительность.

Мой совет - измерить его .

19
ответ дан 28 November 2019 в 03:24
поделиться

В частности, не существует специальных методов, которые может непосредственно реализовать класс Python для поддержки интерфейса буфера , который был бы PEP 298 , но он был удален.

Боюсь, вам придется использовать какой-то явный атрибут или метод (или встроенный как str , который внутренне вызывает специальный метод), чтобы передать экземпляры класса в file.write & c: - (.

-121--2717425-

На работе мне часто приходится накапливать большие наборы XML-документов для последующего анализа. Обычно это сделано, засунув их в справочник, и анализ сделан grep (или сделанная на заказ Явская программа со всеми ее ФАБРИЧНЫМИ/СТРОИТЕЛЯМИ/ОБЕРТКАМИ/API принадлежностями XML).

Однажды я подумал, что попробую поместить его в PostgreSQL. Есть две особенности, которые я хотел бы опробовать:

  • Автоматическое сжатие больших данных, когда это необходимо (TOAST).
  • Индексирование с использованием выражения.

Для первой функции размер базы данных был меньше половины размера необработанных файлов. Выполнение полнотекстового поиска, сканирование таблицы с использованием WHERE data:: TEXT LIKE '% образец%' , было на самом деле быстрее, чем выполнение grep для файлов. Когда вы имеете дело с несколькими ГБ XML, это само по себе делает БД стоящей.

Вторая функция, индексация, - это немного больше работы для обслуживания. Было несколько конкретных элементов, которые, как я предположил, было бы полезно проиндексировать. Индекс на xpath ('//startHeader/startId/text () ', data) работает, но дублирование в каждом запросе может быть затруднительным. Мне было проще добавлять обычные столбцы для некоторых полей и использовать триггеры вставки/обновления, чтобы синхронизировать их.

-121--3942023-

Вы можете всегда лучше работать с помощью malloc (), чтобы выделить большой объем памяти и разделить его самостоятельно. Malloc () был оптимизирован для хорошей работы в общем случае и не делает никаких предположений, используете ли вы потоки или каков может быть размер распределений программы.

Целесообразно ли реализовать собственный субраспределитель - вопрос второстепенный. Это редко так, явное управление памятью уже достаточно сложно. Вам редко нужен другой уровень кода, который может облажаться и разрушить вашу программу без какого-либо хорошего способа ее отладки. Если вы не пишете распределитель отладки.

2
ответ дан 28 November 2019 в 03:24
поделиться

Другой хорошая точка о WCF заключается в том, что если ваши требования когда-либо менялись и внезапно вы должны переместить одно из приложений на другую машину, требующую сейчас сетевых возможностей, вам нужно только Измените конфигурацию с обеих сторон, вместо того, чтобы перекодировать.

Плюс, AD David сказал, WCF является хорошим инструментом, чтобы иметь в вашей сумке.

Ура, Вагнер.

-121--2387537-

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

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

Однако могут быть лучшие шансы на успех при выделении небольших блоков памяти против одного большого блока. Ваша программа выделяет один небольшой блок и освобождает его или необходимо выделить (и сохранять) небольшие блоки. Когда память становится фрагментированной, доступно менее большие кусочки, поэтому распределитель памяти может придеться объединять все блоки для формирования блока достаточно большой для распределения.

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

1
ответ дан 28 November 2019 в 03:24
поделиться

Ответ заключается в том, что это зависит от того, что большая часть потенциальной медлительности скорее исходит от malloc() и free() в комбинации и обычно #1 и #2 будут иметь одинаковую скорость.

Во всех реализациях malloc() есть механизм индексации, но скорость добавления нового блока в индекс обычно не зависит от количества блоков, уже находящихся в индексе.

Большая часть медлительности malloc происходит из двух источников

  • ищущих подходящий свободный блок среди ранее освобожденных(блоков)
  • многопроцессорных проблем с блокировкой

Пишу свой почти стандартный инструмент замены malloc() malloc() && free() time от 35% до 3-4%, и он серьезно оптимизировал эти два фактора. Скорее всего, с такой же скоростью можно было бы использовать и какой-нибудь другой высокопроизводительный malloc, но иметь свой собственный было бы более переносимым на эзотерические устройства и, конечно же, позволяло бы в некоторых местах свободно встраиваться в него.

2
ответ дан 28 November 2019 в 03:24
поделиться

Вы не определяете относительную разницу между «множеством» и «немногими», но я подозреваю, что большинство Mallocs будут функционировать практически одинаково в обоих сценариях. Вопрос подразумевает, что каждый вызов Malloc имеет столько же накладных расходов, как обновления системного вызова и обновления страницы. Когда вы делаете Call Malloc, например, MALLOC (14), в окружающей среде без мозга, MALLOC фактически выделяет больше памяти, чем вы просите, часто множественную систему размер страницы MMU. Вы получаете 14 байтов и Malloc отслеживают вновь выделенную область, чтобы позже звонки могли просто вернуть кусок уже выделенной памяти, пока не нужно запросить больше памяти в ОС.

Другими словами, если я звоню Malloc (14) 100 раз или Malloc (1400) один раз, накладные расходы будут примерно одинаковыми. Мне просто нужно управлять большей выделенной кусочкой памяти.

1
ответ дан 28 November 2019 в 03:24
поделиться

Это, конечно, подробности реализации, но обычно free() вставляет память в список свободных блоков. Затем malloc() будет искать в этом списке свободный блок нужного размера или больше. Обычно только в случае неудачи malloc() просит у кернела больше памяти.

Есть и другие соображения, например, когда объединять несколько соседних блоков в один, больший блок.

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

3
ответ дан 28 November 2019 в 03:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: