说实话,最近的项目,越做越无聊了,核心的东西基本完成,剩下的几乎都是体力活,没什么新鲜好玩的。昨天打完工人物语7,睡意正浓,突然看了两个提神的网页:http://www.buraks.com/azoth/ 和 http://philippe.elsass.me/2010/05/as3-fast-memory-access-without-alchemy/ ,这一下子精神就来了。
FlashPlayer中读写ByteArray速度应付某些变态需求的时候,总会力不从心,这两天徐灿被搞得非寻找个离经叛道的非官方手段不可,结果还就真找到了。我之前听闻haXe的高效率是因为作者找到了FlashPlayer10为炼金术提供的底层接口,但因为种种原因没有去使用haXe,看到这俩网页又让我看到了新的花样,原来是一个圈子里的货。它们三个都是找到了FlashPlayer10给炼金术开的“后门”在低层提高性能。
既然看到了新鲜玩意,不拿来玩弄玩弄就太不给力啦。haXe我依然不打算使用,我希望尽量少地依赖非官方的API。Apparat很好很强大,不过需要安装运行时,而且是一个功能很多的框架,我不喜欢用一个有大半功能都用不上的玩意。
Azoth是一个专门带来高速访问内存API的小工具,小巧轻便,功能唯一,我就喜欢这种。它让我们把一个ByteArray作为一个独立内存区使用,下载http://www.buraks.com/azoth/azoth104.zip然后用里面提供的fastmem类读写数据,写好代码编译成SWF后运行azoth.exe注入swf,就变成了优化版,没有注入的时候显然速度是比flash提供的API要慢的。
既然要玩弄,那就没事找事做实验。在徐灿的鼓动下,今天一时脑子发热,试了一下把位图渲染用这套高速内存访问来优化。基本思路是把所有用于渲染的BitmapData全部以二进制存放到一个ByteArray里,每个位图有一个起始内存地址和长度,手动管理这个ByteArray的所有内部地址,维护图像的层级内容,最终只有输出到视图的是一个BitmapData,以期高速读写带来性能提升。
试过之后发现效果不可观——尽管内存读写速度更快,但它让copypixel的实现负担放到了逐个像素处理上,一张仅300*300的图copypixel到另一张图,则需要计算90000 * 2个内存地址,更大的图更多的内存地址计算,这些计算量在高层实现是很耗时的。而且图与图之间的copypixel并不只是单纯的数值存取,还要根据alpha进行合并,颜色计算又要消耗时间。flash本身的bitmapData的copypixel,对300*300的图进行5次处理只要4ms,而flash里面执行180000次循环加法计算,在我机器上就要7ms。所以嘛,吞吐量不是问题,运算量极度加剧,高速内存存取不是用来干这个的,果然是脑子发热了。
为什么是copyPixel而不是setPixels呢?既然用了byteArray就不必要使用并不显示的bitmapData作buffer了
@Andy Shang, 我这里的copyPixel是自己管理内存实现的替代方法,并不是BitmapData的copyPixel。 而且,既然用了ByteArray,自然也不需要使用并不显示的bitmapData作buffer了,所以也并没有BitmapData的setPixels。
明白:) 虽然并不太擅长render的优化,不过感官的认识,更大段的内存复制效率总是远胜于每个地址的迭代,一般都是索引到tile整个贴到dstmap去的。所以虽然用fastmem单次读写速度提升了,整体效率还是难得到提高。
@AndyShang, 对的