最近关注的WP7比较多,众所周知所有的移动终端设备几乎对内存都有着令人发指的要求,而我所开发的领域——游戏,却是对内存要求非常高,一组几百人的用户数据字节数可能还没一张图片字节数多,而近期我的一些游戏作品也在探讨有关内存的优化等问题,最近WP7的lumia 610悄然加入到Apphub的支持机型名单,这个内存只有256MB的机器会拒绝所有内存(memory)超过90MB的app,以至于很多朋友措手不及,下面摘抄总结了一些内存的有关问题。
第一个问题是:看
因为在模拟器里不会对内存有要求,但是要想弄全所有的设备,可是一个不小的开销,所以如何了解自己的内存是否超了上限是一个重要问题。
Silverlight for WindowsPhone的应用可以直接用
Application.Current.Host.Settings.EnableFrameRateCounter = true;
来开启应用当前的页面数据显示,如下图
而这些数据的作用详细请参看这里:
http://msdn.microsoft.com/zh-cn/library/gg588380(v=VS.92).aspx
在早期,我一直以为这是准确的数据,可是后来知道这只是画面纹理的内存数值,和真实的内存不一样。而且在XNA for WindowsPhone的应用里没法直接打开查看,所以,需要另外一个方法取得:
Microsoft.Phone.Info.DeviceStatus.ApplicationCurrentMemoryUsage
类Microsoft.Phone.Info.DeviceStatus里包含了各种对程序内存的静态属性,具体的信息可以看
http://msdn.microsoft.com/en-us/library/microsoft.phone.info.devicestatus(v=vs.92).aspx
所以无论在Silverlight还是XNA里,都可以写一个简单的计算取得当前应用程序的内存数据:
var value = Microsoft.Phone.Info.DeviceStatus.ApplicationCurrentMemoryUsage / (1024d * 1024d);
第二个问题:缩
你得到了内存数据之后,如果没有超过还好,如果太大并且需要优化的话,就得考虑怎么来缩它了。
注意点1:实现IDisposable
尽量的对于会重复的数据带上IDisposable
注意点2:Image.Source = null
一些动态的载入BitmapImage他们悄声无息的一直站着资源,这个虽然看起很土,但是很管用,曾经让我的Silverlight网页游戏内存稳定并总体降低了1/3。
注意点3:小心事件
在我的团队里,对于一次性的事件一定要求剪掉(-=),甚至在Dispose()里做判断,这是因为游戏中大量的随时创建出来的对象,一直带着几个事件跑就不会被GC掉,用调试工具查看过,大多是因为事件中带着全局或者其他的引用造成。
注意点4:用单例
对于设计模式,没什么好说的,挺怕被喷,只能说单例用好了是英雄,用不好是狗熊。
注意点5:别用数据绑定
据我所知靖南兄、老马,我们都吃过数据绑定的亏,数据绑定是一个多么好的东西啊,可是内存消耗真不是玩的,尤其不是你自己写的控件用上玩数据绑定,那才叫——谁用谁知道!
关于XNA的瘦身策略,可以详细参看http://msdn.microsoft.com/zh-cn/library/hh855082(v=vs.92).aspx
里面详细介绍了Image图像在内存的问题,列举如和使用2次幂优化,降低质换格式的等方法,对于SoundEffect的销毁和顶点数据优化等内容,十分不错。
第三个问题:躲
好吧,当我们的应用程序已经瘦身瘦到无法再瘦,所谓惹不起躲得起,咱们干脆就不支持256MB这样限定90MB的设备了。
打开app的WMAppManifest.xml 加入如下代码:
<Requirements>
<Requirement Name="ID_REQ_MEMORY_90" />
</Requirements>
所谓“你有金银堆北斗,我在江湖度春秋。”,对于现在这状况也只能“路逢险处须当避,不是才子莫吟诗”。