| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Общие вопросы > Менеджеры памяти |
| Автор: 3,14 10.7.2009, 08:12 |
| Есть многопоточное приложение, к-ое каждую секунду создает и удаляет до 6000 объектов. Имеет ли смысл заменить создание/удаление объектов с помощью new/delete на использование менеджера памяти? Даст ли это какой то выигрыш? Ссылки на литературу и результаты тестирования приветствуются. |
| Автор: maxim1000 10.7.2009, 08:37 |
| по-хорошему, для таких решений стоит провести измерение времени, которое программа проводит в operator new и operator delete. вообще глобальный менеджер памяти вряд ли стоит заменять, а вот рассмотреть какие-то частые частные случаи и использовать аллокаторы, заточенные под них, вполне может дать неплохие результаты например, если где-то часто выделяются объекты одинакового размера - можно использовать аллокаторы для фиксированных блоков памяти, есть, например, в boost-е |
| Автор: Lazin 10.7.2009, 10:05 | ||
здесь можно использовать не менеджер памяти, а пулл объектов, что-бы не создавать и удалять их каждый раз, а использовать раннее созданные объекты |
| Автор: Alexeis 10.7.2009, 10:22 |
| 6000 объектов в секунду это не мало. Может имеет смысл переписать код так чтобы объекты создавались в стеке и уничтожались по выходу из функции? Если число объектов не известно, то можно воспользоваться функцией alloca для выделения в стеке участков произвольного размера и очистки по выходу, только нужно следить чтобы не было переполнения стека. |
| Автор: Lazin 10.7.2009, 11:40 |
| размещать много данных в стеке - не самая лучшая идея, так как это приведет к потере производительности |
| Автор: avnemchenko 10.7.2009, 12:29 |
| Когда-то я создавал приложение, где с XML-файла бралась куча данных, на их основе строились новые. Там каждую секунду многомерные сложные конструкции динамически создавались, потом уничтожались (это было тестирование с большим количеством внешне задаваемых опций). И весьма скоро у меня все стало ВИСЕТЬ, по-черному Тогда я озверел, за недельку написал менеджер памяти. И в итоге 1) исчезли все проблемы с зависанием, т. к. все происходило в моей памяти, и не было динамических обращений к чему-то за ее пределами, 2) также я смог проконтролировать всякие перекрытия и их устранить, и 3) быстродействие ощутимо подскочило. Так что рекомендую! Как потом оказалось, у меня были проблемы с созданием текстовых строк - иной раз одно накладывалось на другое, или вообще в пустоту ссылалось... Теперь я везде использую эту свою библиотеку. Она у меня многопоточная (использую критические секции из Win API), стабильно и быстро работает. Теперь, правда, возникла неожиданная проблема - я себе резервирую кучу памяти. А когда я подключаю к своему приложению несколько своих же DLL-ек, и все они тоже резервируют кучу памяти, ее в итоге не хватает ... Буду дальше ее совершенствовать. А тем, кто не любит изобретать велосипеды, лучше брать что-то из Boost. |
| Автор: Леопольд 10.7.2009, 12:39 | ||||
На мой взгляд рекомендация Lazin о пуле лучшая. Я, наверное, перегрузил бы new - delete с использованием пула. И использовал бы "умные" указатели что бы не "парится" об исключениях. Добавлено @ 12:43
Мне кажется это нарвится всем... А в boost'е, как минимум, отдебажено не одним пользователем. Больше времени и внимания можно уделить остальному коду. |
| Автор: avnemchenko 10.7.2009, 13:23 | ||||
Угу. А вот насчет доверия другим библиотекам - было дело, в фирме писали мы компилятор здоровенный (пишется он на трех континентах сотней разработчиков). И там они использовали реализацию std:: от Silicon Graphics - там были одни заморочки 9глюки и баги). Потом подключили реализацию от Microsoft - там оказались другие баги. И меня это так задолбало, что я решил делать СВОЮ библиотеку, где будут МОИ баги! И я их буду исправлять в режиме реального времени, а не ждать месяцами, когда там прочухается поставщик библиотеки! Не спорю - это не самый быстрый путь. Зато самый надежный. |
| Автор: vinick 10.7.2009, 13:30 | ||
Можно узнать почему? Я всегда считал, что работа со стеком происходит гораздо быстрее чем с кучей. |
| Автор: Alexeis 10.7.2009, 13:59 |
| vinick, думаю тут дело в алгоритмах, стековый объект нельзя вернуть по ссылке, только копию, но я имел ввиду построить алгоритм так чтобы то что должно быть выделено выделялось вместе со входом в функцию и после обработки уничтожалось, без того чтобы его копировать. |
| Автор: Lazin 10.7.2009, 15:08 | ||
|
| Автор: 3,14 10.7.2009, 15:15 |
| Хм, а у меня вопрос как замерить производительность. Идея в том что сейчас проблем не наблюдается. Но пока нет основной функциональности, к-ая давала бы основную нагрузку. Я боюсь что возникнут проблемы на дальнейших стадиях, но просто так переписывать все на те же пулы тоже не хочется, а вдруг выигрыш будет пустяковый на самом деле? Собственно вопрос в том проводились ли какие либо тесты на этот счет и как протестировать что то подобное у себя? Могут ли возникнуть какие нибудь узкие места с многопоточным менеджером памяти у C++, и как результат лишние затраты на синхрониззацию? |
| Автор: Alexeis 10.7.2009, 16:51 | ||
Во-первых в настройках компилятора есть параметр - размер стека, вычисляешь сколько тебе максимум надо, умножаешь в 2 раза и ставишь как максимальный размер. Во-вторых если стек будет возрастать, то уже уменьшаться не будет, поэтому временные затраты на расширение стека это разовые затраты. Их не нужно учитывать. ОЗУ оно и в Африке ОЗУ, будет ли это стек или пул. Если юзать кучу то быстрее точно не будет. Факт в том что объект живет короткое время, а затраты на одну операцию выделения значительны. Уже есть встроенный механизм, не вижу смысла зачем его дублировать своим? |
| Автор: Леопольд 10.7.2009, 18:57 | ||
Не соглашусь... Просто надо пользовать заслужившие доверие open source библиотеки. Например, boost, wxWidgets... Думаю, их можно пользовать спокойно, именно потому что уже отдебажено другими пользователями. К тому же, если всё же есть бага в такой библиотеке, то её можно дебажить самому, в режиме реального времени... Обычно это быстрее чем написать свою библиотеку с высокой степенью надёжностью, такой-же сложности. |
| Автор: Lazin 10.7.2009, 21:58 | ||||||
Alexeis,
речь идет не о дублировании, существует множество стратегий управления памятью к примеру, в realtime системах как правило происходит какая-то обработка данных, выделяется память под множество объектов, а после того как обработка закончена, все созданные объекты разрушаются и система возвращается в исходное состояние, после чего все снова повторяется. При этом может фрагментироваться память, могут быть значительные задержки, а самое главное - сложно будет добиться того, что-бы каждая итерация укладывалась в определенные временные рамки. Как правило, для того, что-бы это исправить, абсолютно все временные объекты размещают в одном большом буфере, выделенном заранее в хипе. Ну и разрушить все сразу то-же не проблема, достаточно освободить буфер, предварительно вызвав деструкторы(хотя это не всегда нужно), можно даже не освобождать буфер а использовать его повторно. Если во время обработки данных что-то пойдет не так и, к примеру, произойдет выход за границу массива, то шансов испортить кучу - мало. Так как буфер большой, и маловероятно, что ты выйдешь за его границы. Если ты будешь использовать для этого стек, то помимо данных он естественно будет содержать и коды возврата, и параметры ф-ий. И если во время обработки данных программа испортит память, то велика вероятность, что стек будет испорчен то-же. в общем, ты получишь примерно такой call stack(растет вверх):
короче, все яйца в одну корзину лучше не класть |
| Автор: Alexeis 10.7.2009, 22:05 | ||
Так задача, то стояла в том чтобы многократно создавать и уничтожать. Повторно использовать это уже другая стратегия. Короче без дополнительной конкретизации дальше спорить бесполезно. |
| Автор: Леопольд 10.7.2009, 23:48 | ||
Создавать и разрушать не значит постоянно выделять память и возвращать её операционной системе. Lazin прав, гораздо быстрее выделять память большими кусками и уже там создавать и разрушать объекты. Память при этом возвращать операционной системе не надо, как правило. |
| Автор: 3,14 19.7.2009, 08:27 |
| Как бы это странно не звучало, но заметной нагрузки на проц создание/удаление такой кучи объектов вроде не дает. В чем тогда прикол использования менеджеров памяти? |
| Автор: MAKCim 19.7.2009, 08:52 |
фрагментация? |
| Автор: DrHex 19.7.2009, 08:59 |
| Короче чем меньше вызовов new\call тем быстрее. А вообще нужно писать объекты которые могут быть использованны много раз. |
| Автор: Леопольд 19.7.2009, 11:36 | ||
А по времени выполнения? Профайлер что показывает? |