Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Можно ли вычистить XML из памяти? (http://www.flasher.ru/forum/showthread.php?t=182808)

mikhailk 03.08.2012 15:12

Можно ли вычистить XML из памяти?
 
Собственно, несложный тест показывает, что присвоение null ничего не дает:

Код AS3:

package 
{
        import flash.display.Sprite;
        import flash.events.Event;
        import flash.system.*;
 
        public class Main extends Sprite
        {
 
                private var testXML:XML;
 
                public function Main():void
                {
                        if (stage) init();
                        else addEventListener(Event.ADDED_TO_STAGE, init);
                }
 
                private function init(e:Event = null):void
                {
                        removeEventListener(Event.ADDED_TO_STAGE, init);
                        // entry point
 
                        checkMemory("before init testXML:");
                        testXML = generateXML();
                        checkMemory("after init testXML:");
                        testXML = null;
                        checkMemory("after testXML=null:");
 
                }
 
                private function checkMemory(label:String) : void
                {
                        System.gc();
                        trace("Main::checkMemory", label, System.totalMemory);
                }
 
                private function generateXML() : XML
                {
                        var xml:XML = new XML();
                        for (var i:int = 0; i < 1000; i++)
                        {
                                var child:XML = XML('<random/>');
                                child.@value = Math.random();
                                xml.appendChild(child)
                        }
                        return xml;
                }
 
        }
 
}

Вывод:

Код:

Main::checkMemory before init testXML: 3375104
Main::checkMemory after init testXML: 3641344
Main::checkMemory after testXML=null: 3641344


expl 03.08.2012 16:59

Цитата:

Note: Flash Player 10.1 and AIR 1.5.2 introduce a new method called disposeXML() on the System class. This method allows you to make an XML object immediately available for garbage collection, by passing the XML tree as a parameter.
Не?
http://help.adobe.com/en_US/as3/mobi...7189-7ffc.html

mikhailk 03.08.2012 18:07

Это, конечно, удивительно, но замена присвоения нулла на System.disposeXML(testXML) не дала ничего. :)

Добавлено через 43 секунды
Код:

Main::checkMemory before init testXML: 3371008
Main::checkMemory after init testXML: 4550656
Main::checkMemory after System.disposeXML(testXML): 4550656

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

zuxul 03.08.2012 18:54

Попробуйте проверять количество памяти через несколько "фреймов". Кто его знает, как устроен сборщик мусора, может он делает это поэтапно...
Вот тут, нужно покликать по черному квадрату, чтобы запустить gc.
Если закомментировать disposeXML, и присвоение null, памяти больше занимает.
Код AS3:

package {
  import flash.display.Sprite;
  import flash.events.Event;
  import flash.events.MouseEvent;
  import flash.events.TimerEvent;
  import flash.net.URLLoader;
  import flash.net.URLRequest;
  import flash.system.System;
  import flash.utils.Timer;
 
  /**
  * @author zu
  */

  public class Main extends Sprite {
 
    public function Main():void {
      if (stage) init();
      else addEventListener(Event.ADDED_TO_STAGE, init);
    }
 
        private var data:XML;
 
    private function init(e:Event = null):void {
          var loader:URLLoader = new URLLoader();
          loader.addEventListener(Event.COMPLETE, loadComplete);
          loader.load(new URLRequest('test.xml'));
 
          var sprite:Sprite = new Sprite();
          sprite.graphics.beginFill(0);
          sprite.graphics.drawRect(0, 0, 200, 200);
          sprite.graphics.endFill();
          addChild(sprite);
          sprite.addEventListener(MouseEvent.CLICK, testMemoryListener);
    }
 
        private function testMemoryListener(e:Event):void {
                System.gc();
                trace(System.totalMemory);
                if (data) {
                        System.disposeXML(data);
                        data = null;
                }
        }
 
        private function loadComplete(e:Event):void {
 
                data = new XML(URLLoader(e.currentTarget).data);
                e.currentTarget.removeEventListener(e.type, arguments.callee);
        }   
  }
}


mikhailk 04.08.2012 00:14

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

Код AS3:

package 
{
        import flash.display.BitmapData;
        import flash.display.Sprite;
        import flash.events.Event;
        import flash.events.MouseEvent;
        import flash.system.*;
        import flash.utils.*;
 
        public class Main extends Sprite
        {
 
                private var testXML:XML;
                private var testBitmapData:BitmapData;
 
                public function Main():void
                {
                        if (stage) init();
                        else addEventListener(Event.ADDED_TO_STAGE, init);
                }
 
                private function init(e:Event = null):void
                {
                        removeEventListener(Event.ADDED_TO_STAGE, init);
                        // entry point
 
                        checkMemory("before init testXML:");
 
                        testXML = generateXML();
                        checkMemory("after init testXML:");
 
                        System.disposeXML(testXML);
                        System.gc();
                        checkMemory("after disposeXML(testXML) immediately:");
 
                        setTimeout(checkAfterTimeout, 1000);
                }
 
                private function checkMemory(label:String) : void
                {
                        trace("Main::checkMemory", label, System.totalMemory/1024);
                }
 
                private function checkAfterTimeout() : void
                {               
                        checkMemory("after disposeXML(testXML) and timeout:");
                }
 
                private function generateXML() : XML
                {
                        var xml:XML = new XML();
                        for (var i:int = 0; i < 10000; i++)
                        {
                                var child:XML = XML('<random/>');
                                child.@value = Math.random();
                                xml.appendChild(child)
                        }
                        return xml;
                }
 
        }
 
}

Вывод:

Код:

Main::checkMemory before init testXML: 3336
Main::checkMemory after init testXML: 4384
Main::checkMemory after disposeXML(testXML) immediately: 4384
Main::checkMemory after disposeXML(testXML) and timeout: 3620


alatar 04.08.2012 14:09

Полностью. У вас там еще таймер в памяти добавился и его событие.

mikhailk 04.08.2012 20:31

Вот как бы нет.

Код AS3:

package 
{
        import flash.display.BitmapData;
        import flash.display.Sprite;
        import flash.events.Event;
        import flash.events.MouseEvent;
        import flash.events.TimerEvent;
        import flash.system.*;
        import flash.utils.*;
 
        public class Main extends Sprite
        {
 
                private var testXML:XML;
                private var testBitmapData:BitmapData;
                private var timer:Timer;
 
                public function Main():void
                {
                        if (stage) init();
                        else addEventListener(Event.ADDED_TO_STAGE, init);
                }
 
                private function init(e:Event = null):void
                {
                        removeEventListener(Event.ADDED_TO_STAGE, init);
                        // entry point
 
                        checkMemory("before init timer:");
 
                        timer = new Timer(5000, 1)
                        timer.addEventListener(TimerEvent.TIMER, checkAfterTimeout);
 
                        checkMemory("after init timer:");
 
                        testXML = generateXML();
                        checkMemory("after init testXML:");
 
                        System.disposeXML(testXML);
                        System.gc();
                        checkMemory("after disposeXML(testXML) immediately:");
 
                        timer.start();
                }
 
                private function checkMemory(label:String) : void
                {
                        trace("Main::checkMemory", label, System.totalMemory/1024);
                }
 
                private function checkAfterTimeout(e:Event) : void
                {               
                        checkMemory("after disposeXML(testXML) and timeout:");
                }
 
                private function generateXML() : XML
                {
                        var xml:XML = new XML();
                        for (var i:int = 0; i < 10000; i++)
                        {
                                var child:XML = XML('<random/>');
                                child.@value = Math.random();
                                xml.appendChild(child)
                        }
                        return xml;
                }
 
 
 
        }
 
}

Код:

Main::checkMemory before init timer: 3336
Main::checkMemory after init timer: 3356
Main::checkMemory after init testXML: 4416
Main::checkMemory after disposeXML(testXML) immediately: 4416
Main::checkMemory after disposeXML(testXML) and timeout: 3628

Добавлено через 9 минут
Кстати, если процедуру генерации слегка изменить:

Код AS3:

 
                private function generateXML() : XML
                {
                        var xml:XML = <testXML/>;
                        for (var i:int = 0; i < 10000; i++)
                        {
                                var child:XML = <random/>;
                                child.@value = Math.random();
                                xml.appendChild(child)
                        }
                        return xml;
                }

Выходит:

Код:

Main::checkMemory before init timer: 3336
Main::checkMemory after init timer: 3356
Main::checkMemory after init testXML: 4816
Main::checkMemory after disposeXML(testXML) immediately: 4816
Main::checkMemory after disposeXML(testXML) and timeout: 4852


GBee 05.08.2012 00:03

Один из клиентов ругался на рост пожираемой памяти. Выяснили, что хмл не убивается, а они у нас от 16 метров и больше. Пришлось переходить на 11 плеер. disposeXML разрушает хмл и этот "мусор" дальше ждет GC. Сейчас использую disposeXML и http://silin.su/#AS3/utils/gc в проекте (работает), жду пока откажемся от хмл.

mikhailk 05.08.2012 14:32

Да, адобовцы свинью подложили еще ту.
Работать с xml реально удобно, но то, что он столько памяти на себя берет - это какая-то жесть.

GBee 06.08.2012 13:25

Адобовцы не виноваты :о) Говорил с прогерами других направлений (сишники разные), говорят, что хмл и им мозги повыел.


Часовой пояс GMT +4, время: 15:36.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.