BitmapData.rect creates a new rectangle?

I was working on some blitting code today and after profiling it found that I was creating 1000s of new rectangles. I was shocked because I only had 1 or 2 different new Rectangle() calls or I was using the .rect property of BitmapData.

I started commenting out huge swathes of code until I was left with this code in my sprite class: canvas.bitmapData.copyPixels(_bitmapData, _bitmapData.rect, destination, null, null, true);

I cached the result of _bitmapData.rect at object creation and my thousand of new rectangle calls were suddenly gone from the profiler.

Why the heck would BitmapData.rect create a new rectangle? Is there a way to check the core libraries or something and confirm this is true? It seems baffling.


Bethanny Anne said:

Why the heck would BitmapData.rect create a new rectangle? Is there a way to check the core libraries or something and confirm this is true? It seems baffling.

Imagine the following hypothetical situation where BitmapData.rect always returns the same Rectangle instance:

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 returns a new instance every time to avoid that situation and to make sure you are getting the correct data in the returned Rectangle instance.

Final note: this relates to 'pass-by-value' (primitive types) and 'pass-by-reference' (complex type) variables. For more info check out google or other posts on stackoverflow: Pass by reference or pass by value?


Interesting observation.

You can use the === operator to check if two instances of any Object are the same.

It's likely that BitmapData internally uses different data structures to maintain its visual state. The rect property must be implemented as a getter function. However, one would expect that because the dimensions of BitmapData are immutable, that the Rectangle object would never need to be recreated, or even re-computed at all.

Edit: The rect property on BitmapData is read-only (no setter), however the properties on a Rectangle are not. Creating a new instance of Rectangle ensures that external objects cannot make mutations.


Yes, it sounds discouraging, but if you will take a look at BitmapData class source code you will discover this:

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

So the answer is Yes, AVM creates new instance of Rectangle in the heap every time you retrieve it through accessor-function.

链接地址: http://www.djcxy.com/p/20666.html

上一篇: 为什么指定的对象有资格进行垃圾回收?

下一篇: BitmapData.rect创建一个新的矩形?