Возникла необходимость вызывать realloc тысячу раз в секунду(в самом худшем случае, 95% времени этого не будет). На сколько это плохо? Стоит ли выделять память блоками кратного размера чтобы избежать фрагментации кучи?
Обычно realloc() выделяет новый регион памяти и копирует туда старые данные. То, что он просто "продлевает" уже существующий регион - это иллюзия. В холостом копировании данных туда-сюда 1K раз в секунду, imho, мало смысла. Я бы как-нибудь реорганизовал программу, чтобы вообще избавиться от realloc(): увеличил бы буфер, разбил бы его на кусочки (вектор) и т.п.
> я согласен, просто некоторые оптимизации закладываются сразу в алгоритм. Потом, чтобы оптимизировать, придётся всё переделывать.
Если "придётся всё переделывать", то либо это "всё" очень маленькое, либо стоит лучше подумать над структурой программы, лучше изолирующей "алгоритм чего-то там" от всей конструкции.
> Обычно realloc() выделяет новый регион памяти и копирует туда старые данные. То, что он просто "продлевает" уже существующий регион - это иллюзия.
Чем нибудь докажете? А то все известные реализации сначала пытаются выполнить измененение размера in-place и только если не удается перевыделяют память…
Это как раз хороший пример, когда расчёт на "правильное" поведение realloc() приводит к очень существенному падению производительности на отдельных платформах (в данном случае - на Windows).
>Это как раз хороший пример, когда расчёт на "правильное" поведение realloc() приводит к очень существенному падению производительности на отдельных платформах (в данном случае - на Windows).
По моему в Линуксе аллокатор не охотится за дырками в куче, и все серия реаллокаций в конечном итоге будет происходить на ее вершине, где верхнего баунда нет.
> В холостом копировании данных туда-сюда 1K раз в секунду, imho, мало смысла.
не, не в холостом режиме. Просто я хочу сделать маленький буфер для клиента и расширять его если вдруг клиент пошлёт что-нить больше. Но я не хочу держать большие буфера и задумал, скажем, раз в минуту большие буфера уменьшать.
А по поводу того как работает аллокатор не спорьте: его с каждым релизом glibc патчат, да и делаю я кроссплатформенный код, поэтому учитывать особенности конкретной реализации realloc смысла нет.
ну так я как раз и говорю за то, что в общем случае realloc() работает "плохо", и поэтому в кроссплатформенном коде на realloc() лучше не рассчитывать.
Что касается изменения размеров буферов - каждый сам решает. Я предпочитаю держать буфер под максимальный размер пакета, чтобы не усложнять код, но если пакеты слишком уж большие (несколько десятков килобайт, наверное, уже многовато), то стараюсь организовать работу как с потоком, считывая и разбирая сообщения по кусочкам "на лету" (вместо считывания всего сообщения целиком с последующим разбором).
на windows realloc() так адски тормозит, что обычный std::vector::resize работал в 10 раз быстрее на некоторых продолжительных нагрузках. (конечно, не составляет проблем написать свою обёртку из 3-х строк с экспоненциальным ростом)