Почему "Любой процессор (предпочтительный 32-разрядный)" позволяет мне выделять больше памяти, чем x86 в .NET 4.5?
В соответствии со многими ответами SO и это широко цитируемое сообщение в блоге, приложение .NET 4.5, построенное для "Any CPU" с "предпочтительным 32" -бит "будет работать как 32-разрядный процесс как в 32-разрядной, так и в 64-разрядной системах (в отличие от .NET 4.0 и ранее).
Другими словами, x86 и AnyCPU с "предпочтительным 32-битным" выбранным эквивалентом (игнорируя, может ли он запускаться на ARM).
Однако мои тесты показали, что в 64-битной системе приложение AnyCPU предпочитает 32-разрядное приложение (которое я уверен, запускает 32-разрядный) может выделить больше памяти, чем x86. Я написал консольное приложение .NET 4.5 С#, которое выделяет массивы в 10 Мбайт байт в цикле (сохраняя ссылки, конечно), пока не попадет в OutOfMemoryException и не запустит его в 64-разрядной системе с большим количеством ОЗУ. Когда он построен как x86, он падает примерно на 1,2 ГБ. Один и тот же код, построенный как "Любой процессор (предпочтительный 32-разрядный)", достигает 1,5 ГБ.
Почему разница?
Ответы
Ответ 1
Оказывается, что в Visual Studio 2015 создание в виде "AnyCPU (предпочтительно 32-битного)" устанавливает бит IMAGE_FILE_LARGE_ADDRESS_AWARE в исполняемом файле (эквивалентно запуску editbin /LARGEADDRESSAWARE
на нем), тогда как он не для сборки x86, Это можно подтвердить с помощью dumpbin /HEADERS
и поискать строку "Приложение может обрабатывать большие ( > 2 ГБ) адреса".
Это не относится к Visual Studio 2013. Это изменение явно недокументировано.
В теории это должно дать CLR еще 2 ГБ для игры. Я не знаю, почему распределяемая память увеличивается примерно на 300 МБ.
Ответ 2
У меня была такая же проблема, и я хотел оставить x86. Большинство наших приложений зависят от внешних 32-разрядных сборок, и когда разработчики видят любой процессор, они склонны менять его на x86. Я обнаружил, что editbin/largeaddressaware $ (TargetPath) не работает в VS 2017. Поэтому я использовал следующий пакет Nuget и сохранил свой проект на x86.
https://www.nuget.org/packages/LargeAddressAware/ https://github.com/KirillOsenkov/LargeAddressAware
Чтобы использовать, вы добавляете пакет Nuget, а затем помещаете в файл проекта следующее:
<PropertyGroup>
<LargeAddressAware>true</LargeAddressAware>
</PropertyGroup>
Это сработало в моем случае.