最新文章
泰课在线 | 微信拼团成功后如何获取课程?
08-09 17:57
Unity教程 | 使用ARKit为iOS开发AR应用
07-31 17:23
Unity Pro专业版7折订阅四选一工具包之VR开发与艺术设计
07-28 11:47
网友使用虚幻UE4实现CAVE 多通道立体渲染的沉浸式环境
07-27 11:57
VR晕动症调查:未来5年内大部分VR晕动症将得到解决
07-27 11:26
AMD CEO:未来3-5年最重要 希望5年达1亿VR用户
07-27 10:44
Unity项目常见Lua解决方案性能比较
测试说明
Unity不支持热更新一直是一个令人困扰的痛点。作者在第一个项目上线后,深刻体会到每次更新的代价巨大,然而官方路线图中却迟迟未推出热更新功能。
UWA此前分享过Android平台热更新解决方案,直接替换dll是一种可行方式,但在iOS上由于使用IL2CPP而无法实现,这本质上是商业原因而非技术问题。另一个常见的解决方案是使用Lua。考虑到作者的不少同事之前有Cocos2d - lua开发经验,且有对应的后端框架如Skynet,因此在立项时,作者考虑采用Unity + Lua的方式进行开发。
测试内容
本次测试结果包含以下三种解决方案的比较:
- slua, commit #ef57252
- ulua, commit #dbe98bc(作者已不再维护,转至tolua)
- tolua, commit #710dedc
注意事项
- 当然还存在其他解决方案,如CsTolua,但由于作者精力有限,无法一一测试,欢迎提交Pull Request。本次测试将slua和tolua版本升级到最新(ulua原本就是最新)。
- 为避免不必要的争端,强调本次测试仅考虑解决方案本身的性能差异。对于有人提出“ulua在iOS下面用的是lua原生vm,跟slua用的luajit有啥好比的?”的疑问,如果有人愿意提供luajit版本,作者很乐意从使用者角度再进行测试。
- benchmark中的数据是作者测试的真实结果,仅供参考。而且slua/ulua在OSX编辑器下有几个结果比较异常,若有知道原因的朋友,还望不吝告知。
- 作者以slua的Test Case为范本,具体代码请参考slua Perf文件,然后在其他两个项目中复制了一遍。每个测试都统计了lua的os.clock()时间差、C#的Profiler.BeginSample()和Profiler.EndSample()。
测试环境
- UWA在原作基础上,对最新的Lua版本用更多机型(iPhone 4s、iPhone 5s)进行了测试作为补充,同时对原部分数据进行了修正。所使用的测试代码和原作一样,依然是6个测试用例。测试方法也相同,每个测试顺序执行五次,然后重启。
- 目前UWA只测试了目前使用最广泛的移动平台(Android和iOS)。
测试代码
Test1
function test1()
local transform = cube.transform
local start = os.clock()
for i=1,200000 do
transform.position=transform.position
end
print("test1/lua " .. ((os.clock() - start) * 1000));
end
Test2
function test2()
local transform=cube.transform
local start = os.clock()
for i=1,200000 do
transform:Rotate(Vector3.up, 90)
end
print("test2/lua " .. ((os.clock() - start) * 1000));
end
Test3
function test3()
local start = os.clock()
for i=1,2000000 do
local v = Vector3(i,i,i)
Vector3.Normalize(v)
end
print("test3/lua " .. ((os.clock() - start) * 1000));
end
Test4
function test4()
local t = cube.transform
local v = Vector3.one
local start = os.clock()
for i=1,200000 do
local v = GameObject()
end
print("test4/lua " .. ((os.clock() - start) * 1000));
end
Test5
function test5()
local v = cube.transform.position
local start = os.clock()
for i=1,20000 do
local v = GameObject()
v:AddComponent(SkinnedMeshRenderer)
local c=v:GetComponent(SkinnedMeshRenderer)
c.shadowCastingMode=0
c.receiveShadows=false
end
print("test5/lua " .. ((os.clock() - start) * 1000));
end
Test6
function test6()
local transform=cube.transform
local start = os.clock()
for i=1,200000 do
local t=Quaternion.Euler(100,100,100)
local q=Quaternion.Slerp(Quaternion.identity,t,0.5)
end
print("test6/lua jit " .. ((os.clock() - start) * 1000));
end
Android平台测试结果
以下为UWA在Android上对高、中、低配置的三款设备进行测试后得到的平均数据。图中下方的表格部分为柱状图的准确数值,其数值表示完成测试用例所需的时间,单位为毫秒。
- 低端设备:三星S3(Android OS 4.3) 注:红色部分的数值已远超其他的测试数据,因此UWA进行了截断显示,具体数值可见下方的表格。
- 中端设备:红米Note2(Android OS 5.0.2)
- 高端设备:三星S6(Android OS 6.0.1)
iOS平台测试结果
以下为UWA在iOS上对armv7和arm64的两款设备进行测试后得到的平均数据。测试中使用了il2cpp+Universal的发布方式,同时禁用了bitcode。图中下方的表格部分为柱状图的准确数值,其数值表示完成测试用例所需的时间,单位为毫秒。
- armv7设备:iPhone 4s (OS 7.1.2)
- arm64设备:iPhone 5s(OS 9.3.5)
总结
- 在Android设备上,slua在Test 2和3上表现较为出色,这两个测试用例主要涉及大量的向量操作。而tolua在Test 1、4和5上较为占优,这三个测试主要是组件属性的赋值和GameObject的创建等操作。ulua在中高端设备上的性能基本介于两者之间,但在低端机上有较为明显的性能问题。
- 在iOS设备上,tolua的性能表现最佳,ulua次之,slua的性能较tolua和ulua稍逊一筹。其中,Test3中slua的向量操作在iOS设备上耗时较高。目前暂时无法给出原因,但在多款iOS设备上测试均得到相似结论,值得研发团队注意。
以上是对目前市面上主流Lua版本的性能分析,希望对大家在Lua版本的选择和使用上有所帮助。需要说明的是,框架的选择不应仅考虑性能,还需考虑可维护性、稳定性等其他维度。本次测试仅供性能层面的参考,如有相关疑问,可加入相关技术QQ群交流讨论:446956587。