Выделение памяти - это блокир операция, а вот сколько она занимает во временном интревале? GetTickCount тут понятно не сработает. И что влияет на это время?
Из далека конечно начал, но имеет ли смысл писать для своей проги "менджер памяти" т.е. в начале запуска выделять большой кусок памяти, потом разбивать на блоки по 10к и при запросе смотреть есть ли в массиве свободные участки и занимать эту память. Просто столкнулся при написании сервера - для каждого отсыла данных выделять GetMem, а после завершения операции чистить.
Классная функция QueryPerformanceCounter! Протестил функции GetMem и VirtualAlloc. До 1к Getmem работает шустрее раза в три. При более 10к VirtualAlloc быстрее выделяет. Что странно при первом вызове VirtualAlloc время раза в 4 больше затрачивается, чем при последующих... К чему бы это?
SnugForce "Послать" бы тебя покурить мануалы, да поискать по гуглу и по форуму ) Я на подобные вопросы Virtual vs Heap уже не раз отвечал, вот только неизвестно, что после "больших чисток" сохранилось Ну да ладно, с точки зрения быстродействия дело обстоит так: 1) Основные задержки возникают при выделении страниц физической памяти. Во-первых, это неизбежные отказы страниц (#PF - page fault) - на них держится все управление виртуальной памятью. Винда никогда не торопится выделять физ.память по первому требованию - при любых VirtualAlloc, MapView и т.п. она лишь подготавливает служебные структуры данных (VAD, PDE, PTE), содержащих описание (дескрипторы) выделенных регионов и страниц памяти. Когда приложение обращается к странице, не присутствующей в физ.памяти, процессор генерит #PF и винда "бросается" выделять под страницу физ память. При этом сама обработка исключения занимает не менее нескольких тысяч тактов процессора. Во-вторых, к этому могут добавляться дополнительные тормоза, связанные со свопингом и обнулением выделяемых страниц. 2) Резервирование памяти MEM_RESERVE выполняется достаточно быстро, т.к. при этом лишь добавляется небольшая запись в VAD (virtual address descriptor) и никаких отказов при этом обычно не происходит. А вот при первом MEM_COMMIT возникают доп.тормоза, т.к. винда при этом должна выделить и инициализировать одну или несколько страниц памяти под таблицы страниц (PT, каждая таблица занимает 4К и при 32-бит адресации описывает 4M памяти). При последующих MEM_COMMIT этих тормозов может не быть, если запрашиваемый адрес соответствует уже инициализированным PT. 3) Быстродействие функций кучи ес-но зависит от того выделяется ли блок памяти из уже выделенных физ.страниц или приходится выделять доп.память VirtualAlloc'ом. В первом случае мы имеем лишь небольшие накладные расходы на поиск свободного блока нужного размера, запись заголовка блока и изменения связей в списке свободных блоков - все это мелочи по сравнению с #PF (даже с учетом блокировок). В любом случае это работает на порядки быстрее, чем выделение нового блока VirtualAlloc'ом, и фразы типа "шустрее раза в три" скорее всего свзяаны с некорректными сравнениями. Дело в том, что сам по себе VirtualAlloc с MEM_COMMIT дает существенные тормоза при первом вызове, но в любом случае будут дополнительные тормоза в момент первого обращения на чтение или запись к каждой странице выделенного блока памяти. Если же GetMem\HeapAlloc повторно выделяют память из уже выделенных страниц, то ес-но никаких тормозов в момент чтения\записи не будет. Поэтому для корректного сравнения Virtual vs Heap нужно еще пробежаться по выделенной памяти и прочитать по одному дворду из каждой страницы - тогда получим более объективную картину общих затрат времени. При таком сравнении функции кучи будут работать существенно быстрее Virtual при вторичном выделении памяти из уже инициализированных страниц и немного медленее Virtual, если они обращаются к VirtualAlloc. Если же сравнивать только время вызова, то хиповые функции при обращении к Virtual могут давать существенно худшие результаты, т.к. они могут записывать в выделенную страницу служебные данные, вызывая #PF "внутри себя". 4) Делать какие-то обобщения насчет "до 1К" или "более 10К" тут не просто и не совсем корректно, т.к. все это зависит от состояния кучи, ее фрагментации - для "чистой" кучи можем иметь один результат, а для "грязной" другой. Дело в том, что менеджеры кучи предпочитают делать DECOMMIT только при освобождении памяти в хвосте кучи, если же освобождается большой кусок памяти в середине кучи (между двумя занятыми блоками), то он может оставаться COMMIT и затем использоваться для вторичных выделений без всяких #PF - это м.б. и 10К и 100К (до некторого MAX, более которого память всегда выделяется через VirtualAlloc, в винде это ~512К)
> "А мануалы какие следует курить?" Как я уже пояснил, "скорость выделения памяти" VirtualAlloc'ом определяется принципом работы менеджера виртуальной памяти. Достаточно хорошо эти принципы описаны например в "The Virtual-Memory Manager in Windows NT" by Randy Kath (есть в MSDN или например тут). Да и в MSDN неплохо бы заглянуть в Memory Management Overview и в описание функции VirtualAlloc, где однозначно сказано, что физическая память под commited страницу выделяется только при первой попытке чтения или записи в нее. Что касается времени обработки отказа страницы, то там же есть статейка по оптимизации кода на MS VC (by Martin Heller) с наглядной, но видимо "умозрительной" диаграммой сравнительных задержек чтения при попадании\непопадании в кэш и отказов страниц без подкачки и с подкачкой данных с диска. Но лучше проверить и убедиться самому: делаешь pMem:=VirtualAlloc и сравниваешь число тиков на первое чтение i:=pInteger(pMem)^ и на любое последующее из той же страницы i:=pInteger(pMem+X)^, 0 < X < 4092