Как я могу найти информацию о распределителе памяти Windows C++, который я использую?
Отладка моего приложения C++ показывает следующее в стеке вызовов:
ntdll.dll!RtlEnterCriticalSection() - 0x4b75 bytes
ntdll.dll!RtlpAllocateHeap() - 0x2f860 bytes
ntdll.dll!RtlAllocateHeap() + 0x178 bytes
ntdll.dll!RtlpAllocateUserBlock() + 0x56c2 bytes
ntdll.dll!RtlpLowFragHeapAllocFromContext() - 0x2ec64 bytes
ntdll.dll!RtlAllocateHeap() + 0xe8 bytes
msvcr100.dll!malloc() + 0x5b bytes
msvcr100.dll!operator new() + 0x1f bytes
Мой многопоточный код масштабируется очень плохо, а профилирование с помощью случайной выборки указывает на то, что malloc в настоящее время является узким местом в моем многопоточном коде. Кажется, что стек указывает на некоторую блокировку при распределении памяти. Как я могу найти детали этой конкретной реализации malloc?
Я читал, что производительность системного распределителя Windows 7 в настоящее время конкурирует с распределителями, такими как tcmalloc и jemalloc. Я работаю на Windows 7, и я создаю Visual Studio 2010. Является ли msvcr100.dll быстрым/масштабируемым "системным распределителем Windows 7" часто упоминаемым как "Современное состояние"?
В Linux я видел резкое увеличение производительности в многопоточном коде, меняя распределитель, но я никогда не экспериментировал с этим в Windows - спасибо.
просто спрашиваю, какую реализацию malloc я использую, возможно, ссылку на некоторые подробности о моей конкретной версии этой реализации.
Столбик вызова, который вы видите, указывает на то, что MSVCRT (точнее, его operator new
умолчанию operator new
=> malloc
вызывается в функции Win32 Heap. (Я не знаю, направляет ли malloc
все запросы непосредственно в CRT Win32 Heap или делает это дополнительное кэширование - но если у вас есть VS, у вас должен быть и исходный код CRT, поэтому он должен быть в состоянии проверить это.) (В книге Windows Internals также говорится о куче.)
Общий совет, который я могу дать, заключается в том, что по моему опыту (VS 2005, но, судя по ответам Ганса по другому вопросу VS2010, может быть похоже) многопоточная производительность кучи CRT может вызвать заметные проблемы, даже если вы не делаете безумных сумм распределений.
Это RtlEnterCriticalSection
- это именно то, что критически важно для Win32: дешево блокировать с низким уровнем конкуренции, но с более высоким уровнем вы увидите субоптимальное поведение во время выполнения. (Бах! Когда-либо пытался профилировать/оптимизировать код, который кашляет по производительности синхронизации? Это беспорядок.)
Одно из решений заключается в разделении кучи: использование разных кучи дало нам значительные улучшения, хотя каждая куча все еще включена MT (без HEAP_NO_SERIALIZE
).
Поскольку вы "входите" через operator new
, вы можете использовать разные распределители для некоторых из разных классов, которые часто назначаются. Или, может быть, некоторые из ваших контейнеров могут извлечь выгоду из пользовательских распределителей (которые затем используют отдельную кучу).
Один случай, который мы имели, состоял в том, что мы использовали libxml2 для синтаксического анализа XML, а при создании дерева DOM он просто подталкивает систему в вызовах malloc.К счастью, он использует свой собственный набор программ распределения памяти, которые можно легко заменить тонкой оболочкой над функциями Win32 Heap.Это дало нам огромные улучшения, поскольку XML-синтаксический анализ больше не мешал остальным распределениям системы.