gpt4 book ai didi

performance - 在ActionScript 3中扩展类的负面影响是什么?

转载 作者:行者123 更新时间:2023-12-04 02:47:20 26 4
gpt4 key购买 nike

在我的游戏引擎中,我使用Box2D进行物理处理。 Box2D的命名约定和不好的注释破坏了我引擎中一致的,有据可查的其余部分,这令人沮丧,并且在使用时效果不佳。

我考虑过为Box2D制作一组包装器类。也就是说,扩展每个公共Box2D对象并对其函数进行重写的类均遵循我的引擎其余部分的命名约定,并对其进行更清晰且一致的注释。我什至考虑过在某些类的基础上构建并添加一些点滴(例如b2Vec2类中用于基于像素的测量的吸气剂)。

很好,但是我不确定这会带来什么负面影响以及这些负面影响会影响我的应用程序和游戏的程度。我不确定编译器是否在一定程度上缓解了我的某些顾虑,或者在添加一些不必要的类以提高可读性和一致性时是否需要体贴。

我有些怀疑:


更多内存消耗,以容纳额外级别的类结构。
是否由于初始化成员的额外级别而在创建新对象时对性能产生影响?


我专门询问有关运行时的影响。

最佳答案

在集成第三方库时,这是一个非常普遍的问题,尤其是作为端口的库(如Box2DAS3一样),它们保留父语言的编码和命名约定,而不是与目标语言完全集成(例如) :Box2DAS3使用getFoo()setFoo()而不是.foo getter / setter)。

要快速回答您的问题,不,使用包装器类不会对性能产生重大影响;只不过您在自己的项目的类层次结构中会看到。当然,如果您对500万次迭代进行一次循环,则可能会发现相差一毫秒或两毫秒,但是在正常使用情况下,您不会注意到它。

“更多的内存消耗可容纳额外级别的类结构。”
像任何具有类继承的语言一样,vtable将在幕后使用,因此您的内存/性能会有少量增加,但这可以忽略不计。

“由于初始化额外级别的成员而在创建新对象时的性能影响?”
只不过是普通的实例化,因此除非您要创建大量的对象,否则不必担心。

在性能方面,通常应该没有问题(除非您实际遇到问题,否则应优先考虑可读性和可用性而不是性能),但是我将其更多地视为体系结构问题,考虑到这一点,我会考虑扩展/修改外部库的类的负面影响通常取决于以下三个方面:


修改库
扩展课程
用自己的班级作文


修改库

由于Box2DAS3是开放源代码,因此没有什么可以阻止您介入并将所有类/函数名称重构为您喜欢的内容。我曾认真考虑过有时这样做。

优点:


您可以修改所需的内容-函数,类,为其命名
您可以添加所需的任何缺失部分(例如,像素-米转换帮助器)
您可以解决任何潜在的性能问题(我注意到,如果以“ AS3”方式完成,则可以更好更快地完成一些工作)


缺点:


如果您打算保持版本为最新,则需要手动合并/转换所有更新和更改。对于流行的图书馆或变化很大的图书馆,这可能是一个巨大的痛苦
这非常耗时-除了修改之外,您还需要对正在发生的事情有很好的了解,以便可以进行任何更改而不会破坏功能
如果有很多人在使用它,他们将不能过多地依赖外部文档/示例,因为内部可能已经发生了变化


扩展课程

在这里,您只需创建自己的包装器类,即可扩展Box2D基类。您可以根据需要添加属性和函数,包括实现自己的命名方案,该方案可以转换为基类(例如MyBox2DClass.foo()可能只是Box2DClass.bar()的包装器)

优点:


您仅实现所需的类,并进行必要的更改
包装器类仍然可以在基本的Box2D引擎中使用-即,您可以将MyBox2DClass对象传递给采用Box2DClass的内部方法,并且您知道它可以工作
在这三种方法中,这是最少的工作量


缺点:


同样,如果您打算保持版本最新,则需要检查所有更改都不会破坏您的课程。虽然通常情况下问题不大
如果您创建自己的调用Box2D等效函数的函数(例如,“我应该使用setPos()还是SetPosition()?”),则可能会使类陷入混乱。即使您自己进行工作,当您返回自己的在6个月内上课,您会忘记
您的类将缺乏连贯性和一致性(例如,某些使用命名方法(setPos())的函数,而另一些使用Box2D(SetPosition())的函数)
你被Box2D困住了;您不能在没有大量开发人员的情况下更改物理引擎,这取决于在整个项目中使用类的方式。如果您不打算切换,这可能没什么大不了的


用自己的班级作文

您可以自己创建类,这些类在内部拥有Box2D属性(例如MyPhysicalClass将具有属性b2Body)。您可以根据需要自由实现自己的接口,并且只需要必要的接口即可。

优点:


您的课程更干净,更适合您的引擎。仅公开您感兴趣的功能
您不受Box2D引擎的束缚;例如,如果要切换到Nape,则只需修改自定义类;您的引擎和游戏的其余部分将被忽略。其他开发人员也无需学习Box2D引擎即可使用它
在那里,您甚至可以实现多个引擎,并使用切换或界面在它们之间切换。同样,其余的引擎和游戏都可以忽略
与基于组件的引擎配合良好-例如您可以拥有一个包含b2Body属性的Box2DComponent


缺点:


除了扩展类以外,还需要做更多的工作,因为实际上是在引擎和Box2D之间创建一个中间层。理想情况下,在自定义类之外,不应引用Box2D。工作量取决于班级需要什么
额外的间接级别;通常,这应该没问题,因为Box2D会直接使用Box2D属性,但是如果您的引擎正在大量调用函数,那么在性能方面这是一个额外的步骤


在这三个中,我更喜欢使用组合,因为它可以提供最大的灵活性并保持引擎的模块化特性不变,即您拥有核心引擎类,并且可以使用外部库扩展功能。您可以轻而易举地切换出库的事实也是一个巨大的优势。这是我在自己的引擎中采用的技术,并且还将其扩展到其他类型的库中,例如广告-我有我的引擎广告类,可以根据需要与Mochi,Kongregate等集成-游戏的其余部分不在乎我使用的是什么,这使我可以在整个引擎中保持编码风格和一致性。仍然是灵活和模块化的。

-----更新20/9/2013 -----

大更新时间!所以我回去做一些关于尺寸和速度的测试。我使用的课程太大,无法在此处粘贴,因此您可以在http://divillysausages.com/files/TestExtendClass.as下载

在其中,我测试了许多类:


Empty实例;一个仅扩展Object并实现一个空的getPostion()函数的类。这将是我们的基准
b2Body实例
Box2DExtends实例;扩展b2Body并实现仅返回getPosition()的函数GetPosition()的类(b2Body函数)
Box2DExtendsOverrides实例;扩展b2Body并覆盖GetPosition()函数的类(仅返回super.GetPosition()
Box2DComposition实例;具有b2Body属性和返回getPosition() b2Body'sGetPosition()函数的类
Box2DExtendsProperty实例;扩展b2Body并添加新的Point属性的类
Box2DCompositionProperty实例;同时具有b2Body属性和Point属性的类


所有测试均在非大型笔记本电脑上的独立播放器FP v11.7.700.224 Windows 7中完成。

测试1:大小

AS3有点烦人,因为如果您调用getSize(),它将为您提供对象本身的大小,但是任何也为Objects的内部属性只会导致4 byte增加,因为它们只是数指针。我可以看到他们为什么这样做,只是使获得正确的尺寸有点尴尬。

因此,我转向了flash.sampler包。如果我们对创建对象进行采样,并在NewObjectSample对象中添加所有大小,则将获得对象的完整大小(注意:如果要查看创建的内容和大小,请在< cc>调用测试文件)。


空的大小为56 //扩展对象
b2Body的大小是568
Box2DExtends的大小为568 //扩展b2Body
Box2DExtendsOverrides的大小为568 //扩展b2Body
Box2DComposition的大小为588 //具有b2Body属性
Box2DExtendsProperty的大小为604 //扩展b2Body并添加Point属性
Box2DCompositionProperty的大小为624 //具有b2Body和Point属性


这些大小均以字节为单位。需要注意的几点:


基本的log大小是Object字节,所以只有类,而没有其他内容是40字节。
添加方法不会增加对象的大小(无论如何,它们都是基于类实现的),而属性显然会增加
只是扩展类并没有添加任何东西
16的额外20字节来自类的Box2DComposition和指向16属性的指针的4
对于b2Body等,对于Box2DExtendsProperty类本身,具有16;对于Point属性的指针,具有4;对于Point8属性的每个xy > = Numbers字节和36之间的字节差


因此,显然大小的差异取决于您添加的属性,但总的来说,可以忽略不计。

测试2:创建速度

为此,我简单地使用Box2DExtends和一个getTimer()循环,该循环本身循环10000(大约100k)次以获得平均值。在每个集合之间调用10以最大程度地减少由于垃圾收集而导致的时间。


空的创建时间为3.9毫秒(平均)。
b2Body的创建时间为65.5ms(平均)
Box2DExtends的创建时间为69.9ms(平均)。
Box2DExtendsOverrides的创建时间为68.8ms(平均)。
Box2DComposition的创建时间为72.6ms(平均)。
Box2DExtendsProperty的创建时间为76.5毫秒(平均)。
Box2DCompositionProperty的创建时间为77.2毫秒(平均)。


这里没有一堆值得注意的东西。扩展/合成类花费的时间稍长一些,但是它就像System.gc()(这是100,000个对象的创建时间),因此它并不是真正值得考虑的。

测试3:通话速度

为此,我再次使用0.000007ms,并使用getTimer()循环,其自身循环1000000(因此10m)次以获得平均值。在每个集合之间调用10以最大程度地减少由于垃圾收集而导致的时间。所有对象都调用了其System.gc()函数,以查看覆盖和重定向之间的区别。


getPosition()为空的时间为83.4ms(平均)//为空
b2Body的GetPosition()时间为88.3ms(平均)//正常
Box2DExtends的getPosition()时间为158.7毫秒(平均)// getPosition()调用GetPosition()
Box2DExtendsOverrides的GetPosition()时间为161ms(平均)//覆盖调用super.GetPosition()
Box2DComposition的getPosition()时间为160.3毫秒(平均)//调用this.body.GetPosition()
Box2DExtendsProperty的GetPosition()时间为89毫秒(平均)//隐式超级(即不被覆盖)
Box2DCompositionProperty的getPosition()时间为155.2毫秒(平均)//调用this.body.GetPosition()


这让我有些惊讶,时间之间的差异约为2倍(尽管每次通话仍为getPosition()/GetPosition())。延迟似乎完全取决于类的继承-例如0.000007ms只是调用Box2DExtendsOverrides,但速度却是super.GetPosition()的两倍,后者是从其基类继承Box2DExtendsProperty的。

我想这与函数查找和调用的开销有关,尽管我在FlexSDK中使用GetPosition()查看了生成的字节码,并且它们是相同的,所以要么对我说谎(或者不包括在内)它),或者有一些我想念的:)虽然步骤可能相同,但它们之间的时间可能不同(例如,在内存中,它正在跳转到您的类vtable,然后跳转到基类vtable,等等)

swfdump的字节码很简单:

getlocal        4
callproperty :GetPosition (0)
coerce Box2D.Common.Math:b2Vec2
setlocal3


var v:b2Vec2 = b2Body.GetPosition()var v:b2Vec2 = Box2DExtends.getPosition()返回 getPosition())是:

getlocal        5
callproperty :getPosition (0)
coerce Box2D.Common.Math:b2Vec2
setlocal3


对于第二个示例,它没有显示对 GetPosition()的调用,因此我不确定他们如何解决该问题。如果有人想破解说明,可以下载测试文件。

请记住以下几点:


GetPosition()并没有做任何事情;它本质上是伪装成函数的吸气剂,这就是“额外的类步骤惩罚”如此之大的原因之一
这是一个10m的循环,您不太可能在游戏中这样做。每次通话的罚金确实不值得担心
即使您确实担心罚款,也请记住,这是您的代码与Box2D之间的接口。 Box2D内部构件将不受此影响,只有对您界面的调用


总而言之,我希望扩展自己的一个类可以得到相同的结果,所以我不必担心。实施最适合您的解决方案的体系结构。

关于performance - 在ActionScript 3中扩展类的负面影响是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18776442/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com