Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/apache-flex/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Apache flex 不变性和Flex是一个糟糕的组合吗?_Apache Flex_Actionscript 3_Immutability - Fatal编程技术网

Apache flex 不变性和Flex是一个糟糕的组合吗?

Apache flex 不变性和Flex是一个糟糕的组合吗?,apache-flex,actionscript-3,immutability,Apache Flex,Actionscript 3,Immutability,在我的scratch构建的flex游戏框架中,我定义了一个名为ThreeDPoint的类,它携带一个x、y和z坐标集来跟踪游戏中的对象,称为Actors。我还使用该类创建运动向量,这些向量在每一帧中叠加在一起,为每个参与者创建一个累积的运动向量 我将ThreeDPoint类设置为不可变类,以支持以下观点:给定的位置无法更改,您只能给演员一个新的位置,同时也阻止潜在的客户端程序员(我!)更改堆栈中的运动向量,而不是分配一个新的运动向量来创建您想要的运动类型 不幸的是,这个系统的性能下降得非常快。使

在我的scratch构建的flex游戏框架中,我定义了一个名为ThreeDPoint的类,它携带一个x、y和z坐标集来跟踪游戏中的对象,称为Actors。我还使用该类创建运动向量,这些向量在每一帧中叠加在一起,为每个参与者创建一个累积的运动向量

我将ThreeDPoint类设置为不可变类,以支持以下观点:给定的位置无法更改,您只能给演员一个新的位置,同时也阻止潜在的客户端程序员(我!)更改堆栈中的运动向量,而不是分配一个新的运动向量来创建您想要的运动类型

不幸的是,这个系统的性能下降得非常快。使用Flex Builder profiler,我注意到我泄漏了一些三点对象(我有26个参与者,大概有30个,但只要60秒的运行时间,我就有1000多个这样的对象),但由于这些对象非常轻量级,实际内存占用相当稳定

另一方面,分析器显示在运行60秒后累计创建的250000多个三点对象。现在,由于我是如何故意创造和扔掉这些东西的,这对我来说一点也不奇怪。但是当看到这样一个概要文件时,我想到的唯一一件事是大量的new()和GC调用(不,我没有显式地调用GC)是影响性能的因素,特别是考虑到这样一个事实,即当我开始时,三点是可变的,一切都很好。这似乎合理吗

package net.emptykingdom.utils
{
    public class ThreeDPoint
    {
        public function ThreeDPoint(x:Number = 0, y:Number = 0, z:Number = 0)
        {
            this._x = x;
            this._y = y;
            this._z = z;
        }

        public function get X():Number { return _x; }
        public function get Y():Number { return _y; }
        public function get Z():Number { return _z; }

        private var _x:Number = 0;
        private var _y:Number = 0;
        private var _z:Number = 0;
    }
}

编辑:我已找到并删除内存泄漏。它带来了一个很小但很明显的性能增益,尽管还没有大到可以实例化大量参与者的程度。根据分析器,我的代码仍然由对三点构造函数的调用控制。回到一个可变的三分球让我找回了我曾经享受过的相当多的表现。因此,我猜Flex对象实例化比我在其中玩过的其他环境更昂贵。太糟糕了。

我想说,在AS3的性能敏感应用程序中,使用不可变值来表示快速变化的值是一个糟糕的组合,是的。AS3不是最快的环境,让它处理3D意味着压缩性能。要求它为原语值的每次更改创建一个新对象可能会带来麻烦。

您的描述非常有趣,您的怀疑——通过使三点类不可变进行预优化破坏了您的性能——听起来是正确的。您基本上是用交换整个对象来替换更改对象的内部(可变),并假设
gc
和运行时会更喜欢这样。正如您所说的,实例化和
gc
调用现在正使工作陷入困境。所以你只有几个可能性:

  • 您在某处保留了一些引用,或者创建了比您想要的更多的这些对象,这会降低您的性能
  • 通过减少
    gc
    触发的次数,您可能可以提高性能。我对此表示怀疑,但至少你可以
  • 可变设计更好。理论上不是这样,但Flash引擎就是这么认为的
  • 如果这个问题对您来说真的很有趣,那么将其简化为核心元素(可变与不可变、大量对象创建与变异),并在一些测试运行中展示您的直觉。然后将结果发布到这里,这样我们都可以变得更聪明

    我的猜测:这是一个明显的例子,试图为Flash引擎做一些没有帮助的事情


    编辑:更好地阅读您的第一段,我意识到您这样做是出于程序中的设计原因。如果是这样,不幸的是,实时编程是OO设计遇到运行时引擎严酷现实的地方

    您正在为每个演员每秒创建160个三点。在每秒30帧时,这大约是每个演员每帧5帧。这使得每个演员每帧调用15次,仅用于读取三个点的坐标。 我相信,这不可能无限扩展

    Actor::moveTo(x:Number,y:Number,z:Number):void
    Actor::moveBy(x:Number,y:Number,z:Number):void
    有什么不对

    另外,对于一个游戏,我认为这是一个更好的演员模型(只是一个草图):

    下面的界面抽象了对参与者的所有影响(摩擦力、重力、推力等)

    一个以恒定速度移动的演员只需要一个步骤。就这样。 你只需要在IActorAffector上创建每个可以作用于目标(吸引力来源等)的效果

    不变性并不是那么错误,但在您的情况下,它似乎太昂贵了。另外,如果您管理好了这三个点,那么可能需要使用对象池来保持实例化和GC的低级别


    如果事情对性能至关重要,您可能需要检查一下。它输出更快的字节码,允许低级别内存访问,并允许作为只读实例变量(编译时特性),这允许实现不变性,而无需对每个字段进行调用访问。使用Haxe还有很多其他原因,但我会让你自己去发现。

    听起来像是一个可怕的GC。我想知道,你是否检查过,以确保你没有意外地在某处留下引用?正如我在“我注意到我正在泄漏一些…”一句中提到的,我确实在泄漏对象。然而,泄漏对象的数量比创建和GC'd的对象数量少两个数量级。因此,我很乐于接受这样一个观点,即我的瓶颈是创造/破坏,而不是内存开销。达斯曼,这基本上是不相关的,但如果你不知道这些存在,你应该知道。我
    package {
        public class Actor {
            private var _x:Number;
            private var _y:Number;
            private var _z:Number;
            public var xs:Number;
            public var ys:Number;
            public var zs:Number;
    
            public function Actor() {}
            public function get x():Number { return _x; }
            public function get y():Number { return _y; }
            public function get z():Number { return _z; }
            public function step():void {
                this.x += this.xs;
                this.y += this.ys;
                this.z += this.zs;
            }                  
        }   
    }
    
    package {
        interface IActorAffector {
            function applyTo(actor:Actor):void;
        }   
    }