Как настроить Visual Studio 13, чтобы не тратить много памяти

Обновлено: 21.11.2024

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

Несмотря на то, что вы можете в любое время собирать снимки памяти с помощью инструмента «Использование памяти», вы можете использовать отладчик Visual Studio, чтобы контролировать выполнение приложения при исследовании проблем с производительностью. Установка точек останова, пошагового выполнения, прерывания всего и других действий отладчика может помочь вам сосредоточить исследования производительности на наиболее релевантных путях кода. Выполнение этих действий во время работы приложения может устранить шум в коде, который вас не интересует, и значительно сократить время, необходимое для диагностики проблемы.

В этом руководстве вы:

  • Создание снимков памяти
  • Анализ данных об использовании памяти

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

Поддержка настраиваемого распределителя. Собственный профилировщик памяти работает, собирая данные о событиях ETW выделения, созданные во время выполнения. Распределители в CRT и Windows SDK аннотированы на исходном уровне, чтобы можно было зафиксировать данные об их распределении. Если вы пишете свои собственные распределители, то любые функции, возвращающие указатель на недавно выделенную память кучи, могут быть украшены __declspec(allocator), как показано в этом примере для myMalloc:

__declspec(распределитель) void* myMalloc(size_t size)

Сбор данных об использовании памяти

Откройте проект, который вы хотите отлаживать, в Visual Studio и установите точку останова в своем приложении в точке, с которой вы хотите начать проверку использования памяти.

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

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

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

Окно «Средства диагностики» появляется автоматически, если вы не выключили его. Чтобы снова открыть это окно, нажмите «Отладка» > «Windows» > «Показать инструменты диагностики».

Выберите «Использование памяти» с помощью параметра «Выбор инструментов» на панели инструментов.

Нажмите "Отладка"/"Начать отладку" (или "Пуск" на панели инструментов или F5).

Когда приложение завершит загрузку, появится сводка инструментов диагностики.

Поскольку сбор данных о памяти может повлиять на производительность отладки ваших собственных или смешанных приложений, моментальные снимки памяти по умолчанию отключены. Чтобы включить моментальные снимки в собственных или смешанных приложениях, запустите сеанс отладки (сочетание клавиш: F5). Когда появится окно «Средства диагностики», выберите вкладку «Использование памяти», а затем выберите «Профилирование кучи».

Остановить (сочетание клавиш: Shift+F5) и перезапустить отладку.

Чтобы сделать снимок в начале сеанса отладки, выберите «Создать снимок» на сводной панели инструментов «Использование памяти». (Здесь также может помочь установить точку останова.)

Чтобы создать основу для сравнения памяти, рассмотрите возможность создания моментального снимка в начале сеанса отладки.

Запустите сценарий, который приведет к срабатыванию первой точки останова.

Когда отладчик остановлен в первой точке останова, выберите «Создать снимок» на сводной панели инструментов «Использование памяти».

Нажмите F5, чтобы запустить приложение до второй точки останова.

Теперь сделайте еще один снимок.

С этого момента вы можете приступить к анализу данных.

Анализ данных об использовании памяти

В строках сводной таблицы "Использование памяти" перечислены снимки, сделанные во время сеанса отладки, и приведены ссылки на более подробные представления.

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

Чтобы проанализировать использование памяти, нажмите на одну из ссылок, которая откроет подробный отчет об использовании памяти:

  • Чтобы просмотреть сведения о различиях между текущим снимком и предыдущим снимком, выберите ссылку изменения слева от стрелки (). Красная стрелка указывает на увеличение использования памяти, а зеленая стрелка на уменьшение.

Чтобы быстрее выявлять проблемы с памятью, отчеты о различиях сортируются по типам объектов, общее число которых увеличилось больше всего (нажмите на ссылку изменения в столбце "Объекты (Diff)") или которые больше всего увеличили общий размер кучи (нажмите кнопку изменить ссылку в столбце Размер кучи (Diff)).

Чтобы просмотреть сведения только о выбранном снимке, щелкните ссылку без изменений.

Отчет появится в отдельном окне.

Отчеты по управляемым типам

Выберите текущую ссылку на ячейку «Объекты» (Diff) или «Выделения (Diff)» в сводной таблице «Использование памяти».

В верхней панели отображается количество и размер типов в моментальном снимке, включая размер всех объектов, на которые ссылается тип (включая размер).

В дереве объектов, на которые есть ссылки, отображаются ссылки, относящиеся к типу, выбранному на верхней панели.

Чтобы отобразить экземпляры выбранного типа на верхней панели, выберите значок.

В представлении «Экземпляры» на верхней панели отображаются экземпляры выбранного объекта в моментальном снимке. На панели «Пути к корню и объектам, на которые есть ссылки» отображаются объекты, которые ссылаются на выбранный экземпляр, и типы, на которые ссылается выбранный экземпляр. Когда отладчик остановлен в точке, где был сделан снимок, вы можете навести указатель мыши на ячейку «Значение», чтобы отобразить значения объекта во всплывающей подсказке.

Отчеты собственного типа

Выберите текущую ссылку на ячейку "Распределение" (Diff) или "Размер кучи" (Diff) в сводной таблице "Использование памяти" в окне "Средства диагностики".

В представлении «Типы» отображается количество и размер типов в снимке.

Выберите значок экземпляров ( ) выбранного типа, чтобы отобразить информацию об объектах выбранного типа в снимке.

В представлении «Экземпляры» отображаются все экземпляры выбранного типа. При выборе экземпляра отображается стек вызовов, который привел к созданию экземпляра, на панели стека вызовов распределения.

Выберите «Просмотр стеков» в списке «Режим просмотра», чтобы просмотреть стек распределения для выбранного типа.

Отчеты об изменениях

Выберите ссылку изменения в ячейке сводной таблицы на вкладке «Использование памяти» в окне «Средства диагностики».

Выберите снимок в списке «Сравнить с» управляемого или собственного отчета.

Отчет об изменениях добавляет в базовый отчет столбцы (отмеченные знаком (Diff)) и показывающие разницу между базовым значением моментального снимка и сравнительным снимком. Вот как может выглядеть отчет о различиях в представлении нативного типа:

Блоги и видео

Дальнейшие шаги

Из этого руководства вы узнали, как собирать и анализировать данные об использовании памяти. Если вы уже ознакомились с профилировщиком, возможно, вы захотите узнать, как анализировать загрузку ЦП в ваших приложениях.

Обновление. Обратите внимание, что этот пост был обновлен для Visual Studio 2013 RTM и является первым из двух частей. На снимках экрана и в примерах функции «Только мой код» и «Свернуть мелкие объекты» отключены, как описано в части 2. Перед прочтением части 2 рекомендуется прочитать этот пост.

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

Прежде чем я начну, следует отметить несколько моментов, касающихся функции «Отладка управляемой памяти», обсуждаемой в этом посте:

Зачем беспокоиться о проблемах с памятью

Если в приложении возникают проблемы с памятью, конечные пользователи могут столкнуться с тремя распространенными симптомами.

  1. Приложение может аварийно завершить работу с исключением "Недостаточно памяти". Это относительно распространенная проблема для 32-разрядных приложений, поскольку они ограничены только 4 ГБ общего виртуального адресного пространства. Однако это менее распространено для 64-разрядных приложений, поскольку операционная система устанавливает для них гораздо более высокие ограничения на виртуальное адресное пространство.
  2. Приложение начнет демонстрировать низкую производительность. Это может произойти из-за частого запуска сборщика мусора и конкуренции за ресурсы ЦП с приложением или из-за того, что приложению постоянно требуется перемещать память между ОЗУ (физической памятью) и жестким диском (виртуальная память); который называется пейджингом.
  3. Другие приложения, работающие на том же компьютере, демонстрируют низкую производительность. Поскольку и ЦП, и физическая память являются системными ресурсами, если приложение использует большое количество этих ресурсов, другие приложения останутся с недостаточным объемом и будут демонстрировать отрицательную производительность.

Сбор данных

Следующее, что я собираюсь сделать, это пять раз обновить домашнюю страницу, чтобы проверить логику загрузки страницы. После этого я вижу, что моя память увеличилась с ~ 3,5 МБ до ~ 13 МБ, поэтому это, похоже, указывает на то, что у меня могут быть проблемы с памятью моего приложения, поскольку я не ожидал, что несколько загрузок страниц одним и тем же пользователем приведут к значительное увеличение объема памяти.

Для этого примера я собираюсь захватить дамп iisexpress.exe с помощью ProcDump и назвать его «iisexpress1.dmp» (обратите внимание, что мне нужно использовать флаг –ma для захвата памяти процесса, иначе я не буду уметь анализировать память). Вы можете прочитать об альтернативных инструментах для захвата дампов в разделе Что такое дамп и как его создать?

Теперь, когда у меня есть базовый снимок, я собираюсь обновить страницу еще 10 раз. После дополнительных обновлений я вижу, что использование моей памяти увеличилось до ~ 21 МБ. Поэтому я снова воспользуюсь procdump.exe для создания второго дампа, который я назову «iisexpress2.dmp»

Теперь, когда мы собрали файлы дампа, мы готовы использовать Visual Studio для выявления проблемы.

Анализ файлов дампа

Первое, что нам нужно сделать, чтобы начать анализ, — это открыть файл дампа. В этом случае я выберу самый последний файл дампа «iisexpress2.dmp».

Начнется анализ

После завершения анализа я вижу совершенно новое представление анализа управляемой памяти Visual Studio 2013. Окно содержит две панели, верхняя панель содержит список объектов в куче, сгруппированных по имени их типа, со столбцами, показывающими их количество и общий размер. Когда на верхней панели выбран тип или экземпляр, на нижней панели отображаются объекты, ссылающиеся на этот тип или экземпляр, которые предотвращают его сборку мусора.

[Примечание: на данный момент Visual Studio находится в режиме отладки, так как мы фактически отлаживаем файл дампа, поэтому я закрыл окна отладки по умолчанию (отслеживание, стек вызовов и т. д.) на снимке экрана выше.]

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

Повышение эффективности памяти

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

На этом этапе мне нужно перейти к исходному коду моего приложения, чтобы узнать, для чего Пользователь использует Byte[]. Перейдя к определению User в примере проекта, я вижу, что у меня есть член BinaryData, который имеет тип byte[]. Оказывается, когда я извлекаю своего пользователя из базы данных, я заполняю это поле, хотя я не использую эти данные как часть логики загрузки страницы.

public class User: IUser
<

Как настроить Visual Studio 13, чтобы не тратить много памяти
public string Id

public string UserName

public byte[ ] Двоичные данные < получить; задавать; >
>

Который заполняется запросом

Пользователь user = MockDatabase.SelectOrCreateUser(
"выберите * из пользователей, где
userID);

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

Пользователь user = MockDatabase.SelectOrCreateUser(
"выберите идентификатор, имя пользователя из списка пользователей, где
userID);

Поиск утечки памяти

Вторая проблема, которую я хочу исследовать, — это постоянное увеличение объема памяти, указывающее на утечку. Возможность видеть, что изменилось с течением времени, — очень мощный способ найти утечки, поэтому я собираюсь сравнить текущий дамп с первым, который я сделал. Для этого я раскрываю раскрывающийся список «Выбрать базовый план» и выбираю «Обзор…». Это позволяет мне выбрать «iisexpress1.dmp» в качестве базового.

Далее я перейду к классу UserRepository, который я добавил в приложение.

public static class UserRepository
<
//Храним локальную копию недавних пользователей в памяти, чтобы предотвратить лишние запросы к базе данных
static private List m_userCache = new List ();
публичный статический список UserCache >

public static User GetUser(string userID)

//Получение записи из базы данных пользователя
User user = MockDatabase.SelectOrCreateUser(
“выберите идентификатор, UserName from Users where
userID);

//Добавить пользователя в кэш перед возвратом
m_userCache.Add(user);
вернуть пользователя;
>
>

Обратите внимание, что на этом этапе определение правильного исправления обычно требует понимания того, как работает приложение. В случае моего примера приложения, когда пользователь загружает страницу Home, контроллер страницы запрашивает в UserRepository запись базы данных пользователя. Если у пользователя нет существующей записи, создается новая и возвращается в контроллер. В моем UserRepository я создал статический List, который я использую в качестве кеша для хранения локальных копий, поэтому мне не всегда нужно запрашивать базу данных. Тем не менее, статика автоматически получает root-права, поэтому List показывает прямую ссылку на корень, а не на UserRepository.

Возвращаясь к расследованию, обзор логики в моем методе GetUser() показывает, что проблема в том, что я не проверяю кеш перед запросом к базе данных, поэтому при каждой загрузке страницы я Я создаю новый объект Пользователь и добавляю его в кеш. Чтобы решить эту проблему, мне нужно проверить кеш перед запросом к базе данных.

public static User GetUser(string userID)
<
//Проверяем, находится ли пользователь в локальном кеше
var cachedUser = from user in m_userCache
где пользователь .Id == ID пользователя
выбрать пользователя;

if (cachedUser.Count() > 0)
<
return cachedUser.FirstOrDefault();
>
else
<
//Пользователь отсутствует в локальном кеше, получить пользователя из базы данных
User user = MockDatabase.SelectOrCreateUser(
“ выберите * из пользователей, где
userID);

//Добавить пользователя в кэш перед возвратом
m_userCache.Add(user);

Проверка исправления

После внесения этих изменений я хочу убедиться, что проблема исправлена ​​правильно. Для этого я снова запускаю измененное приложение, и после 20 обновлений страницы монитор производительности показывает мне лишь минимальное увеличение объема памяти (некоторые изменения следует ожидать, поскольку мусор накапливается до тех пор, пока он не будет собран).

Для окончательной проверки исправлений я сделаю еще один дамп, и его просмотр показывает, что Byte[] больше не является типом объекта, занимающим больше всего памяти. Когда я расширяю Byte[], я вижу, что самый большой экземпляр намного меньше, чем предыдущие экземпляры размером 1 МБ, и на него не ссылается Пользователь. Поиск по User показывает мне в памяти один экземпляр, а не 20, поэтому я уверен, что устранил обе эти проблемы.

В заключение

Мы рассмотрели простой пример, демонстрирующий, как использовать Visual Studio 2013 для диагностики проблем с памятью с помощью файлов дампа с кучей. Хотя пример был простым, надеюсь, вы видите, как это можно применить к проблемам с памятью, которые возникают у ваших приложений в рабочей среде. Поэтому, если вы столкнулись с ситуацией, когда вам нужно использовать меньше памяти, или вы подозреваете утечку памяти, попробуйте Visual Studio 2013 Ultimate. Не стесняйтесь загружать образец проекта, использованный в этом сообщении блога, и попробовать его самостоятельно. Рекомендуется продолжить чтение части 2 этого поста, посвященной дополнительным функциям.

Если у вас есть какие-либо комментарии/вопросы, я хотел бы услышать их в комментариях ниже или на нашем форуме MSDN.

На примере этого поста

Если вы хотите попробовать образец, который я показал в этом посте, сделайте следующее:

Ваше приложение SampleLeak MVC теперь будет соответствовать приложению, которое я использовал для создания этой записи в блоге

Я установил Android Studio 1.0 RC 2. У меня установлено 4 ГБ ОЗУ, но после запуска Android Studio и эмулятора Android более 90 % физической памяти используется только этими двумя приложениями. Есть ли способ уменьшить это использование памяти? Из-за этой проблемы с памятью я не могу одновременно открывать другие приложения.

Использование Eclipse или Android Studio и эмулятора на компьютере для разработки Windows с 4 ГБ памяти будет очень болезненным. Я настоятельно рекомендую вам либо обновить оперативную память вашего компьютера для разработки (8 ГБ или больше), протестировать на устройстве (вместо эмулятора) или пропустить IDE и выполнять разработку с помощью простого редактора и инструментов командной строки.

Судя по опубликованному вами снимку экрана, вы используете Windows. Но какая версия Windows? Кроме того, поскольку Android Studio все еще находится в зачаточном состоянии, у вас будет много проблем с ним. Если вам не нужна поддержка Gradle, вы всегда можете попробовать Eclipse — среда IDE проверена годами, поэтому она вполне надежна для среды разработки — с точки зрения оперативной памяти.

@PPD: в Windows отключите ненужные службы с помощью инструментов администрирования | Вариант услуг. Перейдите в msconfig и отключите ненужные приложения на вкладке «Автозагрузка». Отключите ненужные визуальные эффекты в Windows. Когда вы запускаете эмулятор Android, включите параметр «Использовать хост-графический процессор», особенно если у вас мощная графическая карта. У меня есть компьютер для разработки Windows 7, и я использую только 2-2,5 ГБ ОЗУ в любой момент времени, включая: Windows 7, Eclipse, Mozilla Firefox (без надстроек) и этапы настройки Windows, которые я только что упомянул. Я также использую Fedora, и она использует даже меньше памяти, чем Windows.

Просто наблюдение: я вижу, у вас открыто несколько вкладок Google Chrome. Вы можете обнаружить, что Firefox использует немного меньше оперативной памяти, поскольку он не использует процесс для каждой вкладки браузера.

13 ответов 13

В настоящее время я запускаю Android Studio на компьютере с Windows 8.1 и 6 ГБ ОЗУ.

Я обнаружил, что отключение VCS в Android Studio и использование внешней программы для управления VCS очень помогло. Вы можете отключить VCS, перейдя в Файл->Настройки->Плагины и отключив следующее:

  • Интеграция с CVS
  • Интеграция с Git
  • GitHub
  • Тестирование Google Cloud
  • Основные инструменты Google Cloud
  • Облачные инструменты Google для Android Studio
  • hg4idea
  • Интеграция с Subversion
  • Интеграция с Mercurial
  • ТестНГ-J

Огромная разница, когда ваш проект настроен с любым репозиторием, таким как svn или github. мое время ожидания выполнения сократилось с >3 минут до

Кажется, это работает и имеет большое значение, хотя я не отключал "Интеграция с Git". В идеале Android Studio должна иметь эти настройки по умолчанию.

Я использовал этот метод для корпуса HP 6005 mini с 4 ГБ оперативной памяти и процессором amd X4. после деактивации всех этих плагинов моя студия Android открылась очень-очень быстро, я не могу поверить. перед запуском студии Android требуется 15 секунд, но теперь она появляется за 1 секунду. спасибо

В моем случае было два основных источника перегрузки памяти: IDE и Gradle:

Android Studio (до 1,5 ГБ)

JVM среды IDE настроена на максимальный размер кучи. Вы можете увидеть это в правом нижнем углу основного интерфейса:

Вы можете уменьшить это, изменив параметры памяти в файле .vmoptions. Например, я изменил максимальный размер кучи на 512 МБ:

К сожалению, я обнаружил, что снижение этого значения увеличивает частоту временных зависаний Android Studio, возможно, для сборки мусора.

Gradle (до 1,5 ГБ)

Gradle также может использовать много оперативной памяти после некоторого времени разработки. Windows просто показывает его как Java(TM) Platform SE Binary:

Это можно исправить, изменив параметры Gradle JVM. Вы можете сделать это для каждого пользователя, отредактировав gradle.properties :

  1. Откройте файл gradle.properties и создайте его, если он не существует:
    • Windows: %USERPROFILE%\.gradle\gradle.properties
    • Linux/Mac: ~/.gradle/gradle.properties

Обновите свойство org.gradle.jvmargs, создав его при необходимости. Я установил это:

Я не заметил никакой разницы в производительности сборки для моего небольшого проекта с максимальным размером кучи, равным 256 МБ ( -Xmx256m ).

Обратите внимание, что вам может потребоваться перезапустить Android Studio, чтобы старый процесс Gradle был уничтожен; в противном случае вы можете запустить оба одновременно.

Эмулятор

Что касается того, что эмулятор занимает много оперативной памяти, на скриншоте видно, что он занимает около 800 МБ. Вы можете выбрать, сколько оперативной памяти выделить эмулятору:

  1. Изменить AVD
  2. Нажмите Показать дополнительные настройки
  3. Уменьшите значение ОЗУ

@Zelphir, какую версию ОС и Android Studio вы используете? Я использую Windows, и в инструкциях говорится, что файл находится под %USERPROFILE% , что зависит от пользователя. Я не очень хорошо разбираюсь в Linux, но в инструкциях для Mac и Linux также говорится, что файл находится в папке ~ , что, как я полагаю, является домашним каталогом пользователя? Если файла нет, возможно, вы можете просто создать его; в упомянутой выше документации говорится: Вместо этого вы можете настроить атрибуты, создав свои собственные .properties или .vmoptions в следующих каталогах. . Не могли бы вы сообщить мне, работает ли это, чтобы я мог обновить ответ?

Отличные предложения! Для Gradle я решил проблему «для всего пользователя», отредактировав ~/.gradle/gradle.properties .

Вы можете ускорить работу с Eclipse или Android Studio, просто следуя этим инструкциям:

  • Использовать/открывать один проект за раз
  • очищать проект после каждого запуска приложения в эмуляторе
  • использовать мобильное/внешнее устройство вместо эмулятора
  • не закрывайте эмулятор после первого использования, каждый раз используйте один и тот же эмулятор для запуска приложения
  • Отключите VCS с помощью File->Settings->Plugins и отключите следующие вещи:
    1.Интеграция с CVS,
    2.Интеграция с Git,
    3.GitHub,
    4.Google. Облачные инструменты для Android Studio
    5.Интеграция с Subversion

Я также использую Android Studio с установленной основной памятью 4 ГБ, но следующие утверждения действительно повышают производительность Android Studio.

Я думаю, что говорить о том, что "i3" является причиной неудач в программном обеспечении, - это полная чепуха!

Мой процессор i3 хочет бросить вызов вашему >i3, вы хотите принять этот вызов? Никто не скажет, что i3 замедляет работу или занимает много памяти.

Android Studio недавно опубликовала официальное руководство для машин с малым объемом памяти: Руководство

Если вы используете Android Studio на компьютере с характеристиками ниже рекомендованных (см. Системные требования), вы можете настроить IDE для повышения производительности на вашем компьютере следующим образом:

Уменьшите максимальный размер кучи, доступный для Android Studio: уменьшите максимальный размер кучи для Android Studio до 512 МБ.

Обновите Gradle и подключаемый модуль Android для Gradle. Обновите Gradle и подключаемый модуль Android для Gradle до последних версий, чтобы использовать преимущества последних улучшений производительности.

Включить режим энергосбережения. Включение режима энергосбережения отключает ряд фоновых операций, интенсивно использующих память и батарею, в том числе выделение ошибок и проверки "на лету", автоматическое завершение кода во всплывающих окнах и автоматическую добавочную фоновую компиляцию. Чтобы включить режим энергосбережения, нажмите «Файл» > «Режим энергосбережения».

Отключите ненужные проверки lint. Чтобы изменить проверку, которую Android Studio запускает в вашем коде, выполните следующие действия. Нажмите «Файл» > «Настройки» (на Mac, Android Studio > «Настройки»), чтобы открыть диалоговое окно «Настройки». На левой панели разверните раздел «Редактор» и нажмите «Проверки». Установите флажки, чтобы выбрать или отменить проверку ворсинок в соответствии с вашим проектом. Нажмите «Применить» или «ОК», чтобы сохранить изменения.

Отладка на физическом устройстве. При отладке на эмуляторе используется больше памяти, чем при отладке на физическом устройстве, поэтому вы можете повысить общую производительность Android Studio, выполняя отладку на физическом устройстве.

Включайте только необходимые сервисы Google Play в качестве зависимостей. Включение сервисов Google Play в качестве зависимостей в ваш проект увеличивает объем необходимой памяти. Включайте только необходимые зависимости для улучшения использования памяти и производительности. Дополнительную информацию см. в разделе Добавление сервисов Google Play в ваш проект.

Уменьшите максимальный размер кучи, доступный для компиляции файла DEX: установите для параметра javaMaxHeapSize для компиляции файла DEX значение 200 м. Дополнительные сведения см. в статье Ускорение сборки за счет настройки ресурсов DEX.

Не включать параллельную компиляцию: Android Studio может компилировать независимые модули параллельно, но если у вас система с малым объемом памяти, вам не следует включать эту функцию. Чтобы проверить этот параметр, выполните следующие действия: Нажмите «Файл» > «Настройки» (на Mac, Android Studio > «Настройки»), чтобы открыть диалоговое окно «Настройки». На левой панели разверните Сборка, Выполнение, Развертывание и щелкните Компилятор. Убедитесь, что флажок "Компилировать независимые модули параллельно" не установлен. Если вы внесли изменения, нажмите "Применить" или "ОК", чтобы изменения вступили в силу.

Включите автономный режим для Gradle. Если у вас ограниченная пропускная способность, включите автономный режим, чтобы Gradle не пытался загрузить отсутствующие зависимости во время сборки. Когда автономный режим включен, Gradle выдаст ошибку сборки, если у вас отсутствуют какие-либо зависимости, вместо того, чтобы пытаться их загрузить. Чтобы включить автономный режим, выполните следующие действия:

Нажмите «Файл» > «Настройки» (на Mac, Android Studio > «Настройки»), чтобы открыть диалоговое окно «Настройки».

На левой панели разверните узел "Сборка", "Выполнение", "Развертывание" и нажмите "Gradle".

Unity — это отличный и простой инструмент для многоплатформенной разработки. Его принципы просты для понимания, поэтому программисты могут быстро и интуитивно приступить к разработке новых продуктов. Однако, если разработчики не будут помнить о некоторых важных вещах, разработка может замедлиться в критические моменты, в том числе, когда проект отходит от первоначального прототипа или приближается к финальной версии.В этой статье независимый инженер-программист Toptal Томас Мацек описывает наиболее распространенные ошибки, о которых разработчикам Unity следует знать при работе над будущими проектами.

Unity — отличный и простой инструмент для разработки на разных платформах. Его принципы просты для понимания, и вы можете интуитивно приступить к созданию своих продуктов. Однако, если некоторые вещи не будут приняты во внимание, они замедлят ваш прогресс, когда вы перейдете к следующему уровню своей работы, поскольку вы переходите от фазы начального прототипа или приближаетесь к финальной версии. В этой статье будут даны советы о том, как преодолеть наиболее распространенные проблемы и как избежать фундаментальных ошибок в ваших новых или существующих проектах. Обратите внимание, что данная статья больше ориентирована на разработку 3D-приложений, но все упомянутое применимо и к 2D-разработке.

Для каждого проекта очень важно определить несколько моментов еще до того, как начнется проектирование приложения и программная часть проекта. В наши дни, когда маркетинг продукта является важной частью всего процесса, также важно иметь четкое представление о том, какой будет бизнес-модель внедряемого приложения. Вы должны быть уверены, для каких платформ вы будете выпускать продукт и какие платформы включены в ваш план. Также необходимо установить минимальные характеристики поддерживаемых устройств (будете ли вы поддерживать более старые недорогие устройства или только более новые модели?), чтобы иметь представление о том, какую производительность и визуальные эффекты вы можете себе позволить. Этот факт влияет на каждую тему в этой статье.

С технической точки зрения необходимо заранее установить весь рабочий процесс создания активов и моделей при их предоставлении программисту, уделяя особое внимание процессу итерации, когда модели потребуют дополнительных изменений и уточнений. . У вас должно быть четкое представление о желаемой частоте кадров и бюджете вершин, чтобы 3D-художник мог знать, в каком максимальном разрешении должны быть модели и сколько вариаций LOD он должен сделать. Также следует указать, как унифицировать все измерения, чтобы иметь согласованный масштаб, и процесс импорта во всем приложении.

То, как будут спроектированы уровни, имеет решающее значение для будущей работы, потому что разделение уровня сильно влияет на производительность. Вопросы производительности всегда должны быть у вас в голове при разработке новых уровней. Не идите с нереалистичными видениями. Всегда важно задавать себе вопрос: «Может ли это быть разумно достигнуто?» В противном случае вам не следует тратить свои драгоценные ресурсы на что-то труднодостижимое (конечно, если это не является частью вашей бизнес-стратегии, чтобы сделать это вашим главным конкурентным преимуществом).

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

Важно правильно установить масштаб. Иногда невозможно правильно установить это в вашем программном обеспечении для 3D-моделирования из-за разных единиц измерения, используемых этими приложениями. Чтобы все было правильно, установите масштабный коэффициент в настройках импорта моделей (оставьте 0,01 для 3dsMax и Modo, установите 1,0 для Maya), и учтите, что иногда вам потребуется повторно импортировать объекты после изменения настройки масштаба. Эти настройки должны гарантировать, что вы можете использовать только базовый масштаб 1,1,1 в своих сценах, чтобы получить согласованное поведение и отсутствие проблем с физикой. Динамическая пакетная обработка также, скорее всего, будет работать корректно. Это правило также следует применять к каждому подобъекту модели, а не только к основному. Когда вам нужно настроить размеры объекта, делайте это в отношении других объектов в приложении для 3D-моделирования, а не в Unity. Тем не менее, вы можете поэкспериментировать с масштабом в Unity, чтобы найти подходящие значения, но для конечного приложения и последовательного рабочего процесса хорошо все подготовить перед импортом в Unity.

Относительно функциональности объектов и их динамических частей — ваши модели должны быть хорошо разделены. Чем меньше подобъектов, тем лучше. Отдельные части объекта на всякий случай, когда они вам нужны, например, для динамического перемещения или вращения, для целей анимации или других взаимодействий. Каждый объект и его подобъекты должны иметь свою точку опоры, правильно выровненную и повернутую относительно своей основной функции. Главный объект должен иметь ось Z, указывающую вперед, а точка поворота должна быть внизу объекта для лучшего размещения на сцене. Используйте как можно меньше материалов для объектов (подробнее об этом ниже).

Все активы должны иметь собственные имена, которые легко описывают их тип и функциональность. Сохраняйте эту последовательность во всех своих проектах.

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

Для этого существует множество различных подходов. Хорошей отправной точкой является сама система компонентов Unity. Сложности могут возникнуть, когда определенным компонентам необходимо взаимодействовать с другими системами приложения. Для этого вы можете использовать интерфейсы, чтобы сделать части вашей системы более абстрактными и повторно используемыми. В качестве альтернативы вы можете использовать подход, управляемый событиями, для реагирования на определенные события извне, либо путем создания системы обмена сообщениями, либо путем регистрации непосредственно в частях другой системы в качестве слушателей. Правильным подходом будет попытка отделить свойства gameObject от логики программы (по крайней мере, что-то вроде принципа модель-контроллер), потому что сложно определить, какие объекты изменяют свои свойства преобразования, такие как положение и вращение. Ответственность за это должен нести исключительно его контролер.

Постарайтесь все хорошо задокументировать. Относитесь к этому всегда так, как будто вы должны вернуться к своему коду через долгое время, и вам нужно быстро понять, что именно делает эта часть кода. Потому что на самом деле вы довольно часто будете добираться до некоторых частей вашего приложения через какое-то время, и это лишнее препятствие для быстрого перехода к проблеме. Но не переусердствуйте. Иногда вполне достаточно соответствующего имени класса, метода или свойства.

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

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

Обновление циклов

Не используйте элементы, требующие высокой производительности, в циклах обновления, вместо этого используйте кэширование. Типичным примером является доступ к компонентам или другим объектам в сцене или интенсивные вычисления в ваших скриптах. Если возможно, кэшируйте все в методах Awake() или измените свою архитектуру на более управляемый событиями подход, чтобы запускать вещи только тогда, когда они необходимы.

Экземпляры

Для объектов, экземпляры которых создаются довольно часто (например, пули в игре FPS), создайте предварительно инициализированный пул из них и просто выберите уже инициализированный пул, когда он вам понадобится, и активируйте его. Затем, вместо того, чтобы уничтожать его, когда он больше не нужен, деактивируйте его и верните в пул.

Визуализация

Используйте отсечение окклюзии или методы LOD, чтобы ограничить отображаемые части сцены. Попробуйте использовать оптимизированные модели, чтобы контролировать количество вершин в сцене. Имейте в виду, что количество вершин — это не просто количество вершин в самой модели, на него влияют и другие факторы, такие как нормали (жесткие края), координаты UV (швы UV) и цвета вершин. Кроме того, количество динамических источников света в сцене сильно повлияет на общую производительность, поэтому старайтесь запекать все заранее, когда это возможно.

Вызовы рисования

Проблемы с перерисовкой

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

Шейдеры

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

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

Необходимо понимать, что, несмотря на то, что сборщик мусора (GC) сам по себе помогает нам быть действительно эффективными и сосредоточиться на важных вещах в программировании, есть несколько вещей, о которых мы должны четко знать. Использование GC не бесплатно. Как правило, нам следует избегать ненужного выделения памяти, чтобы сборщик мусора не срабатывал слишком часто и, таким образом, не снижал производительность скачками частоты кадров. В идеале вообще не должно происходить никаких новых выделений памяти, происходящих регулярно в каждом кадре. Однако как мы можем достичь этой цели? Это действительно определяется архитектурой приложения, но есть несколько правил, которым вы можете следовать:

  • Избегайте ненужных выделений памяти в циклах обновления.
  • Используйте структуры для простых контейнеров свойств, поскольку они не размещаются в куче.
  • Попробуйте предварительно выделить массивы, списки или другие наборы объектов, а не создавать их внутри циклов обновления.
  • Избегайте использования моно проблематичных вещей (например, выражений LINQ или циклов foreach), поскольку Unity использует более старую, не идеально оптимизированную версию Mono (на момент написания это модифицированная версия 2.6, с обновлением в планах) .
  • Кэшировать строки в методах Awake() или в событиях.
  • Если необходимо обновить строковое свойство в цикле обновления, используйте объект StringBuilder вместо строки.
  • Используйте профилировщик для выявления потенциальных проблем.

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

Для поиска поглотителей ресурсов вы можете использовать журнал редактора, где вы можете увидеть (после каждой новой сборки) размер ресурсов, разделенных на отдельные категории, такие как аудио, текстуры и библиотеки DLL. Для лучшей ориентации в Unity Asset Store есть расширения редактора, которые предоставят вам подробную сводку со ссылками на ресурсы и файлы в вашей файловой системе. Фактическое потребление памяти также можно увидеть в профилировщике, но рекомендуется протестировать его при подключении для сборки на вашей целевой платформе, потому что при тестировании в редакторе или на чем-либо другом, отличном от целевой платформы, возникает много несоответствий.

Больше всего памяти часто потребляют текстуры. Желательно использовать сжатые текстуры, так как они занимают гораздо меньше места и памяти. Сделайте все текстуры квадратными, в идеале сделайте длину обеих сторон степенью двойки (POT), но имейте в виду, что Unity также может автоматически масштабировать текстуры NPOT до POT. Текстуры могут быть сжаты в форме POT. Атласные текстуры вместе, чтобы заполнить всю текстуру. Иногда вы даже можете использовать альфа-канал текстуры для дополнительной информации для ваших шейдеров, чтобы сэкономить дополнительное место и производительность. И, конечно же, старайтесь максимально повторно использовать текстуры для своих сцен и используйте повторяющиеся текстуры, когда это возможно, чтобы сохранить хороший внешний вид. Для младших устройств вы можете понизить разрешение текстур в настройках качества. Используйте сжатый аудиоформат для более длинных аудиоклипов, таких как фоновая музыка.

Когда вы имеете дело с разными платформами, разрешениями или локализациями, вы можете использовать наборы ресурсов для использования разных наборов текстур для разных устройств или пользователей. Эти пакеты ресурсов можно динамически загружать из Интернета после установки приложения. Таким образом, вы сможете превысить ограничение в 100 МБ, загружая ресурсы во время игры.

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

Чтобы изменить положение объекта с Rigidbody на нем, всегда устанавливайте Rigidbody.position, если новое положение не следует за предыдущим, или Rigidbody.MovePosition, если это непрерывное движение, которое также учитывает интерполяцию. При его изменении применяйте операции всегда в FixedUpdate , а не в функциях обновления. Это обеспечит последовательное поведение физики.

Если возможно, используйте примитивные коллайдеры на игровых объектах, такие как сфера, коробка или цилиндр, а не коллайдеры сетки. Вы можете составить свой окончательный коллайдер из более чем одного из этих коллайдеров.Физика может быть узким местом производительности вашего приложения из-за накладных расходов ЦП, а коллизии между примитивными коллайдерами вычисляются намного быстрее. Вы также можете настроить параметр «Фиксированный временной шаг» в диспетчере времени, чтобы уменьшить частоту фиксированных обновлений физики, когда точность физического взаимодействия не так важна.

Иногда может возникать тенденция тестировать функциональность вручную, экспериментируя в игровом режиме, потому что это довольно весело, и все находится под вашим непосредственным контролем. Но этот холодный фактор может довольно быстро уменьшиться. Чем сложнее становится приложение, тем больше утомительных задач приходится повторять и обдумывать программисту, чтобы убедиться, что приложение ведет себя так, как было задумано изначально. Он легко может стать худшей частью всего процесса разработки из-за своего повторяющегося и пассивного характера. Кроме того, поскольку ручное повторение сценариев тестирования не так уж весело, существует большая вероятность того, что некоторые ошибки пройдут через весь процесс тестирования.

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

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

Поверьте мне; они не будут. При работе с некоторыми клиентами я иногда сталкивался с тенденцией или пережитками прошлого использования плагинов хранилища активов для каждой мелочи. Я не имею в виду, что в Unity Asset Store нет полезных расширений Unity. Их много, и иногда даже сложно определиться, какой из них выбрать. Но для каждого проекта важно сохранять последовательность, которую можно разрушить из-за неразумного использования разных элементов, которые плохо сочетаются друг с другом.

С другой стороны, для функциональности, на реализацию которой у вас уйдет много времени, всегда полезно использовать хорошо протестированные продукты из Unity Asset Store, которые могут сэкономить вам огромное количество времени на разработку. Тем не менее, выбирайте тщательно, используйте проверенные, которые не принесут много неконтролируемых и странных ошибок в ваш конечный продукт. Пятизвездочные отзывы — хороший показатель для начала.

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

Иногда может показаться, что среды Unity Editor вполне достаточно для базового тестирования игр и дизайна уровней, а расширять ее — пустая трата времени. Но поверьте мне, это не так. Большой потенциал расширения Unity заключается в возможности адаптировать его к конкретным задачам, которые необходимо решать в различных проектах. Это может либо улучшить взаимодействие с пользователем при работе в Unity, либо значительно ускорить весь рабочий процесс разработки и дизайна уровней. Было бы прискорбно не использовать встроенные функции, такие как встроенные или настраиваемые ящики свойств, ящики декораторов, пользовательские настройки инспектора компонентов или даже не создавать целые плагины с собственными окнами редактора.

Заключение

Я надеюсь, что эти темы будут вам полезны по мере продвижения ваших проектов Unity. Есть много вещей, которые специфичны для проекта, поэтому их нельзя применять, но всегда полезно иметь в виду некоторые основные правила при попытке решить более сложные и специфические проблемы. У вас могут быть разные мнения или подходы к решению этих проблем в ваших проектах. Самое важное — поддерживать единообразие идиом во всем проекте, чтобы любой член вашей команды мог четко понять, как следует правильно решить конкретную область.

Читайте также: