Каждый раз, когда у вас есть приложение, которое имеет критический путь с высокой производительностью, вы должны заботиться о том, как обращаться с памятью. Большинство клиентских приложений для конечных пользователей не попадают в эту категорию, потому что они являются первичными управляемыми событиями, и большинство событий происходит от взаимодействия с пользователем, и у него нет такого большого количества (если вообще имеется) ограничений производительности.
Тем не менее, многие фоновые программы должны сосредоточиться на том, как обрабатывается память, потому что большая часть этого программного обеспечения может масштабироваться для обработки большего количества клиентов, большего количества транзакций, большего количества источников данных ... Как только вы начнете раздвигая границы, вы можете начать анализировать, как ваши пользователи программного обеспечения запоминают память и писать собственные схемы распределения, адаптированные к вашему программному обеспечению, а не полагаться на полностью общий распределитель памяти, который был написан для обработки любого мыслимого варианта использования.
Чтобы привести несколько примеров ... в моей первой компании я работал над пакетом Historian, программным обеспечением, отвечающим за сбор / хранение / архивирование данных управления процессом (например, завод, атомная электростанция или нефтеперерабатывающий завод с 10 миллионами датчиков, мы будем хранить эти данные). Каждый раз, когда мы анализировали любые узкие места в производительности, которые мешали Historian обрабатывать больше данных, большую часть времени проблема заключалась в том, как обрабатывается память. Мы проделали большую работу, чтобы убедиться, что malloc / free не были вызваны, если они не были абсолютно необходимы.
На моей нынешней работе я работаю над видеомагнитофоном для видеонаблюдения и пакетом анализа. При 30 кадрах в секунду каждый канал получает видеокадр каждые 33 миллисекунды. На оборудовании, которое мы продаем, мы можем легко записать 100 каналов видео. Так что это еще один случай, чтобы убедиться, что в критическом пути (сетевой вызов => компоненты захвата => программное обеспечение для управления записывающим устройством => компоненты хранения => диск) нет динамического выделения памяти. У нас есть специальный распределитель кадров, который содержит блоки буферов фиксированного размера и использует LIFO для повторного использования ранее выделенных буферов. Если вам требуется 600 КБ хранилища, вы можете получить буфер 1024 КБ, который занимает пустое место, но поскольку он специально предназначен для нашего использования, где каждое выделение очень короткое, он работает очень хорошо, потому что используется буфер,
В описанных мной типах приложений (перемещение большого количества данных из A в B и обработка большого количества клиентских запросов) переход в кучу и обратно является основным источником узких мест производительности ЦП. Сокращение фрагментации кучи до минимума является вторичным преимуществом, однако, насколько я могу судить, большинство современных ОС уже реализуют кучи с низкой фрагментацией (как минимум, я знаю, что Windows это делает, и я надеюсь, что и другие тоже). Лично за 12+ лет работы в таких средах я часто сталкивался с проблемами использования процессора, связанными с кучей, хотя ни разу не видел систему, которая действительно страдала от фрагментированной кучи.