项目后期Lua接入笔记11--Lua代码优化2
2017-04-18 19:16
435 查看
文章转载自Unity3D游戏优化之Lua的内存,感谢原作者燃野提供的好文章
近段时间处理了一些Lua相关的性能和内存问题,分享记录下
1.lua内存增长很快,但gc可以降低的情况
一个小场景,角色站着不动内存就会稳定的增长,对比了unity profiler里的数据,没有特别显著的变化,但是lua内存增长了很多
执行lua gc后会大幅降低。说明是临时对象占用的内存,不gc释放不掉。也确实没开自动gc和定期gc,也算是为了暴露问题。
接着用windows sdk里的umdh(user mode dump heap)查出来是slua的pushVector3造成的
紧接着反查都哪里会调pushVector3,发现是lua和C#间进行Vector3类型转换的时候会用到,后来发现是小地图lua代码里每帧一次取UI组件的几个position,频率虽然不高,但引起的内存增长倒是不少。
项目开始的时候已经知道频繁调用transform.position等会有性能问题,所以专门写了不用进行vector3转换的SetPostion(x, y, z)等方法,但没有对position的相关方法做限制,口头约定不要用position接口,但还会有人不注意。现在干脆删掉了transform里position等相关的导出方法,用了就报错,强制使用自定义的setter和getter。让我再次想起来规范一定要做到工具里,或者形成强制限制或检查,不然就是没用的规范。
这次比较幸运,是特殊的pushVector3造成的,如果之后是lua里某些地方造成频繁的创建临时对象怕是都不好找到是哪块lua代码。
2.lua内存增长,但是gc不掉的情况
使用了云风写的lua snapshot,cloudwu/lua-snapshot,
原理也是获取两个时间点的内存snapshot进行对比,找新申请未清除引用的,注意不是未释放,释放由gc来进行。
跟着服务器压测时发现每处理一个player add消息会增加lua内存700k,且gc释放不掉
在连续的2个palyer add消息的时候截取lua snapshot,对比发现大量内存被同一地址引用,有关键数字,搜一下60010发现是某数据表里的数据,原来是重复缓存了数据表造成的。
3.lua数据表内存优化
策划添excel表,导成lua表为客户端和服务器所用,数据越来越多,占了50M。
通过分析发现很多数据都是一样的,分析需求建表的时候会刻意回避动不动就添一列且只有少数行会用到这一列的情况,但实际上还出现了不少。m行xn列的数据,增长是很快的。
想到了用默认值的方式,每列出现次数最多的数据当作默认值,专门建一行默认值表。m行*n列的数据中如果跟默认值一样,就不写到表里了,这样可以随意创建多列,即使利用率低也不会让内存爆炸。用原表的__index就能实现有自定义值时取自定义的,没有则取默认值的方式。
内存降低到33M,没有预期中降低的多。
还有一种方法是去掉key,m行*n列中只按下标1..n存数据,原表里存key到index的映射,适合一行中大多都不是默认值的情况,这个还没实施测试。
默认值和去key的方式是可以混用的,根据每行数据的特点2选1。
近段时间处理了一些Lua相关的性能和内存问题,分享记录下
1.lua内存增长很快,但gc可以降低的情况
一个小场景,角色站着不动内存就会稳定的增长,对比了unity profiler里的数据,没有特别显著的变化,但是lua内存增长了很多
执行lua gc后会大幅降低。说明是临时对象占用的内存,不gc释放不掉。也确实没开自动gc和定期gc,也算是为了暴露问题。
接着用windows sdk里的umdh(user mode dump heap)查出来是slua的pushVector3造成的
紧接着反查都哪里会调pushVector3,发现是lua和C#间进行Vector3类型转换的时候会用到,后来发现是小地图lua代码里每帧一次取UI组件的几个position,频率虽然不高,但引起的内存增长倒是不少。
项目开始的时候已经知道频繁调用transform.position等会有性能问题,所以专门写了不用进行vector3转换的SetPostion(x, y, z)等方法,但没有对position的相关方法做限制,口头约定不要用position接口,但还会有人不注意。现在干脆删掉了transform里position等相关的导出方法,用了就报错,强制使用自定义的setter和getter。让我再次想起来规范一定要做到工具里,或者形成强制限制或检查,不然就是没用的规范。
这次比较幸运,是特殊的pushVector3造成的,如果之后是lua里某些地方造成频繁的创建临时对象怕是都不好找到是哪块lua代码。
2.lua内存增长,但是gc不掉的情况
使用了云风写的lua snapshot,cloudwu/lua-snapshot,
原理也是获取两个时间点的内存snapshot进行对比,找新申请未清除引用的,注意不是未释放,释放由gc来进行。
跟着服务器压测时发现每处理一个player add消息会增加lua内存700k,且gc释放不掉
在连续的2个palyer add消息的时候截取lua snapshot,对比发现大量内存被同一地址引用,有关键数字,搜一下60010发现是某数据表里的数据,原来是重复缓存了数据表造成的。
3.lua数据表内存优化
策划添excel表,导成lua表为客户端和服务器所用,数据越来越多,占了50M。
通过分析发现很多数据都是一样的,分析需求建表的时候会刻意回避动不动就添一列且只有少数行会用到这一列的情况,但实际上还出现了不少。m行xn列的数据,增长是很快的。
想到了用默认值的方式,每列出现次数最多的数据当作默认值,专门建一行默认值表。m行*n列的数据中如果跟默认值一样,就不写到表里了,这样可以随意创建多列,即使利用率低也不会让内存爆炸。用原表的__index就能实现有自定义值时取自定义的,没有则取默认值的方式。
内存降低到33M,没有预期中降低的多。
还有一种方法是去掉key,m行*n列中只按下标1..n存数据,原表里存key到index的映射,适合一行中大多都不是默认值的情况,这个还没实施测试。
默认值和去key的方式是可以混用的,根据每行数据的特点2选1。
相关文章推荐
- 项目后期Lua接入笔记10--Lua代码优化1
- 项目后期Lua接入笔记07--预制属性转lua代码
- 项目后期Lua接入笔记01--框架及IDE
- 项目后期Lua接入笔记06--按钮事件监听及消息分发
- 项目后期Lua接入笔记03--LuaBehaviour设计
- 项目后期Lua接入笔记04--宏定义处理HelloWorld
- 项目后期Lua接入笔记09--策划Excel转Lua
- 项目后期Lua接入笔记05--网络协议protobuf在lua中的使用pbc
- 项目后期Lua接入笔记08--Lua面向对象及LuaBehaviour的再设计
- 项目后期Lua接入笔记02--框架剥离
- android项目后期优化-----代码重新封装/形成框架意识(http请求)
- android 笔记11 得到布局,状态栏显示隐藏,代码优化
- OA项目11:部门列表树状显示功能及其他代码优化
- 20121/1/4 oracle笔记 项目背景 242后期搭建个oracle数据库,现在还没做到的是更换ip地址时如何访问oem,企业管理器,搞了一下午没搞出来
- Android应用开发笔记 - 项目代码2
- iOS开发笔记--Xcode小技巧 统计项目的代码总行数
- java代码优化11大原则
- Android应用开发笔记 - 项目代码3
- SEO笔记--代码优化(三)
- 工作笔记总结——使用sonar进行代码优化