c# - leak - scitech.net memory profiler




Игра Unity Board AI, вызывающая утечку памяти (3)

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

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

Если вы исключили, что это одно из двух распространенных заблуждений, обычно утечки памяти в управляемом Runtime означают одно: вы добавляете что-то в коллекцию (массив, список <>, словарь <,>), но забываете вынуть ее снова , Это единственный способ утечки памяти. В частности, GC существует, поэтому мы снова не сталкиваемся с проблемой «Я забыл о свободной памяти».

Редкий случай - это ошибки с Disposing . Если вы передаете непосредственно ресурсы, которые вы используете, вы должны сначала написать свой финализатор, а затем удалить вторую. Если вы обрабатываете anythign, который реализует IDisposeable, всегда также реализуйте IDisposeable, даже если весь ваш Dispose () выполняет ретрансляцию заказа в содержащийся экземпляр. Никогда не передавайте заказ Finalize, то есть между этим экземпляром и GC.

Я создаю настольную игру, похожую на tic tac toe, и я создал AI, чтобы играть в эту игру. AI очень интенсивно работает на CPU, поэтому я решил поместить его в собственный поток. Я использую этот плагин для многопоточности: https://www.assetstore.unity3d.com/ru/#!/content/15717 .

У меня есть этот IEnumerator:

static IEnumerator executeAITurn(Turn turn) {
    Vector2[] move = mctsManager.mcts(new State(sections, null, turn), AIIterations)[0, 0].metaData.lastMove;

    yield return Ninja.JumpToUnity;

    input(move, true);

    yield return Ninja.JumpBack;

    Debug.Log("DONE!");
}

и я запускаю его, используя

gameManager.StartCoroutineAsync(executeAITurn((AITurn == Turn.X) ? Turn.O : Turn.X));

Обычно, когда я запускаю executeAITurn, он работает нормально без проблем, но по какой-то причине иногда, когда я запускаю его, он делает то, что должен, но в диспетчере задач моя память только начинает увеличиваться примерно на 30 мб / сек. Объем памяти увеличивается до 1000 мб, и игра становится очень медленной. Когда я выключаю режим воспроизведения, память иногда продолжает увеличиваться или просто останавливается там, где она есть. Я должен закончить Unity через диспетчер задач, чтобы освободить память.

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

Любая помощь будет оценена по достоинству.

Вот некоторые из кода, участвующих в executeAITurn:

Класс mctsManager: https://pastebin.com/yzeHrY2p

вход Функция: https://pastebin.com/8f2hzZws


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

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

Уточнение: каждый список массива, который у вас есть, если вы знаете точный размер вашего массива, используйте ArrayList. Если вы используете список, переключите его в словарь, если тип списка известен вам или Hash Table, если нет. таким образом, вы сможете получить информацию по ключевому значению, которая быстрее и повышает производительность.

Во-вторых, попробуйте использовать синтаксис Using, когда вы создаете новый объект, это поможет вам реализовать интерфейс iDisposable для более эффективного удаления объектов.

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

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


Это больше похоже на проблему сбора мусора. Я посмотрел ваш код для MCTS и заметил следующее.

    // Use this for initialization
    void Start () {

    }

    // Update is called once per frame
    void Update () {

Это отсутствовало в вашем первом коде, функции ввода C #. В основном, это вызывает функцию обновления. Как вы можете заметить, в нем говорится, что функция обновления вызывается один раз для каждого кадра. См. Этот https://unity3d.com/learn/tutorials/topics/performance-optimization/optimizing-garbage-collection-unity-games

Я бы рекомендовал кэш.

Надеюсь, это поможет.





memory-leaks