Есть такое желание: получить максимально быстро кусок памяти, причём памяти быстрой (в смысле чтения/записи). Такие вещи, как VirtualAlloc нежелательны, т.к. выделяют память (с последующей очисткой) долго, порядка 3000 тактов. Остается два способа: .data? и стек. .data? вроде неограничен в размерах, но медленней, а стек быстрее, но как из него выдавить порядка 16 кБ - не знаю До 10 кБ вроде устойчиво работает sub esp,10000 mov [esp+5000],eax add esp,10000 а больше - падает. Равно как и LOCAL var[10000] :BYTE. Можно ли снять это ограничение? Без всякого рода апи. Пытался ключем /F 10000 - безуспешно.
BSS, который .data?, ничем существенно не отличается от VirtualAlloc. Макрос LOCAL складывает размеры всех локальных переменных и вычитает результат из esp, т.е. генерирует sub esp,10000. PS: А хип (HeapAlloc) юзать не пробовали?
Asterix Видел эти ссылки, но там мало памяти, а проходить через исключения и получать новую страницу - долго. Экзотические способы вроде CreateThread - совсем медленно Quantum Цепочка invoke GetProcessHeap mov ebx,eax invoke HeapAlloc,ebx,HEAP_ZERO_MEMORY,16384 invoke HeapFree,ebx,HEAP_NO_SERIALIZE,eax это ещё медленней, чем VirtualAlloc. Так что, получается, максимум устойчивого стека - две страницы?
cresta Не очищая память все равно не выйдет. Даже на стеке - когда стек будет расширяться память должна быть очищена. Почему? Потому что это не секюрно - система должна или очистить память или быть уверена что она никогда не использовалась на запись, потому что там может остаться что угодно - в том числе и пароли. Если такой подход не нравится - придется патчить систему или если линукс - подправить кернел =).
Quantum HEAP_ZERO_MEMORY - это как индикатор, была сделана запись в ячейку или нет, без этого флага быстро получается, но потом надо самому забивать память. Чуть быстрее, но не принципиально. semen Не понял, если выходим из процедуры, add esp,... достаточно ведь, зачем ещё что-то? Стек нам никто чистым не предоставляет, так чего его за собой чистить? Пусть система считает, что это от её предыдущего выделения остался мусор Видимо придётся таки в .data? кусок брать. Чуть медленней работать, но получаешь мгновенно.
.data? -- лучшее, что можно предложить. Стек может быть ограничен в размере. А .data? (bss) может быть очень большой. Выделяет эту память винда, освобождает при завершении проги тоже... халява! Если нужна скорость, то можно пробежаться по страницам и сделать pagein. Для особо тяжелых случаев можно заблокировать эту память, чтобы винда ее в своп не скинула.
Вот ссылки по теме: Сколько памяти, максимально, можно выделить в стеке под текстовый буфер? Размер стека http://www.rsdn.ru/article/baseserv/stack.xml
Если размер памяти большой (20Mb и более) то лучше использовать секцию ниинициализированных данных в PE. Каков максимально допустимый размер такой секции - сложно сказать, вполне возможно, что начиная с какого-то значения будут проблемы с запуском на некоторых версиях виндоса/конфигурациях системы. Если памяти нужно меньше - можно использовать стэк, предварительно (например, при старте проги) пробежаться по всем 4K страницам, что бы случаем exception не выскочил.
Asterix Третью ссылку я до этого не видел, но там подмена опять таки через вызовы апи, а это время _BC_, S_T_A_S_ Мне в принципе много не надо (порядка 16 кб), главное, чтобы под рукой всегда было. При запуске подергать за страницы тоже не удастся - код будет в либе, а вызывать фунцию, которая только этим и занималась бы при запуске (типа init_lib_memory) - не знаю, нужно ли это. Видимо .data? остается как единственный приемлимый вариант. Спасибо всем.
Для 16 кб - стэк как раз самое то Он всегда под рукой и не имеет проблем как у глобальных данных. добавить в точку входа Код (Text): mov ecx, 16384/4 mov eax, esp repeat: push 0 loop repeat xchg esp, eax хотя лучше код немного увеличить и обращаться не к каждому dword, а только к страницам.
cresta add esp,... не достаточно - еще нужна защита от переполнения (тест чтобы не перелететь stack guard page). Иначе зачем С crt вызывает __chkstk при больших аллокациях стека? Чтобы обратиться к каждой новой странице стека и обработчик исключения уже непосредственно аллокирует страницы (сразу весь дефолтный мегабайт стека ведь не выделяется). Если система просто будет аллокировать память - я создам много тредов с большим стеком и буду в нем искать пароли от тока что закрывшегося админского процесса из под обычного юзера. Можно и не обнулять - но быть уверенным что никакой процесс сюда данные не записывал НАДО. А секции все равно инициализируются нулями при старте процесса - так что тоже самое что и VirtualAlloc.
S_T_A_S_ Это кусок пожрал 16000 тактов Вся процедура, которой нужна эта память, примерно столько работает. Видимо винда со своим диспетчером памяти вклинилась semen ну её к чёрту, эту винду с её маниакальной секретностью
cresta Линукс такой-же секретный. Но его поправить легче... Например недавно найденная дыра в линукс + хипертрединг как раз и заключалась в возможности прочитать память другого процесса из-за данной реализации поддержки хипертрединга в кернеле (если мне память не изменяет).
w2ksp4: VirtualAlloc(MEM_COMMIT) ~1500 на 16Кб HeapAlloc(HEAP_NO_SERIALIZE) ~5000 на 16Кб HeapAlloc(HEAP_ZERO_MEMORY) ~30000-60000 на 16Кб Надо мерять разные способы, и определять будет ли вся выделенная память в L1 или делать префетч самому
bogrus мерял конечно: VirtualAlloc(MEM_COMMIT) ~3200 HeapAlloc(HEAP_NO_SERIALIZE) ~400 HeapAlloc(HEAP_ZERO_MEMORY) ~4500 Похоже, альтернативы неинициализированной секции нет
cresta > Этот кусок не расчитан на скорость, поскольку на каждые 4K делается 999 лишних итераций цикла Да я и не пойму, зачем ему скорость - он вызывается один раз при старте проги.
Компилятор вот так делает: Код (Text): push ebp mov ebp, esp and esp, 0FFFFFFF8h mov eax, 12ECh test_pages: sub esp, 1000h sub eax, 1000h test [esp], eax cmp eax, 1000h ja short test_pages sub esp, eax
S_T_A_S_ Даже один раз не хочется делать Если при запуске делать, то можно тот же VirtualAlloc сделать, и держать эту память до конца работы программы. А так хотелось найти уже готовое место, на халяву