- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在我的游戏引擎中,我使用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's
的GetPosition()
函数的类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
;对于Point
和8
属性的每个x
,y
> = 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()
并没有做任何事情;它本质上是伪装成函数的吸气剂,这就是“额外的类步骤惩罚”如此之大的原因之一
关于performance - 在ActionScript 3中扩展类的负面影响是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18776442/
关闭。这个问题是opinion-based .它目前不接受答案。 想改善这个问题吗?更新问题,以便可以通过 editing this post 用事实和引文回答问题. 8年前关闭。 Improve t
暂时忘记能力的定义,只关注能力的“检查”(使用“授权!”),我看到 CanCan 添加了大约 400 毫秒,用于简单地检查用户是否具有特定的能力主题/模型。 这是预期的吗(我假设不是)?或者,有没有可
我正在阅读有关 Swift 的教程 ( http://www.raywenderlich.com/74438/swift-tutorial-a-quick-start ),它预定义为不显式设置类型,因
这主要是由于对 SQL 问题的回答。由于性能原因,有意省略了 UDF 和子查询。我没有包括可靠性并不是说它应该被视为理所当然,但代码必须工作。 性能永远是第一位的吗?提供了许多以性能为主要优先事项的答
我已经编写了一个简单的测试平台来测量三种阶乘实现的性能:基于循环的,非尾递归的和尾递归的。 Surprisingly to me the worst performant was the loop o
我已将 ui-performance 插件应用到我的应用程序中。不幸的是,在开发模式下运行应用程序时它似乎不起作用。例如,我的 javascript 导入是用“vnull”版本呈现的。 例如 不会
我有一个我操作的 F# 引用(我在各处添加对象池以回收经常创建和删除的短期对象)。我想运行结果报价;现在我使用了 F# PowerPack,它提供了将引用转换为表达式树和委托(delegate)的方法
我正在尝试在 Spark 服务器上运行 SparklyR 库中的机器学习算法。 1 个簇 8 核 24G内存 Ubuntu 16.04 星火2.2 独立配置 1名师傅/2名 worker 每个执行器的
我有一个数据库(准确地说是在 postgres 上运行),具有以下结构: user1 (schema) | - cars (table) - airplanes (table, again) .
我的应用程序在我的 iPad 上运行。但它的表现非常糟糕——我的速度低于 15fps。谁能帮我优化一下? 它基本上是一个轮子(派生自 UIView),包含 12 个按钮(派生自 UIControl)。
在完成“Scala 中的函数式编程原则”@coursera 类(class)第 3 周的作业时,我发现当我实现视频类(class)中所示的函数联合时: override def union(tha
我正在重构我的一个 Controller 以使其成为一项服务,我想知道不将整个服务容器注入(inject)我的 Controller 是否会对性能产生影响。 这样效率更高吗: innova.path.
我有一个要显示的内容很大的文件。例如在显示用户配置文件时, 中的每个 EL 表达式需要一个 userId 作为 bean 的参数,该参数取自 session 上下文。我在 xhtml 文件中将这个 u
我非常了解 mipmapping。我不明白(在硬件/驱动程序级别)是 mipmapping 如何提高应用程序的性能(至少这是经常声称的)。在执行片段着色器之前,驱动程序不知道要访问哪个 mipmap
这个问题在这里已经有了答案: 10年前关闭。 Possible Duplicate: What's the (hidden) cost of lazy val? (Scala) Scala 允许定义惰
一些文章建议现在 build() 包含在 perform() 本身中,而其他人则建议当要链接多个操作时使用 build().perform()一起。 最佳答案 build() 包含在 perform(
Postgres docs说 For best optimization results, you should label your functions with the strictest vol
阅读Zero-cost abstractions看着 Introduction to rust: a low-level language with high-level abstractions我尝
我想在 MQ 服务器上部署 SSL,但我想知道我当前的 CPU 容量是否支持 SSL。 (我没有预算增加 CPU 内核和 MQ PVU 的数量) 我的规范: Windows 2003 服务器 SP2,
因此,我在 Chrome 开发者工具 的性能 选项卡内的时间 部分成功地监控了我的 React Native 应用程序的性能。 突然在应用程序的特定重新加载时,Timings 标签丢失。 我已尝试重置
我是一名优秀的程序员,十分优秀!