BitmapData.rect создает новый прямоугольник? - PullRequest
1 голос
/ 15 июля 2011

Сегодня я работал над небольшим кодом и после профилирования обнаружил, что я создаю тысячи новых прямоугольников.Я был шокирован, потому что у меня было только 1 или 2 разных новых вызова Rectangle (), или я использовал свойство .rect BitmapData.

Я начал комментировать огромные фрагменты кода, пока я не остался с этим кодом в моемкласс спрайта: canvas.bitmapData.copyPixels(_bitmapData, _bitmapData.rect, destination, null, null, true);

Я кэшировал результат _bitmapData.rect при создании объекта, и моя тысяча новых вызовов прямоугольника внезапно пропала из профилировщика.

Почему, черт возьми, BitmapData.rectсоздать новый прямоугольник?Есть ли способ проверить основные библиотеки или что-то еще и подтвердить, что это правда?Это кажется сбивающим с толку.

Ответы [ 4 ]

1 голос
/ 15 июля 2011

Бетани Энн сказала:

Почему, черт возьми, BitmapData.rect создаст новый прямоугольник?Есть ли способ проверить основные библиотеки или что-то еще и подтвердить, что это правда?Это выглядит странно.

Представьте себе следующую гипотетическую ситуацию, когда BitmapData.rect всегда возвращает один и тот же экземпляр Rectangle:

public function BitmapDataRectTest()
{
    var bmp:BitmapData = new BitmapData(100, 100, true, 0);

    var rect1:Rectangle = bmp.rect;
    rect1.width = 200;

    var rect2:Rectangle = bmp.rect;
    trace(rect2.width); // 200 <--- this would be wrong, 
                        //          the BitmapData is still only 100 pixels wide.
}

BitmapData.rect каждый раз возвращает новый экземпляр, чтобы избежать этогои убедиться, что вы получаете правильные данные в возвращенном экземпляре Rectangle.

Последнее замечание: это относится к «передаче по значению» (типам примитивов) и «передаче по ссылке»(сложный тип) переменные.Для получения дополнительной информации проверьте Google или другие сообщения на stackoverflow: Передать по ссылке или передать по значению?

0 голосов
/ 15 июля 2011

Да, это звучит обескураживающе, но если вы посмотрите на исходный код класса BitmapData, вы обнаружите это:

public class BitmapData extends Object implements IBitmapDrawable {
...
    public function get rect() : Rectangle {
        return new Rectangle(0, 0, this.width, this.height);
    }
...
}

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

0 голосов
/ 15 июля 2011

Интересное наблюдение.

Вы можете использовать оператор ===, чтобы проверить, совпадают ли два экземпляра любого Object.

Вероятно, BitmapData внутренне использует разные данныеструктуры для поддержания своего визуального состояния.Свойство rect должно быть реализовано как функция получения.Однако можно было бы ожидать, что, поскольку размеры BitmapData неизменны, объект Rectangle никогда не нужно будет воссоздавать или даже вообще пересчитывать.

Редактировать: Свойство rect в BitmapData доступно только для чтения (без установщика), однако свойства в Rectangle - нет.Создание нового экземпляра Rectangle гарантирует, что внешние объекты не могут создавать мутации.

0 голосов
/ 15 июля 2011

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

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

Пример:

package
{
    import flash.display.Sprite;
    import flash.display.BitmapData;
    import flash.geom.Rectangle;

    public class BitmapDataRectTest extends Sprite
    {
        public function BitmapDataRectTest()
        {
            var bmp:BitmapData = new BitmapData(100, 100, true, 0);
            trace(bmp.rect == bmp.rect); // false
            var rect1:Rectangle = bmp.rect;
            var rect2:Rectangle = bmp.rect;

            trace("Place breakpoint here and look at rect1 and rect2 memory addresses");
            // rect1 address on my pc: @6900f71
            // rect2 address on my pc: @6900f41
        }
    }
}

РЕДАКТИРОВАТЬ Подобное поведение в нативных классах:

  • DisplayObject.transform: возвращает новый экземпляр Transform при каждом доступе
  • Transform.colorTransform: возвращает новый экземпляр ColorTransform при каждом доступе
  • DisplayObject.filters: возвращает новый экземпляр Array при каждом доступе
  • ... вы можете найти множество других случаев, когда вы получаете копию внутреннего объекта.

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

...