AS3 - когда работает сборщик мусора? - PullRequest
6 голосов
/ 31 августа 2010

извинения, если это дурак; я не смог его найти.

Я прочитал и понял блог Гранта Скиннера на сборщике мусора AS3 - http://www.adobe.ca/devnet/flashplayer/articles/garbage_collection.html, но мой вопрос там не рассматривается.

вот мой вопрос.

предположим, я написал код AS3, например:

statementOne;
statementTwo;

есть ли вероятность того, что сборщик мусора будет работать во время или между двумя моими операторами, или он будет работать только после того, как мой "пользовательский" код завершит работу и вернет управление на флэш-память?

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

ТИА, Orion

Ответы [ 6 ]

6 голосов
/ 31 августа 2010

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

Ключевое слово new вызовет сборщик мусора, если ему не хватит памяти.

Вы можете запустить этот код, чтобы наблюдать это поведение:

var vec:Vector.<*> = new Vector.<*>(9001);
for (;;) {
    vec[0] = new Vector.<*>(9001);
    vec = vec[0];
}

Использование памяти быстро увеличится до максимума (для меня 1 ГБ), а затем будет удерживаться до истечения времени.

5 голосов
/ 31 августа 2010

Здесь много хороших ответов, но я думаю, что некоторые тонкости не были учтены.

  1. Flash Player реализует два вида сборки мусора. Одним из них является подсчет ссылок, когда Flash хранит счетчик входящих ссылок на каждый объект и знает, что когда счетчик достигнет нуля, объект может быть освобожден. Второй метод - это разметка, когда Flash время от времени ищет и удаляет изолированные группы объектов (где объекты ссылаются друг на друга, но группа в целом не имеет входящих ссылок).
  2. В соответствии со спецификацией любой вид сборки мусора может происходить в любое время. Игрок не дает никаких гарантий относительно того, когда объекты будут освобождены, и развертки меток могут даже быть распределены по нескольким кадрам. Более того, нет никакой гарантии, что время GC останется неизменным между версиями Flash player, платформами или даже браузерами. Таким образом, в некоторой степени не очень полезно знать что-либо о том, как запускаются GC, поскольку у вас нет возможности узнать, насколько широко применяются ваши знания.
  3. За исключением предыдущего пункта, вообще говоря, разметка меток нечаста и срабатывает только при определенных обстоятельствах. Я знаю о некоторых конфигурациях проигрывателя / ОС, в которых метка / развертка могла запускаться каждые N секунд или всякий раз, когда проигрыватель превышал P% от общей доступной памяти, но это было давно, и детали будут меняться. GC с подсчетом ссылок, напротив, может происходить часто - по крайней мере, между кадрами. Я не думаю, что видел, как они демонстрировали, что это происходит чаще, но это не значит, что это не может произойти (по крайней мере, в определенных ситуациях).

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

С другой стороны, если во время ваших циклов произойдет пометка / развертка, это, несомненно, повлияет на вашу производительность. Но это относительно сложно ошибиться и легко проверить. Если вы тестируете на ПК, а ваше приложение не использует сотни мегабайт памяти (тест с System.totalMemory), вы, вероятно, вообще не получите никакой оценки. Если они у вас есть, должно быть легко проверить, что связанные паузы большие, нечастые и всегда сопровождаются большим падением использования памяти. Если эти вещи не соответствуют действительности, вы можете игнорировать идею, что GC является частью ваших проблем.

1 голос
/ 31 августа 2010

GC не будет работать между двумя операторами, которые находятся в одном стеке / одном кадре, как в вашем примереПамять будет освобождена до выполнения следующего кадра.Так работает большинство современных сред виртуальных машин.

1 голос
/ 31 августа 2010

Насколько мне известно, это не задокументировано.У меня есть ощущение, что GC не будет работать, пока выполняется ваш код (то есть, пока ваш код находится в стеке выполнения; каждый кадр проигрыватель создает новый стек для кода использования).Очевидно, это связано с наблюдением и моим собственным опытом с Flash, поэтому я бы не сказал, что это на 100% точно.Надеюсь, это обоснованное предположение.

Вот простой тест, который, кажется, показывает, что вышеупомянутое верно:

package {
    import flash.display.Sprite;
    import flash.net.FileReference;
    import flash.system.System;
    import flash.utils.Dictionary;
    import flash.utils.setTimeout;

    public class test extends Sprite
    {

        private var _dict:Dictionary = new Dictionary(true);

        public function test()
        {
            testGC();
            setTimeout(function():void { 
                traceCount();
            },2000);            
        }

        private function testGC():void {
            var fileRef:FileReference;
            for(var i:int = 0; i < 100; i++) {
                fileRef = new FileReference();
                _dict[fileRef] = true;
                traceCount();
                System.gc();
            }
        }

        private function traceCount():void {
            var count:int = 0;
            for(var i:* in _dict) {
                count++;
            }
            trace(count);
        }

    }
}

GC кажется особенно жадным, когда есть FileReference объектоввовлечен (опять же, это из моего опыта; насколько я знаю, это не задокументировано).

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

Когда этот счетчик отслеживается снова, вдругой стек выполнения (вызванный асинхронным вызовом setTimeout), все объекты были освобождены.

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

0 голосов
/ 07 мая 2011

Согласно этому Тому из Габоба , достаточно большие сиротские иерархии не собирают мусор.

0 голосов
/ 31 августа 2010

Вы не можете определить, когда GC будет работать. Если вы пытаетесь помешать чему-либо быть GC'd, храните ссылку на это где-нибудь.

...