android

时间:2015-10-22 21:43:02

标签: android actionscript-3 flashdevelop

我遇到了AS3编码AIR for android的工作者之间的通信速度问题。我的测试设备是Galaxy S2(android 4.0.4),我正在使用AIR18.0在flashdevelop中开发。

首先要做的事情。 我尝试通过共享对象进行良好的旧AMF序列化复制。我在物理引擎(辅助线程)上获得平均49次计算/秒,在主线程上具有稳定的60FPS。不得不把它调到超过300个动态物体上,以获得明显的减速。

一切顺利,所以我开始进行设备上的测试,那就是当狗屎开始侧身时。我的速度不到1.5步/秒。

开始深入挖掘,编写了一些代码,以检查地狱的速度是如此之慢,我发现看共享对象有点像看着其他人看油漆干。

此时我开始深入研究。我发现有很多人已经在抱怨消息频道的速度(在共享对象上找不到太多,“开发人员”的现状我猜)。所以我决定使用共享的bytearrays和互斥量。 (我跳过了条件,因为我并不特别希望我的任何线程暂停)。

启动桌面调试器我得到了115-ish计算/ s和超过350次计算/ s直接回调(调试器确实抛出异常,不是为那种连续处理而设计的我猜...任何人。 )。共享的bytearray和互斥量就像宣传的那样,比我前女友的高潮更快。

我在S2上进行调试,看,我得到3.4次计算/秒,200个动态对象。

所以..手机上的并发性已经为我做了很多。然后我想我做了一点测试,没有任何沟通。相同的场景,物理进行超过可接受的40次计算/ s和图形运行在预期的60FPS ......

所以,我直截了当的问题是:

FAPPING FIREFLY正在发生什么?

这是我的Com代码:

package CCom 
{
    import Box2D.Dynamics.b2Body;
    import Box2D.Dynamics.b2World;
    import flash.concurrent.Condition;
    import flash.concurrent.Mutex;
    import flash.utils.ByteArray;
    import Grx.DickbutImage;
    import Phx.PhxMain;

    /**
     * shared and executed across all threads.
     * provides access to mutex and binary data.
     * 
     * @author szeredai akos
     */
    public class CComCore 
    {
        //===============================================================================================//
        public static var positionData:ByteArray = new ByteArray();
        public static var positionMutex:Mutex = new Mutex();

        public static var creationData:ByteArray = new ByteArray();
        public static var creationMutex:Mutex = new Mutex();

        public static var debugData:ByteArray = new ByteArray();
        public static var debugMutex:Mutex = new Mutex();

        //===============================================================================================//
        public function CComCore() 
        {

            positionData.shareable = true;
            creationData.shareable = true;
            debugData.shareable = true;
        }
        //===============================================================================================//
        public static function encodePositions(w:b2World):void
        {
            var ud:Object;

            positionMutex.lock();
            positionData.position = 0;
            for (var b:b2Body = w.GetBodyList(); b; b = b.GetNext())
            {
                ud = b.GetUserData();
                if (ud && ud.serial)
                {
                    positionMutex.lock();
                    positionData.writeInt(ud.serial);               // serial
                    positionData.writeBoolean(b.IsAwake);           // active state
                    positionData.writeInt(b.GetType())              // 0-static 1-kinematic 2-dynamic
                    positionData.writeDouble(b.GetPosition().x / PhxMain.SCALE);    // x
                    positionData.writeDouble(b.GetPosition().y / PhxMain.SCALE);    // y
                    positionData.writeDouble(b.GetAngle());         // r in radians
                }
            }
            positionData.length = positionData.position;
            positionMutex.unlock();

        }
        //===============================================================================================//
        public static function decodeToAry(ar:Vector.<DickbutImage>):void
        {
            var index:int;
            var rot:Number = 0;

            positionData.position = 0;
            while (positionData.bytesAvailable > 0)
            {
                //positionMutex.lock();
                index = positionData.readInt();
                positionData.readBoolean();
                positionData.readInt();
                ar[index].x -= (ar[index].x - positionData.readDouble()) / 10;
                ar[index].y -= (ar[index].y - positionData.readDouble()) / 10;
                ar[index].rotation = positionData.readDouble();
                //positionMutex.unlock();
            }

        }
        //===============================================================================================//
    }

}

(忽略位置y上的低通滤波器 - =(y-x)/ c)

如此。 请注意,仅在解析物理时使用互斥锁确实会使性能提高约20%,同时对主线程的帧速率影响最小。这使我相信问题并不在于每个数据的写入和读取数据,而在于数据可用于第二个线程的速度。我的意思是,那些是字节数组运算,它很快就很自然。我确实通过简单地将远程线程转移到主线来检查速度,速度仍然是合理的。地狱,......即使在S2上也可以接受而不会抛弃额外的计算。

ps:我也尝试过发布版本。

如果没有人有可行的解决方案(除了.2-.4s缓冲区,以及明显的单线程),我确实希望听到有关wanky变通办法或至少是问题的具体来源。

事先提前

1 个答案:

答案 0 :(得分:1)

认为我发现了这个问题。 一如既往,事情比最初想的要复杂得多。

计时器事件以及设置间隔和超时都限制为60fps。只要应用程序在该特定点处空闲,或者在可以自由执行并且延迟已经过去之后立即执行,计时器就会按时执行。但显然,延迟不能短于15-ish(我认为它在台式机上更少)。应该不是问题吧?

然而

如果那段代码操纵共享对象,那么计时器会突然决定自己动手并在15毫秒内查看它,无论它是否有空闲时间。

无论如何,事情是共享对象,工作人员,计时器事件和adobe强加的60FPS限制之间存在错误的交互。

解决方法非常简单。让定时器在5000ms的大量延迟上,并在定时器事件的回调中做5000个循环。显然,下一个计时器事件在5000循环完成之前不会触发,但最重要的是它也不会添加那个巨大的延迟。

另一个奇怪的事情是5000循环期间互斥体的贪婪所有权所以必须使用flash.concurrent.Condition。

好处是性能提升并且令人印象深刻。

缺点是整个物理事物现在与主线程的帧速率(或主游戏循环所包含的任何装置)密切相关,但是嘿。我想,60Fps足够好了。

Zi MuleTrex-感兴趣的人的条件:

package CCom 
{
    import Box2D.Dynamics.b2Body;
    import Box2D.Dynamics.b2World;
    import flash.concurrent.Condition;
    import flash.concurrent.Mutex;
    import flash.utils.ByteArray;
    import Grx.DickbutImage;
    import Phx.PhxMain;

    /**
     * shared and executed across all threads.
     * provides access to mutex and binary data.
     * 
     * @author szeredai akos
     */
    public class CComCore 
    {
        //===============================================================================================//
        public static var positionData:ByteArray = new ByteArray();
        public static var positionMutex:Mutex = new Mutex();
        public static var positionCondition:Condition = new Condition(positionMutex);

        public static var creationData:ByteArray = new ByteArray();
        public static var creationMutex:Mutex = new Mutex();

        public static var debugData:ByteArray = new ByteArray();
        public static var debugMutex:Mutex = new Mutex();

        //===============================================================================================//
        public function CComCore() 
        {

            positionData.shareable = true;
            creationData.shareable = true;
            debugData.shareable = true;
        }
        //===============================================================================================//
        public static function encodePositions(w:b2World):void
        {
            var ud:Object;

            positionData.position = 0;
            positionMutex.lock();
            for (var b:b2Body = w.GetBodyList(); b; b = b.GetNext())
            {
                ud = b.GetUserData();
                if (ud && ud.serial)
                {

                    positionData.writeBoolean(b.IsAwake);           // active state
                    positionData.writeInt(ud.serial);               // serial
                    positionData.writeInt(b.GetType())              // 0-static 1-kinematic 2-dynamic
                    positionData.writeDouble(b.GetPosition().x / PhxMain.SCALE);    // x
                    positionData.writeDouble(b.GetPosition().y / PhxMain.SCALE);    // y
                    positionData.writeDouble(b.GetAngle());         // r in radians

                }
            }
            positionData.writeBoolean(false);
            positionCondition.wait();

        }
        //===============================================================================================//
        public static function decodeToAry(ar:Vector.<DickbutImage>):void
        {
            var index:int;
            var rot:Number = 0;


            positionMutex.lock();
            positionData.position = 0;
            while (positionData.bytesAvailable > 0 && positionData.readBoolean())
            {
                //positionMutex.lock();
                index = positionData.readInt();
                positionData.readInt();
                ar[index].x = positionData.readDouble();
                ar[index].y = positionData.readDouble();
                ar[index].rotation = positionData.readDouble();
                //positionMutex.unlock();


            }
            positionCondition.notify();
            positionMutex.unlock();
        }
        //===============================================================================================//
    }

}

随着更多频道和byteArrays开始弹出,同步将变得更加复杂。