9RIA.com天地会 - 论坛

返回列表 发帖

天地培训

9RIA天地会官方培训机构

Adobe官方认证培训中心

[新闻资讯] [业界动态] 位图数据内存优化

  • 资讯类型: 转载
  • 来源页面: http://www.uxtracer.com/blog/?p=20
  • 资讯原标题: Flash相册程序的内存占用优化
  • 资讯原作者: UXtracer
  • 我的评论:
    对这篇文你有啥看法,跟贴说说吧!欢迎口水和板砖,哈哈。欢迎大家和我们一同分享更多资讯。

    最近协助同事对Flash相册项目做了程序优化,觉得每个优化步骤的试验结果都挺有价值,所以在这里做一个记录分享。

    项目现状
    Flash相册程序,在播放60张图片后(60是相册图片数量上限),内存占用接近1G。

    当前技术实现
    使用Loader加载图片文件,然后新建BitmapData对Loader进行draw操作保存位图数据,随后loader.unload()释放原始图片资源。播放某一张图片时,取出对应的位图数据,根据当前播放窗口大小进行平滑缩放,随后生成Bitmap对象,展现。

    优化思考1:所有已加载的图片都保存其位图数据,导致内存占用过大。那么可以考虑限制位图数据对内存的占用总量,如果位图数据内存占用超出一个设定值(比如200MB)后销毁离当前播放index最远的图片位图数据。
    问题:由于已加载数据可能会被销毁,所以会经常发生图片需要再次加载的情况,影响相册观看流畅度。另外,通过测试发现,即使设定一个比较宽松的上限值(比如200MB),也只能容纳几张图片的位图数据。
    该方法损失了用户体验,但问题仍然没有得到较好解决。

    优化思考2:BitmapData位图数据占用内存过大,如果Loader加载图片文件后不转化为位图数据,而直接保存loader对象,会不会减小内存占用?
    经过试验发现,一个1280*800的jpg(130K),通过Loader加载进舞台并显示,不做任何处理,内存占用高达4MB。将loader对象从舞台上remove掉,只保留引用,内存占用仍不见减少。同时此做法会带来一个问题,loader对象的直接缩放会产生锯齿,这对相册程序而言是不可以接受的。
    此路不通。

    优化思考3:既然直接保存BitmapData对象很吃内存,那么我通过JPGEncoder将其转化为ByteArray再进行保存,势必会减少开销。需要使用图片时,再通过loader.loadBytes来加载ByteArray数据。
    经过试验发现,经过JPGEncoder转化后的ByteArray数据很小,只占用几十KB内存,效果明显。使用loader.loadBytes加载ByteArray显示也很顺利很流程。但一个致命的问题出现了,JPGEncoder执行效率非常低下,即使只是宽高1280*800的BitmapData,转化过程也会长达6秒之久(我的机器配置不低),更糟糕的是,由于Flash是单线程运行环境,所以此操作会导致整个界面卡住,程序陷入假死状态。
    (延伸阅读:使用Vector优化JPGEncoder执行效率    异步JPGEncoder)

    优化思考4:经Laan提醒,想到ByteArray不需要通过对BitmapData数据JPGEncode来做,通过URLLoader指定BINARY方式读取图片文件,其data属性就是JPG或者其它压缩格式的ByteArray数据。
    试验通过,问题终于得到顺利解决。

    优化效果
    经过上述优化,60张图片播放后,内存占用仍然不到100M,优化效果显著。

    最后,说一下如何强制Player进行垃圾回收
    如果只想在Debug Player中使用,则可以使用System.gc();
    如果想在所有运行环境都能运行,则可以使用下面这一段垃圾回收触发代码(查看原帖):

    try {
        new LocalConnection().connect(“gcHacker”);
        new LocalConnection().connect(“gcHacker”);
    } catch (e:Error) {
    }
    1

    评分人数

    • greenidea

    greenidea 赐本贴 威望 + 1 银子 + 20  诏曰:

    we are 译林军
    新闻资讯版Q群:109921254

    天地人才库
    好东西,正为此问题烦恼,终于有解决的方案了。谢谢分享。

    TOP

    很好呀!厉害
    http://www.ways2u.com

    TOP

    好兄弟,讲义气!---by eko

    踏上天地会荣耀之路!

     

    申请舵主

    加入掘金队

    加入译林军

    知识专题整理

     

    咨询(QQ):

    1442604479(小地)

     

    loader对象的直接缩放会产生锯齿,这对相册程序而言是不可以接受的。


    这里有个比较简单的的处理办法,就是在loader的complete事件触发时,把 evt.target.content.smoothing设置成为true
    1

    评分人数

    • eko

    eko 赐本贴 银子 + 4  诏曰: 积极参与奖

    www.ttshock.com RIA应用,WebGame开发

    TOP

    不错,有所收获,谢谢分享

    TOP

    本帖最后由 newage 于 2010-3-29 10:14 编辑

    回复 1# eko

    1、bitmapdata 对象在加载后,本来就需要通过 dispose 进行回收内存,就能自动释放内存,每次重新执行加载的时候再另外 load 一遍,因为图片已经 download到本地 template files 文件夹,则你再次 loading 的文件会先读取本地文件的特征码,并附加在 HTTP 请求道 proxy server ,proxy server 会校验文件并返回 304 协议让你读取本地文件,最后按照这个流程你就知道应该怎么综合去处理了。

    2、那一段垃圾回收触发代码非常不建议使用。性能非常低,自己可以测试一下看看,除了抛异常和 system.gc 其实还有别的方法。

    3、是我的一个期望:flash 在运行时,必须使用位图数据保存,如果这一点能够改进,那么势必大大降低我们的内存占用。众所周知编码不同,最后仍需要在内存中序列化合反序列化,内存中保存 bytearray 是可行,但是仍然会在序列化与反序列化之间占用 CPU 消耗。序列化反序列化保存到本地 sharedobject 是不可行的,这样要进行两次编码,而且写入消耗大量 CPU ,而保存到本地 template files 有一个缺陷,就是要看用户的浏览器,而且仍然是文件系统的读写。 adobe 是否能开辟一个内存区域成为我们的高速硬盘?这个区域可以进行一个比 jpeg 编码简单但是压缩率还可以的,这样用来单独保存图片,并且自动根据 LRU 原则进行空间的整理,也许会是内存和CPU消耗之间的最佳方式。
    1

    评分人数

    • eko

    eko 赐本贴 银子 + 8  诏曰: 积极参与奖

    TOP

    Laan 无所不能啊 神人

    TOP

    回复 6# newage


        newage可以说说别的垃圾回收的方法

    TOP

    好文章 谢谢分享

    TOP

    不错。

    TOP

    本帖最后由 Y.Boy 于 2010-4-1 12:16 编辑

    分享经验不错。不过,疑点不少。
    1. 用 loader 加载图片后,为何还要 draw 一次。Loader.content 已经是 Bitmap 对象了,(loader.content as Bitmap).bitmapData 即可;

    2. “一个1280*800的jpg(130K),通过Loader加载进舞台并显示,不做任何处理,内存占用高达4MB” --> 1280*800 个像素点占用的内存绝对是:1280*800*4/1024 = 4000 KB。没有所谓的“不做任何处理,内存占用高达4MB”

    3.优化技巧3那里,要注意 JPGEncoder 是有损压缩。

    最后就是GC问题,这个有时间再写了。。。

    ---

    loader 可加载三种东西,flash player 会自动判断是哪种东西而让 loader.content 转为哪种类型:
    1. 图片(jpg,png,gif...):loader.content 的类型为 Bitmap;
    2. AVM2 的 swf:loader.content 的类型为 Sprite、MovieClip或继承自这些的类
    3. AVM1 的 swf:...... AVM1Movie
    1

    评分人数

    • eko

    eko 赐本贴 银子 + 8  诏曰: 积极参与奖

    TOP

    回复 11# Y.Boy


        期待GC问题的讨论

    TOP

    楼上的第二点: 4000KB 不就约等于4MB吗? 一个图片占4MB已经很厉害了!
    学习的过程是。。。。。。

    TOP

    如果通过URLLoader指定BINARY方式读取图片文件真能节省那么多 我真想试试。以前没用过这种。
    学习的过程是。。。。。。

    TOP

    有所收获,谢谢分享

    TOP

    返回列表