Unity中SLua、Tolua、XLua和ILRuntime效率评测

2023-11-05

Unity脚本效率评测

对SLua、Tolua、XLua和ILRuntime四个脚本插件进行效率测试,对框架脚本进行选型。
本文项目:https://github.com/cateatcatx/UnityScriptPTest
tolua:https://github.com/topameng/tolua
slua:https://github.com/pangweiwei/slua
xlua:https://github.com/Tencent/xLua
ILRuntime:https://github.com/Ourpalm/ILRuntime

用例版本

Unity5.6.0p3
SLua 1.3.2
Tolua# github 2017/4/25 19:08:37
XLua 2.1.7
ILRuntime 1.11
Lua: luajit-2.1.0-beta2

测试环境

Smartian T2、Win7(64bit)

实验方案

总共设计了17个Test,分别从以下3个方面来考察脚本效率(JIT和非JIT),实验结果取10次的平均值,时间单位为ms。通过实验数据简单分析原因(Lua插件会横向对比,ILRuntime会单独考虑,因为毕竟C#和Lua本身差别较大)。

    1. Mono -> Script,Mono调用脚本
    2. Script -> Mono,脚本调用Mono
    3. Script自身,脚本自身执行效率

Mono -> Script

Test11 Test12 Test13 Test14 Test15 Test16 Sum
Tolua 186 449 598 407 577 759 2978
SLua 315 751 901 757 1253 1883 5863
XLua 145 924 1010 573 1507 1929 6091
ILRuntime 711 422 368 379 397 393 2672
Tolua(JIT) 168 454 592 416 578 826 3037
SLua(JIT) 384 842 956 824 1328 3439 7775
XLua(JIT) 189 957 1047 608 1540 1700 6043
ILRuntime(JIT) 1232 892 903 969 1175 1102 6275

Lua分析:

-- Test11
function EmptyFunc()
    _V0 = _V0 + 1
end

_V0 = 1 -- Test12
_V1 = "12345" -- Test13
_V2 = GameObject.New() -- Test14
_V3 = Vector3.New(1, 2, 3) -- Test15
_V4 = {1, 2, 3} -- Test16

Test11为Mono调用脚本中空方法,Test12~16为测试Mono到脚本中取变量(ILRuntime代码类似,访问类的static函数与变量)。ILRuntime因为没有变量类型的转换所以效率最为优秀(JIT模式下使用的是Mono的反射取值所以会更慢,ILRuntime内部可能对类型变量有缓存,所以比反射快很多),Lua中可以看到Tolua的综合性能尤为突出(所有测试均好于其他Lua)。
对比Tolua和SLua的实现发现,Tolua会尽量减少与C++通信的次数,因为c#与c++通信会有一定效率损耗(参数的Marshaling等),虽然是Mono与Lua通信,但是其中还夹着一层C++,所以Mono与Lua通信的主要优化思路就是减少与C++的通信,从实验数据来看Tolua的这种优化效果是很明显的。

// SLua的函数调用
public bool pcall(int nArgs, int errfunc)
{

    if (!state.isMainThread())
    {
        Logger.LogError("Can't call lua function in bg thread");
        return false;
    }

    LuaDLL.lua_getref(L, valueref);

    if (!LuaDLL.lua_isfunction(L, -1))
    {
        LuaDLL.lua_pop(L, 1);
        throw new Exception("Call invalid function.");
    }

    LuaDLL.lua_insert(L, -nArgs - 1);
    if (LuaDLL.lua_pcall(L, nArgs, -1, errfunc) != 0)
    {
        LuaDLL.lua_pop(L, 1);
        return false;
    }
    return true;
}

// Tolua的函数调用
public void Call()
{
     BeginPCall();
     PCall();
     EndPCall();
}
public int BeginPCall(int reference)
{                        
    return LuaDLL.tolua_beginpcall(L, reference);
}

public int LuaPCall(int nArgs, int nResults, int errfunc)
{
    return LuaDLL.lua_pcall(L, nArgs, nResults, errfunc);
}

public void LuaSetTop(int newTop)
{
    LuaDLL.lua_settop(L, newTop);
}

对比SLua和Tolua代码的函数调用部分,发现SLua的C++调用多余Tolua两倍左右,所以效率高下立见。变量读取读者可以自行对比,总结就是Tolua通过减少C++调用的方式来优化效率,后期对Lua的进一步优化也要遵循这个思路。


ILRuntime分析:
实验发现解释执行下,ILRuntime的获取变量的效率要明显好于Lua,主要是因为都是C#对象,不需要进行类型转换。ILRuntime的JIT模式其实是用的Mono的,效率反而比解释执行更低,猜测是因为JIT下主要采用反射调用函数和取变量,而ILRuntime的解释器可能内部有缓存(因为没看过实现,都是不负责任猜测)。

Script->Mono

Test0 Test1 Test2 Test3 Test4 Test5 Test6 Test7 Test10 Sum
Tolua 675 797 1410 354 839 343 407 1681 915 7426
SLua 768 640 2305 466 1110 408 394 3379 1299 10774
XLua 590 648 8504 450 775 1213 695 1267 845 14989
ILRuntime 1152 1054 4012 315 998 437 1026 3272 1434 13703
Tolua(JIT) 612 701 7.4 357 823 318 37 128 884 3871
SLua(JIT) 732 679 5.4 465 1197 411 10 165 1307 4974
XLua(JIT) 636 668 8312 438 767 1303 734 1340 911 15113
ILRuntime(JIT) 72 197 84 260 402 33 219 303 77 1651

Lua分析:

function Test0(transform)   
    local t = os.clock()

    for i = 1,200000 do
        transform.position = transform.position
    end

    return os.clock() - t
end

function Test1(transform)           
    local t = os.clock()
    for i = 1,200000 do
        transform:Rotate(up, 1) 
    end

    return os.clock() - t
end

function Test2()    
    local t = os.clock()

    for i = 1, 2000000 do
        local v = Vector3.New(i, i, i)
        local x,y,z = v.x, v.y, v.z
    end

    return os.clock() - t
end

function Test3()
    local t = os.clock()    

    for i = 1,20000 do              
        GameObject.New()
    end

    return os.clock() - t
end

function Test4()    
    local t = os.clock()
    local tp = typeof(SkinnedMeshRenderer)

    for i = 1,20000 do              
        local go = GameObject.New()
        go:AddComponent(tp)
        local c = go:GetComponent(tp)
        c.receiveShadows=false
    end

    return os.clock() - t
end

function Test5()
    local t = os.clock()

    for i = 1,200000 do     
        local p = Input.mousePosition
        --Physics.RayCast
    end

    return os.clock() - t
end

function Test6()    
    local Vector3 = Vector3 
    local t = os.clock()

    for i = 1, 200000 do
        local v = Vector3.New(i,i,i)
        Vector3.Normalize(v)
    end

    return os.clock() - t
end

function Test7()        
    local Quaternion = Quaternion
    local t = os.clock()

    for i=1,200000 do
        local q1 = Quaternion.Euler(i, i, i)        
        local q2 = Quaternion.Euler(i * 2, i * 2, i * 2)
        Quaternion.Slerp(Quaternion.identity, q1, 0.5)      
    end

    return os.clock() - t
end

function Test10(trans)
    local t = os.clock()

    for i = 1, 200000 do
        UserClass.TestFunc1(1, "123", trans.position, trans)
    end 

    return os.clock() - t
end

总体效率还是Tolua胜出,其中XLua在Test2中较比SLua、Tolua差出不止一个数量级,主要是因为Tolua和SLua对于Unity的值类型变量做了lua的实现,这种值类型SLua和Tolua中是一个table,而在XLua中是一个Userdata,所以SLua和Tolua在做Test2的时候并没有跟Unity交互(从JIT结果也能看出来,JIT不能处理C函数,所以JIT后Test2效果提升明显),而XLua需要频繁和Unity交互,效率消耗明显。对于对象类型的变量,3种lua处理机制是雷同的,只是内部实现细节不一样而已,细节不再本文讨论范围内,从实验数据上来看,还是Tolua的内部实现更加效率。用好lua+unity,让性能飞起来——lua与c#交互篇,这篇文章对C#与Lua的交互原来有非常详细的说明,虽然插件后续有改进,但是核心思想还是不变的。


ILRuntime分析:
数据上来看ILRuntime解释器的效率还是很高的并不比lua慢太多,但是对于Vector3这种Unity值类型的处理跟lua差距比较大(主要是因为SLua和Tolua中的Unity值类型其实就是table,等于没有跟Unity交互)。ILRuntime还是一个很有潜力的Unity热更解决方案的,毕竟C#配合VS的开发效率还是比Lua高不少的。其中的JIT部分是Mono层的,跟本身的C#代码是没有区别的,不参与对比。

Script自身

Test8 Test9 Sum
Tolua 254 4246 4500
SLua 255 4766 5022
XLua 311 4506 4817
ILRuntime 852 79048 79900
Tolua(JIT) 46 371 417
SLua(JIT) 48 414 463
XLua(JIT) 40 469 510
ILRuntime(JIT) 222 313 536
function Test8()
    local total = 0
    local t = os.clock()

    for i = 0, 1000000, 1 do
        total = total + i - (i/2) * (i + 3) / (i + 5)
    end

    return os.clock() - t   
end

function Test9()
    local array = {}

    for i = 1, 1024 do
        array[i] = i
    end

    local total = 0
    local t = os.clock()

    for j = 1, 100000 do
        for i = 1, 1024 do
            total = total + array[i]
        end         
    end

    return os.clock() - t
end

因为Lua全部使用的是LuaJIT2.1.0B2版本,所以其实脚本自身的效率理论上应该是一致的,从数据上看也差不多。实验结果上主要体现了Lua解释器的速度要明显好于ILRuntime(语言内部实现不一样,勉强对比在一块,毕竟lua是c写的),并且发现LuaJIT对效率的提升也是好几个数量级,虽然LuaJIT很多坑,但是如果能用好还是个优化利器。

总结

综合来看Tolua是现在效率较好的Unity Lua解决方案,后续会对Tolua的内部实现做进一步剖析,从来做进一步的效率优化。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Unity中SLua、Tolua、XLua和ILRuntime效率评测 的相关文章

  • 几种前端h264播放器记录

    近期做了点工作记录一下 主要是将H264流在html5上进行播放 众所周知 大多数的 video组件都是支持FLV或者MP4以及m3u8格式的 而如果是WebRTC是直接集成好了 本次要求的环境主要是通过Websocket方式进行流传输 不
  • pandas 生成excel 和 csv

    import pandas as pd a a b c b 1 2 3 dit char a num b file path r output xlsx writer pd ExcelWriter file path df pd DataF
  • leaflet常用插件库

    1 常用地图切换加载 osm google baidu gaode tianditu etc https github com htoooth Leaflet ChineseTmsProviders 2 切片地图加载 wmts 支持矢量切片
  • 如何获取节点的方法,动态计算节点高度

    监听节点偏移量 onScroll e const scrollTop e detail 根据组件的高度 计算当前的区间在哪个位置 this data scrollIntoview this data activeKey this getAc
  • 冒泡排序和快速排序的分析与比较

    冒泡排序 就是相邻的两个元素相互比较并根据比较结果决定是否交换位置 如从小到大排序 相邻两个元素两两比较 将值更大的元素交换到右侧 如此到最后一个元素 就能确定最大的一个值 一轮排序结束 若某一轮排序交换位置的次数为0 则排序结束 冒泡排序
  • GC0063-51单片机手持可充电VL53L01激光测距离测量报警倒车雷达防撞报警视力保护

    实践制作DIY GC0063 51单片机手持激光测距离测量 一 功能说明 基于51单片机设计 51单片机手持激光测距离测量 二 功能介绍 STC89C52单片机 lcd1602 VL53L01激光测距 锂电池充电电路 18650锂电池 继电
  • 基于时序数据处理的分布式光伏功率预测系统

    摘要 目的 使用高质量的历史数据预测未来光伏发电功率 对高效利用太阳能可再生能源 补充电网供电能力和推进节能减碳具有重要意义 方法 由于光伏时序数据质量参差不齐 本文提出了面向光伏时序数据的缺失值与异常值处理算法 并基于此搭建了分布式光伏功
  • 医学自然语言处理(NLP)相关论文汇总之 EMNLP 2021

    医学自然语言处理 NLP 相关论文汇总之 EMNLP 2021 写在前面 EMNLP2021前段时间已经放榜 一直没时间整理 最近抽时间整理了一下该会议在医疗自然语言处理方向上的相关论文 放在这里 希望对大家有一定的帮助吧 还会继续更新 大
  • Unity3D获得Android和iOS设备的唯一标识

    前言 android为mac地址 ios为advertisingIdentifier 函数都比较简单 网上也搜得到 我也就不多说了 主要是对于我们没做过安卓和IOS开发的人来说 整合进工程有各种的问题 我也就直接上网盘了点击打开链接 代码包
  • 【ant design vue】图片上传(一)

    官网是这样的 action 官网说不管是否使用都不能空着 但是实际上 在我的项目中是没有使用到的 我们是动态上传到后端 然后后端返回一个图片地址给我们显示在前台 代码如下 accept 是限制图片上传类型 customRequest 是自定
  • android edittext 数字正则,一个带有正则匹配的EditText

    先上效果 说明 图中的EditText能够在失去焦点后验证输入框中的文本是否与正则表达式匹配 这里我设置的是5位整数 d 5 当输入110时 不匹配 边框变红并抖动 文本清除 gif中白色文本是因为录制的问题 实际文本已清除 输入12306
  • windows10 powershell窗口输出卡住(看这篇就够了)

    问题原因 cmd窗口开启了快速编辑模式 当点击窗口时运行的进程会被暂停直至点击回车按钮 解决方案 取消勾选快速编辑模式 1 第一步 右键标题栏 选择 属性 第二步 选择 编辑选项 区域 取消 快速编辑模式 的选项 如图所示
  • Linux安装mysql5.7.26 --(傻瓜版3分钟搞定)

    前言 在这之前的一天时间里 我全网搜mysql 的各种安装方式 还有版本不同带来的问题 会发现在 Mac 或者 在linux上安装5 7 一下版本时 出现的问题会少很多 尤其是 拿着 dmg文件在Mac 安装 就是1分钟的事 但是在linu
  • Qt 中实现阴影窗口

    阴影窗口的实现方法一般有三种 方法一是 在窗口的构造函数中设置窗口的属性为 setAttribute Qt WA TranslucentBackground 从而保证窗口不被绘制的部分透明化 接着重写绘制函数paintEvent 其代码示例
  • 变量、作用域与内存

    目录 原始值与引用值 动态属性 复制值 传递参数 确定类型 执行上下文与作用域 作用域链增强 变量声明 1 使用var 的函数作用域声明 2 使用let 的块级作用域声明 3 使用const 的常量声明 标识符查找 垃圾回收 标记清理 最常
  • MPI测试程序

    include
  • mysql cmd命令行 创建数据库 表 基础语句

    一 连接MYSQL 格式 mysql h主机地址 u用户名 p用户密码 1 连接到本机上的MYSQL 首先打开DOS窗口 然后进入目录mysql bin 再键入命令mysql u root p 回车后提示你输密码 注意用户名前可以有空格也可

随机推荐

  • A*寻路算法 lua

    function InitMap self AMap for i 1 10 do self AMap i for j 1 10 do local map map x i map y j map g 999 map h 0 map f 0 m
  • 如何运行一个CFDEM tutorial case

    新手入门 万里长征第一步 安装完CFDEM后 我们知道有很多tutorial可以教我们怎么设置合理的参数 很多tutorial case里都有写好的Allrun脚本 最简单的方法就是运行Allrun脚本走一遍流程 准备工作 复制随便一个tu
  • 当里个当,免费的HTML5连载来了《HTML5网页开发实例详解》连载(一)

    读懂 HTML5网页开发实例详解 这本书 你还在用Flash嘛 帮主早不用了 乔布斯生前在公开信 Flash之我见 中预言 像HTML 5这样在移动时代中创立的新标准 将会在移动设备上获得胜利 国际巨头Google 苹果等都支持HTML 5
  • IDEA写爬虫,配jsoup

    环境变量配了 jdk的lib目录下也加了jsoup的jar包 返回IDEA还是没有 点击左上角的File进Project Setting SDKs 选择自己的jdk文件 在右侧点击 把jar包导进来
  • K8S 安装步骤

    K8S 安装步骤 一 为每台机器安装docker 1 安装docker 1 1 卸载旧版本 sudo yum remove docker docker client docker client latest docker common do
  • 【游戏开发】[用代码创建unity5.X的动画状态机]

    不废话 上代码 可能有的人 会质疑 这不是editor的功能吗 是的 但是这个允许在运行时候使用 你们跟一下代码看看继承于哪里就知道了 using UnityEngine using System Collections using Sys
  • JAVA-时间日期格式转换

    第一种方式 获取当前时间然后按照指定格式转换成String类型 DateFormat dateFormat new SimpleDateFormat yyyy MM dd HH mm ss Calendar cal Calendar get
  • 【Shell牛客刷题系列】SHELL31 netstat练习3-输出每个IP的连接数

    该系列是基于牛客Shell题库 针对具体题目进行查漏补缺 学习相应的命令 刷题链接 牛客题霸 Shell篇 该系列文章都放到专栏下 专栏链接为 专栏 Shell 欢迎关注专栏 本文知识预告 本文复习了awk grep sort uniq命令
  • DEiT实战:使用DEiT实现图像分类任务(二)

    文章目录 训练 导入项目使用的库 设置随机因子 设置全局参数 图像预处理与增强 读取数据 设置模型 train py train dist py 定义训练和验证函数 训练函数 验证函数 调用训练和验证方法 运行以及结果查看 测试 完整的代码
  • win10 git bash 设置别名

    使用git挺久时间 每次输入需要敲入长命令已感费劲 zshell git 有不少别名 可以提高输入效率 从而寻找windows下设置 git bash 别名的方法 环境 git v2 22 0 win10 方法1 通过 profile 文件
  • 使用gtest做单元测试

    使用gtest做单元测试 文章目录 使用gtest做单元测试 1 用gtest写测试工程的大致流程 配置gtest头文件及库 gtest的相关概念 TEST与TEST F 断言 事件机制 参考 gtest是一个跨平台的 Liunx Mac
  • Pycharm 常用快捷键

    常用快捷键 快捷键 功能 Ctrl Q 快速查看文档 Ctrl F1 显示错误描述或警告信息 Ctrl 行注释 可选中多行 Ctrl Alt L 代码格式化 Ctrl Alt O 自动导入 Ctrl Alt I 自动缩进 Tab Shift
  • 【网络】多路转接——poll

    作者 一只大喵咪1201 专栏 网络 格言 你只管努力 剩下的交给时间 书接上文五种IO模型 select poll epoll poll 认识接口 简易poll服务器 poll的特点 epoll 认识接口 epoll原理 简易epoll服
  • CentOS7 安装Redis6过程详解

    CentOS7 安装Redis6过程详解 一 安装redis 1 下载Redis 2 解压 3 使用make编译 4 编译完成后在目录中执行make install安装redis服务 5 安装完成 二 设置redis后台运行以及远程连接 1
  • 华为OD机试 - 找车位(Java)

    题目描述 停车场有一横排车位 0代表没有停车 1代表有车 至少停了一辆车在车位上 也至少有一个空位没有停车 为了防剐蹭 需为停车人找到一个车位 使得距停车人的车最近的车辆的距离是最大的 返回此时的最大距离 输入描述 一个用半角逗号分割的停车
  • Zookeeper 基本数据模型

    介绍 ZooKeeper是一个树形结构 类似于前端开发中的tree js组件 ZooKeeper的数据模型也可以理解为linux unix的文件目录 usr local 每个节点都称为znode 它可以有子节点 也可以有数据 每个节点分为临
  • 正则表达式-分组与后向引用

    前文中 已经总结了正则表达式中的常用字符 次数匹配 位置匹配等 这篇文章中 我们来了解一下正则中的 分组 与 后向引用 什么是分组 什么是后向引用 我们慢慢聊 先来说说什么是分组 算了 思考了半天 我也不知道从何说起 先看个示例吧 根据示例
  • 对NetBackup 问题进行故障排除的步骤

    错误消息通常是指出哪里出现故障的手段 如果在界面上没有看到错误消息 但仍怀疑有问题 请检查报告和日志 NetBackup提供了各种报告和日志记录工具 这些工具可提供错误消息 直接为您指出解决方案 日志还可显示什么运行良好以及当发生问题时Ne
  • html设置 元素最小宽度,css如何让元素宽度自适应屏幕大小

    如今 手机的快速发展使得越来越多的人开始使用手机上网 那么就会出现一个问题 如何才能让PC端的网页在手机上正常显示 让元素能够自动适应不同的屏幕大小呢 css如何让元素宽度自适应屏幕大小 1 在网页代码的头部 加入一行viewport元标签
  • Unity中SLua、Tolua、XLua和ILRuntime效率评测

    Unity脚本效率评测 对SLua Tolua XLua和ILRuntime四个脚本插件进行效率测试 对框架脚本进行选型 本文项目 https github com cateatcatx UnityScriptPTest tolua htt