Подтвердить что ты не робот

Замена Windows malloc (например, tcmalloc) и динамическое соединение crt

Программа С++, использующая несколько DLL и QT, должна быть оснащена заменой malloc (например, tcmalloc) для проблем с производительностью, которые могут быть проверены вызванных Windows malloc. С linux нет проблем, но с окнами существует несколько подходов, и я не считаю их привлекательными:

1. Поместите новый malloc в lib и не забудьте связать его сначала (Другой вопрос SO)

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

2. Удалите malloc из статической библиотеки libcrt с помощью lib.exe(Chrome)

Это проверено/использовано (?) для chrome/chromium, но имеет тот недостаток, что он просто работает со статической связью crt. Статическая связь имеет проблему, если одна системная библиотека динамически связана с msvcrt, может быть несоответствие в распределении/освобождении кучи. Если я правильно ее понимаю, tcmalloc можно связать динамически так, чтобы существовала общая куча для всех самокомпилированных DLL (что хорошо).

3. Патч crt-source code (firefox)

Firefox jemalloc, по-видимому, исправляет исходный код Windows CRT и создает новый crt. Это опять-таки статическая/динамическая проблема связи выше.

Можно подумать об использовании этого для создания динамического MSVCRT, но я думаю, что это невозможно, потому что лицензия запрещает предоставление исправленного MSVCRT с тем же именем.

4. Динамическое обновление загруженного CRT во время выполнения

Некоторые коммерческие распределители памяти могут делать такую ​​магию. tcmalloc может тоже, но это кажется довольно уродливым. У него были некоторые проблемы, но они исправлены. В настоящее время с tcmalloc он не работает под 64-битными окнами.

Есть ли лучшие подходы? Любые комментарии?

4b9b3361

Ответ 1

Q: Программа С++, разделенная на несколько DLL, должна:

A) заменить malloc?

B) обеспечить, чтобы распределение и де-распределение выполнялись в одном и том же модуле dll?

A: Правильный ответ - B. Конструкция приложения С++, которая включает в себя несколько DLL, ДОЛЖНА гарантировать, что существует механизм для обеспечения того, что вещи, которые распределены в куче в одной DLL, освобождаются одним и тем же модулем dll.


Почему вы все равно разделили программу на С++ на несколько dll? С помощью программы С++ я имею в виду, что объекты и типы, с которыми вы имеете дело, - это С++-шаблоны, объекты STL, классы и т.д. Вы НЕ МОЖЕТЕ передавать объекты С++ по границам dll без какой-либо очень тщательной разработки и большого количества специфических для компилятора магии или страданий от массивного дублирования объектного кода в различных DLL, и, как результат, приложение, которое чрезвычайно чувствительно к версии. Любое небольшое изменение определения класса приведет к перестройке всех exe и dll, удалив хотя бы одно из основных преимуществ подхода dll к разработке приложений.

Либо придерживайтесь прямого интерфейса C между приложением и dll, терпите ад или просто скомпилируйте все приложение С++ как один exe.

Ответ 2

Это смелое утверждение о том, что программа С++ должна быть оснащена заменой malloc (например, tcmalloc) для проблем с производительностью.... "

"[В] 6 из 8 популярных тестов... [приложения реального размера] заменяют пользовательский распределитель, в котором люди вложили значительное количество времени и денег... с предоставленным системой немым распределителем [дал] лучшую производительность... Простейшие пользовательские распределители, настроенные для особых ситуаций, являются единственными, которые могут обеспечить выигрыш". - Андрей Александреску

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

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

С++ предоставляет несколько способов выборочной замены распределителя. Например, вы можете предоставить распределитель для контейнера STL, или вы можете переопределить новый и удалить в классе по классам. Оба они дают вам гораздо лучший контроль, чем любой хак, который во всем мире заменяет распределитель.

Заметим также, что замена malloc и free не обязательно будет изменять распределитель, используемый операторами new и delete. Хотя глобальный новый оператор обычно реализуется с использованием malloc, нет необходимости в том, чтобы он это делал. Поэтому замена malloc может даже не повлиять на большинство распределений.

Если вы используете C, скорее всего, вы можете обернуть или заменить ключ malloc и бесплатные вызовы с помощью своего настраиваемого распределителя, где это имеет значение, и оставить остальную часть программы использовать распределитель по умолчанию. (Если это не так, вы можете рассмотреть некоторые рефакторинг.)

Системные распределители имеют десятилетия развития за ними. Они стабильны и хорошо протестированы. Они отлично справляются с общими случаями (с точки зрения скорости загрузки, обсуждения потоков и фрагментации). У них есть отладочные версии для обнаружения утечек и поддержки инструментов отслеживания. Некоторые даже улучшают безопасность вашего приложения, обеспечивая защиту от переполнения буфера буфера. Скорее всего, библиотеки, которые вы хотите использовать, были протестированы только с системным распределителем.

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

Ответ 3

Где ваша предпосылка "Программа на С++, которая использует несколько DLL и QT, должна быть оснащена заменой malloc" из?

В Windows, если все DLL использует общий MSVCRT, нет необходимости заменять malloc. По умолчанию Qt строит против общей библиотеки данных MSVCRT.

У вас возникнут проблемы, если они:

1) Смешать библиотеки DLL, которые используют статические ссылки, используя общий VCRT

2) И также свободная память, которая не была распределена там, где она появилась (т.е. свободная память в статически связанной DLL, которая была распределена совместно VCRT или наоборот).

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

Ответ 4

nedmalloc? также NB, что smplayer использует специальный патч для переопределения malloc, который может быть направлением, в котором вы находитесь.