AS3: оптимизация объема памяти объекта - PullRequest
1 голос
/ 01 августа 2009

У меня есть класс, который я написал, и он кажется больше, чем должен быть. Он ничего не расширяет, и его очень мало - или так я думал - но каждый занимает чуть меньше 100k 100 байт (спасибо back2dos). Я предполагаю, что у меня нет очень хорошего понимания того, что действительно влияет на то, сколько памяти занимает объект в AS3.

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

Я хотел бы сохранить МНОЖЕСТВО этих объектов в памяти - и я думал, что смогу до сих пор, но при таком размере мне придется создавать их или использовать какую-то технику объединения объектов.

Спасибо за помощь.

Редактировать: Хотя у меня все в порядке, я сохраняю код, который я разместил здесь для полноты. Класс был сильно изменен по сравнению с оригинальной версией. Значения, которые ссылались на другие файлы, были сделаны статическими, чтобы позволить коду запускаться для кого-то другого (в теории хе-хе-хе ...).

Хотя моя ситуация разобрана, я дам ответ на хороший справочник информации о классах и памяти.

В этом случае класс имеет 15 переменных. Я использую только одну строку и кучу целых чисел, чисел и логических значений с некоторыми ссылками на некоторые из них в глобально доступных данных XML. Он также импортирует Point для конструктора, хотя точки не сохраняются. В тестировании, даже без глобальных ссылок XML или класса Point, он по-прежнему составляет около 84 тыс. Каждый. В дополнение к конструктору есть геттеры для 7 переменных и пара методов. Все из которых содержат менее 20 строк (и у меня очень редкий стиль кодирования).

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

package
{
    public class AObject
    {
        private var _counter:int;
        private var _frames:int;
        private var _speed:int;

        private var _currentState:String;
        private var _currentFrame:int;

        private var _offset:int;
        private var _endFrame:int;

        private var _type:int;
        private var _object:int;
        private var _state:int;

        private var _x:Number;
        private var _y:Number;

        private var _w:int;
        private var _h:int;

        private var _update:Boolean;

        public function AObject( targetX : int,  targetY : int,  state : int,  object : int,  type : int )
        {       

            _x = targetX;
            _y = targetY;

            _type = type;
            _object = object;
            _state = state;
            _counter = 0;
            _w = 32;
            _h = 32
            _update = true;
            setState( state );
        }

        public function setState( state:int ) : void
        {
            _currentState = "bob";
            var frameCounter : int = 0;
            var stateCounter : int = state - 1;
            while ( state > 0 )
            {
                frameCounter += 4;
                --stateCounter; 
            }
            _offset = frameCounter;
            _currentFrame = _offset;
            _speed = 10;
            _frames = 4;
            _endFrame = _offset + _frames - 1;
        }

        public function get state() : int
        {
            return _state;
        }

        public function animate() : Boolean
        {
            if ( count() )
            {
                if( _currentFrame < _endFrame )
                {
                    ++_currentFrame;
                }
                else
                {
                    _currentFrame = _offset;    
                }
                _speed = 10;
                return true;
            }
            else
            {
                return false;
            }
        }

        private var adder: Number = 0;

        private function count():Boolean
        {
            _counter++;
            if ( _counter == _speed )
            {
                _counter = 0;
                return true;
            }
            else
            {
                return false;
            }
        }

        public function get x():int
        {
            return _x;
        }

        public function get y():int
        {
            return _y;
        }

        public function get type():int
        {
            return _type;
        }

        public function get object():int
        {
            return _object;
        }

        public function get currentFrame():int
        {
            return _currentFrame;
        }

        public function get w():int
        {
            return _w;
        }

        public function get h():int
        {
            return _h;
        } 
    }
}

Ответы [ 2 ]

3 голосов
/ 01 августа 2009

я поражен, это компилируется вообще ... когда я пытаюсь скомпилировать его с помощью flex SDK, это создает колоссальное столкновение со встроенным классом Object, который является базовым классом любого класса, что делает мой след переполнение выхода ...

кроме этого, это бесконечный цикл, если вы передаете значение для состояния больше 0

while ( state > 0 )
{
        frameCounter += 4;
        --stateCounter; 
}

но кажется странным, что эти объекты такие большие ... после переименования и заботы о том, чтобы не передать 0 для состояния, я запустил тест:

package {
    import flash.display.Sprite;
    import flash.sampler.getSize;
    import flash.system.System;
    public class Main extends Sprite {
        public function Main():void {
            const count:int = 100000;
            var start:uint = System.totalMemory;
            var a:Array = [];
            for (var i:int = 0; i < count; i++) {
                a.push(new MyObject(1, 2, 0, 4, 5));
            }
            var mem:uint = System.totalMemory - start - getSize(a);
            trace("total of "+mem+" B for "+count+" objects, aprox. avg. size per object: "+(mem/count));
        }       
    }   
}

это дает:

total of 10982744 B for 100000 objects, aprox. avg. size per object: 109.82744

так что все в порядке ... я думаю, что фактический размер должен быть 4 (для bool) + 4 * 11 (для целых) + 4 (для ссылки на строку) + 8 * 3 (для трех float (у вас есть adder где-то над count) + 8 для пустого класса (ссылка на объекты признаков + что-то еще), что дает вам в общей сложности 88 байтов ... что вы получите, если Вы getSize объект ... обратите внимание, однако, что getSize даст вам только размер самого объекта (рассчитанный здесь), игнорируя размер строк или других объектов, на которые ссылается ваш объект ...

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

Greetz

back2dos

0 голосов
/ 16 марта 2012

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

ints по своей природе 4 байта, вы можете использовать это int для чего-то меньшего, чем 2 ^ 8.

width    height
0xFFFF + 0xFFFF

offset   endframe
0xFFFF + 0xFFFF

Это, однако, становится уродливым, когда вы хотите что-то написать или прочитать что-либо, для записи ширины или высоты вам потребуется:

writing:
size = (width & 0x0000FFFF) << 16 | (height & 0x0000FFFF);

reading:
get width():uint { return (size & 0xFFFF0000) >> 16 };

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

Кроме того, я полагаю, что вы на самом деле получите некоторое увеличение памяти, объявив класс как final, так как я считаю, что конечные функции помещаются в объект признаков, а не

...