Apache flex &引用;“有趣”;Flash/Flex行为:增加绘制10000个三角形的时间

Apache flex &引用;“有趣”;Flash/Flex行为:增加绘制10000个三角形的时间,apache-flex,flash,adobe,Apache Flex,Flash,Adobe,这是一个测试程序,用于测量Flash绘制10000次三角形所需的时间 应用程序(下面的代码)每N秒调用一次runTimeTest(),这将绘制10000次三角形 现在来看“有趣”部分:每次调用占用的处理器越来越多,直到第6次或第7次调用后,它进入“无限”(参见TaskManager的屏幕截图) 奇怪的虫子还是可以解释的 // create a Canvas to draw on var c:Canvas = new Canvas(); function onApplicationComple

这是一个测试程序,用于测量Flash绘制10000次三角形所需的时间

应用程序(下面的代码)每N秒调用一次runTimeTest(),这将绘制10000次三角形

现在来看“有趣”部分:每次调用占用的处理器越来越多,直到第6次或第7次调用后,它进入“无限”(参见TaskManager的屏幕截图)

奇怪的虫子还是可以解释的

// create a Canvas to draw on

var c:Canvas = new Canvas();

function onApplicationComplete(e:Event)
{
    c.width = width;
    c.height = height;

    c.x = 0;
    c.y = 0;

    addChild(c);

    // set up a timer to run every 10 seconds

    var timer:Timer = new Timer(10000);
    timer.addEventListener(TimerEvent.TIMER, runTimeTest);
    timer.start();
}

function runTimeTest(e:Event)
{
    // this is called every 10 seconds

    var x0:int, x1:int, x2:int;
    var y0:int, y1:int, y2:int;

    // set triangle vertices

    x0 = 100; y0 = 500;
    x1 = 120; y1 = 515;
    x2 = 155; y2 = 500;

    // draw a filled triangle 10,000 times

    for (var i:int = 0; i < 10000; ++i)
    {
        c.graphics.beginFill( 0xff0000, 1 );
        c.graphics.moveTo( x0, y0 );

        c.graphics.lineTo( x1, y1 );
        c.graphics.lineTo( x2, y2 );
        c.graphics.lineTo( x0, y0 );

        c.graphics.endFill();
    }
}
//创建要绘制的画布
var c:Canvas=newcanvas();
Application Complete上的函数(e:事件)
{
c、 宽度=宽度;
c、 高度=高度;
c、 x=0;
c、 y=0;
addChild(c);
//设置计时器,使其每10秒运行一次
var定时器:定时器=新定时器(10000);
timer.addEventListener(TimerEvent.timer,runTimeTest);
timer.start();
}
函数运行时测试(e:事件)
{
//每10秒调用一次
变量x0:int,x1:int,x2:int;
变量y0:int,y1:int,y2:int;
//设置三角形顶点
x0=100;y0=500;
x1=120;y1=515;
x2=155;y2=500;
//画一个填充的三角形10000次
对于(变量i:int=0;i<10000;++i)
{
c、 图形填充(0xff0000,1);
c、 图。移动到(x0,y0);
c、 图形。lineTo(x1,y1);
c、 图形。lineTo(x2,y2);
c、 图形。lineTo(x0,y0);
c、 graphics.endFill();
}
}
i34.tinypic.com/jutpwo.png

“如果在运行时测试开始时调用c.graphics.clear()如何?”
詹姆斯·沃德

是的,添加c.graphics.clear()修复了它。
马特

Flash会一直保存所有绘图命令(即图形),直到调用graphics.clear()。这样,您就可以在多个帧上绘制,而无需同时绘制所有内容

绘制三角形的时间越来越长的原因是每次调用runTimeTest()Flash时都需要额外绘制10000个三角形

因此,第一次调用Flash时,它会绘制10000个三角形,第二次调用runTimeTest()时,它必须绘制前10000个三角形(因为尚未清除画布),然后再绘制第二个10000个三角形

正如格伦指出的,解决方案是在绘制每组三角形之前清除画布。这样,Flash只需绘制当前的三角形集。

无论出于何种原因,如果您确实需要在屏幕上绘制大量的项目,您可以利用位图缓存:如果您每次都在不同的画布/精灵上绘制图形,那么Flash只需绘制一次每个图形(其他图形都缓存在幕后的内存中)

e、 g

私有函数drawTriangles():void
{
变量x0:int,x1:int,x2:int;
变量y0:int,y1:int,y2:int;
//设置三角形顶点
x0=100;y0=500;
x1=120;y1=515;
x2=155;y2=500;
//这是重要的部分。
//仅在此新精灵上绘制10000个三角形。
变量c:Sprite=新Sprite();
c、 cacheAsBitmap=true;
addChild(c);
对于(变量i:int=0;i<10000;++i)
{
c、 图形填充(0xff0000,1);
c、 图。移动到(x0,y0);
c、 图形。lineTo(x1,y1);
c、 图形。lineTo(x2,y2);
c、 图形。lineTo(x0,y0);
c、 graphics.endFill();
}
}
使用此方法,您会注意到每次绘制三角形所需的时间大致相同(因为Flash每次实际上只绘制相同数量的对象)

只需注意,在处理大部分静态图形时,位图缓存可以获得最大的好处

通常,如果不需要保留画布上以前的内容,则只绘制所需内容并执行graphics.clear()操作


针对马特的评论:

您的意思是,如果在每个三角形后都没有调用endFill()(就像现在一样)

这对性能没有任何好处,只会改变绘制的内容。如果在同一BegFill/endFill剖面期间在同一区域上绘制,则每次都会“反转”绘制的剖面

没有一个例子就有点难以解释

让我们修改您的三角形函数,以便它在同一beginFill/endFill剖面中绘制两个三角形:

    c.graphics.beginFill( 0xff0000, 1 );
    for (var i:int = 0; i < 2; ++i)
    {
        c.graphics.moveTo( x0, y0 );

        c.graphics.lineTo( x1, y1 );
        c.graphics.lineTo( x2, y2 );
        c.graphics.lineTo( x0, y0 );    
    }
    c.graphics.endFill();
c.graphics.beginll(0xff0000,1);
对于(变量i:int=0;i<2;++i)
{
c、 图。移动到(x0,y0);
c、 图形。lineTo(x1,y1);
c、 图形。lineTo(x2,y2);
c、 图形。lineTo(x0,y0);
}
c、 graphics.endFill();
如果你运行它,那么你就不会在屏幕上看到任何东西

这是因为你在同一个区域上画了两次,它被反转了(变成透明的)——从技术上讲,Flash仍然在画它,但你就是看不见它

如果将迭代次数更改为3,则将再次看到三角形(因为它每次都从可见->不可见->可见进行切换)

这一页很好地解释了这一点(见下面三分之一的“缠绕”部分)-虽然它专门讨论了Flash Player 10,但同样的想法也适用于以前的版本,我们只是当时无法控制它:)

如果你用精灵而不是画布来画画,会有什么不同吗?如果在runTimeTest开始时调用c.graphics.clear()如何?如果您使用新的图形API(即Graphics.drawGraphicsData),会怎么样?是的,添加c.Graphics.clear()修复了它。非常感谢!你能给我一个答复吗?这样我就可以接受了。MattCanvas和Sprite在这里没什么区别。绘制到本机flash图形层不会触发画布布局功能。.clear()工作的原因可能是内存问题。flash引擎可能正在跟踪每个填充的三角形。谢谢Sly提供的信息。我不知道Flash会一直保存所有绘图命令,直到清除()。我想知道如果endFill()被称为
    c.graphics.beginFill( 0xff0000, 1 );
    for (var i:int = 0; i < 2; ++i)
    {
        c.graphics.moveTo( x0, y0 );

        c.graphics.lineTo( x1, y1 );
        c.graphics.lineTo( x2, y2 );
        c.graphics.lineTo( x0, y0 );    
    }
    c.graphics.endFill();