Вы правы, это распространенная проблема [Править: как сделать фиксированное распределение, я имею в виду. «malloc
замедляет мое приложение» встречается реже, чем вы думаете].
Если ваш код слишком медленный и malloc
вероятный виновник, то простой распределитель ячеек (или «пул памяти») может улучшить ситуацию. Вы почти наверняка найдете его где-нибудь, или его легко написать:
Выделите большой блок и поместите односвязный узел списка в начале каждой 16-байтовой ячейки. Свяжите их все вместе. Чтобы выделить, уберите голову из списка и верните ее. Чтобы бесплатно добавить ячейку в начало списка. Конечно, если вы пытаетесь выделить, а список пуст, то вам нужно выделить новый большой блок, разделить его на ячейки и добавить их все в свободный список.
Вы можете избежать этой большой предварительной работы, если хотите. Когда вы выделяете большой блок, просто сохраняйте указатель на его конец. Чтобы выделить, переместите указатель назад на 16 байтов через блок и верните новое значение. Если, конечно, это не было уже в начале блока [*]. Если это произойдет, и свободный список также пуст, вам нужен новый большой блок. Бесплатно не меняется - просто добавьте узел в список свободных.
У вас есть возможность выбрать сначала раздачу из блока и проверить список свободных мест, если он исчерпан, или сначала проверить список свободных мест, а также разгрузить блок, если он пустой. Я не знаю, что будет быстрее - хорошо в бесплатном списке «первым пришел - первым вышел» - это то, что он кеширует, так как вы используете память, которая использовалась недавно, поэтому я, наверное, попробую это первый.
Обратите внимание, что узел списка не нужен, когда ячейка выделена, поэтому на каждую ячейку накладных расходов практически нет. Помимо скорости, это, вероятно, будет преимуществом перед malloc
или другими распределителями общего назначения.
Имейте в виду, что удаление всего распределителя в значительной степени является единственным способом высвободить память обратно в систему, поэтому пользователи, которые планируют выделить много ячеек, использовать их и освободить их все, должны создать свой собственный распределитель , используйте его, а затем уничтожьте. Как для производительности (вам не нужно освобождать все ячейки), так и для предотвращения эффекта стиля фрагментации, когда целый блок должен храниться, если какая-либо из его ячеек используется. Если вы не можете этого сделать, то использование памяти будет являться высшей точкой того времени, когда ваша программа работала. Для некоторых программ это проблема (например, длительно работающая программа с периодическими резкими скачками в использовании памяти в системе, где память ограничена). Для других это абсолютно нормально (например, если количество используемых ячеек увеличивается почти до самого конца программы или колеблется в пределах диапазона, где вам действительно все равно, что вы используете больше памяти, чем могли бы строго). Для некоторых это активно желательно (если вы знаете, сколько памяти вы собираетесь использовать, вы можете выделить все это заранее и не беспокоиться о сбоях). В связи с этим некоторые реализации malloc
испытывают трудности с освобождением памяти из процесса в ОС.
[*] Где «начало блока», вероятно, означает «начало блока, плюс размер некоторого узла, используемого для ведения списка всех блоков, поэтому они могут быть освобождены при уничтожении распределителя ячеек». ».