NLua性能对比:C#注册函数 vs 纯Lua实现

[复制链接]
发表于 2025-7-8 05:19:36 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
引言

在NLua开发中,我们常面临一个紧张选择:将C#函数注册到Lua环境调用,还是直接在Lua中实现逻辑? 直觉告诉我们,C#作为编译型语言性能更高,但跨语言调用的开销是否会影响整体性能?本文通过基准测试揭示真相。

测试场景

实现安全索引访问函数At,对比三种实现方式:

  • NativeLuaAt:纯Lua实现
  • CSharpRegisterAt:C#实现并注册到Lua
  • NativeCSharpAt:纯C#直接调用
测试环境:


  • .NET Framework 4.8.1
  • Intel Core i7-1260P
  • BenchmarkDotNet v0.15.0

性能数据对比

方法平均耗时内存分配NativeLuaAt6,844 ns288 BCSharpRegisterAt9,585 ns552 BNativeCSharpAt106 ns32 B


结论

出乎料想,直接在Lua中实现逻辑会更快,这里缘故原由可能是将C#函数注册到Lua环境调用涉及到上下文切换等耗时动作。
干系代码见NLuaBenchmarkDotNetTest
代码

Lua代码
  1. --[[
  2. 仅用于userdata索引访问函数,C#定义
  3. 参数:
  4.   tbl  : 目标Lua表(数组形式)
  5.   index: 索引值(支持正负索引)
  6.   strict: [可选]严格模式,默认false,设为true时额外校验元素连续性
  7. 返回值:
  8.   对应索引位置的元素
  9. 异常:
  10.   类型错误或索引越界时抛出错误
  11. --]]
  12. function At(tbl, index)
  13.     -- 参数校验阶段
  14.     -- 检查第一个参数是否为table
  15.     if type(tbl) ~= "userdata" then
  16.         error("bad argument #1 (expected table, got "..type(tbl)..")", 2)
  17.     end
  18.    
  19.     -- 检查索引是否为整数
  20.     if type(index) ~= "number" or math.floor(index) ~= index then
  21.         error("index must be integer, got "..type(index), 2)
  22.     end
  23.     -- 长度计算策略
  24.     local len = tbl.Length
  25.    
  26.     -- 严格模式下验证表连续性
  27.     -- 索引转换逻辑
  28.     local adjusted_index
  29.    
  30.     -- 处理正索引(userdata是 的0-based)
  31.     if index >= 0 then
  32.         adjusted_index = index
  33.     -- 处理负索引(从末尾倒数)
  34.     else
  35.         adjusted_index = len + index
  36.     end
  37.     -- 边界检查与错误处理
  38.     -- 有效索引范围:1 ≤ index ≤ len
  39.     if adjusted_index < 0 or adjusted_index >= len then
  40.         local direction = index >=0 and "positive" or "negative"
  41.         error(string.format("Index %d (%s) out of range [%d, %d]",
  42.                           index, direction, -len, len-1), 2)
  43.     end
  44.     -- 最终元素获取
  45.     return tbl[adjusted_index]
  46. end
复制代码
C#代码
  1.         /// <summary>
  2.         /// 安全索引访问器(支持Lua数组的0-based索引规则)
  3.         /// </summary>
  4.         /// <param name="collection">目标集合(支持IList接口的集合)</param>
  5.         /// <param name="index">索引值(支持负索引倒查)</param>
  6.         /// <param name="strict">严格模式校验元素连续性</param>
  7.         /// <returns>索引位置的元素</returns>
  8.         /// <exception cref="ArgumentNullException">输入集合为空</exception>
  9.         /// <exception cref="ArgumentException">集合类型不合法或索引无效</exception>
  10.         public static object At(IEnumerable collection, int index, bool strict = false)
  11.         {
  12.             // 参数基础校验
  13.             if (collection == null)
  14.                 throw new ArgumentNullException(nameof(collection), "输入集合不能为null");
  15.             // 类型安全转换
  16.             IList list = collection as IList;
  17.             if (list == null)
  18.                 throw new ArgumentException("输入集合必须实现IList接口", nameof(collection));
  19.             // 获取有效长度
  20.             int count = list.Count;
  21.             if (count == 0)
  22.                 throw new ArgumentException("集合中不包含有效元素", nameof(collection));
  23.             // 索引转换逻辑
  24.             int adjustedIndex = index >= 0 ? index : count + index;
  25.             // 边界校验
  26.             if (adjustedIndex < 0 || adjustedIndex >= count)
  27.             {
  28.                 string msg = $"索引 {index} 超出有效范围 [{-count}, {count - 1}]";
  29.                 throw new ArgumentOutOfRangeException(nameof(index), msg);
  30.             }
  31.             // 严格模式校验
  32.             if (strict)
  33.             {
  34.                 // 校验是否存在null元素
  35.                 for (int i = 0; i < count; i++)
  36.                 {
  37.                     if (list[i] == null)
  38.                     {
  39.                         throw new ArgumentException($"严格模式检测到空元素 @ 位置 {i}");
  40.                     }
  41.                 }
  42.             }
  43.             return ConvertToDouble(list[adjustedIndex]);
  44.         }
复制代码
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表