基于ToLua的C#和Lua内存共享方案保姆级教程
C#和Lua内存共享方案保姆级教程
前言
在介绍C#和Lua内存共享方案之前,先介绍下面两个点来支撑这个方案的必要性
跨语言交互很费
Lua和C#交互最早是基于反射的方式实现的,后来为了提升性能发展成Luajit+C#静态方法导出注入到lua虚拟机的方式至此Lua+Unity的性能才达到了实用的级别,但我们如果用的不好还是会存在诸多性能问题,具体的一些使用注意事项参考引用里《用好lua+unity,让性能飞起来——lua与c#交互篇》,用文章中的一个例子来加深一下我们lua点点调用一个对象的属性的写法在Lua+C#的组合模式下是有多么的费劲能,虽然写起来很轻松,但实际交互都是调用的虚拟栈,会经历压栈,出栈等操作,性能会随着调用次数的频繁和参数传递的越多而变的越差,看了下面的交互步骤之后就意识到尽可能的避免这种点属性的链式写法
game.bject.transorm.position = pos写法在项目中很常见,但大量使用就比较糟糕,因为每点一次属性就意味着要经过堆栈调用,有的甚至还要经过Dictionary容器查询操作,内部又是好几条指令,每一次指令就意味着时间开销,尽管一次很小但调用次数多了之后就可观了,要实现这个坐标赋值的操作,lua堆栈调用如下
第一步
GameObjectWrap.get_transform lua想从gameobj拿到transform,对应gameobj.transformLuaDLL.luanet_rawnetobj 把lua中的gameobj变成c#可以辨认的idObjectTranslator.TryGetValue 用这个id,从ObjectTranslator中获取c#的gameobject对象gameobject.transform 准备这么多,这里终于真正执行c#获取gameobject.transform了ObjectTranslator.AddObject 给transform分配一个id,这个id会在lua中用来代表这个transform,transform要保存到ObjectTranslator供未来查找LuaDLL.luanet_newudata 在lua分配一个userdata,把id存进去,用来表示即将返回给lua的transformLuaDLL.lua_setmetatable 给这个userdata附上metatable,让你可以transform.position这样使用它LuaDLL.lua_pushvalue 返回transform,后面做些收尾LuaDLL.lua_rawsetiLuaDLL.lua_remove
第二步:
TransformWrap.set_position lua想把pos设置到transform.positionLuaDLL.luanet_rawnetobj 把lua中的transform变成c#可以辨认的idObjectTranslator.TryGetValue 用这个id,从ObjectTranslator中获取c#的transform对象LuaDLL.tolua_getfloat3 从lua中拿到Vector3的3个float值返回给c#lua_getfield + lua_tonumber 3次 拿xyz的值,退栈lua_pop
transform.position = new Vector3(x,y,z) 准备了这么多,终于执行transform.position = pos赋值了
上面的内部堆栈调用说明了lua点属性或者方法调用比较费性能,语言交互代价比较"昂贵"
我们在用unity profiler的时候也会发现有的调用比较深的堆栈一页都拉不到底,当然可能是存在递归调用的情况,这调用嵌套越,执行花费的时间就越多,而上面的gameobject.transform每次如果临时使用很快就会被lua gc掉,下次再调用又会重新走一遍这个堆栈调用的流程就会很费性能
参数传递也很费
用传统的虚拟栈传递参数的方式同样的道理,尤其是Unity特有的值类型结构(Vector3,Quaternion等),lua中一个Vector3就是一个table,跟C#是Vector3是两种结构,就会涉及到这两种类型的转换,例如将C# Vector3传递给Lua,流程如下:
- C#中拿到Vector3的x、y、z三个值;
- Push这3个float给Lua栈;
- 然后构造一个表,将表的x,y,z赋值;
- 将这个表push到返回值里。
一个传vector的操作会经历三次push参数、表内存分配、和3次表插入等操作,虽然单次指令也就那么大几个,但这种频繁操作的代码会导致性能下降
目前项目中参数传递的两种方式
第一种、SendMessage的方式
通过Lua虚拟栈采用数据压栈和出栈的方式(获取对应的LuaTable的方法,传参的方式)


第二种、C#持有LuaTable
C#通过LuaState获取到对应的table,然后给这个table添加对应的数据,也可以添加上table,这种方式有明显的利弊,可读性差,如果采用哈希的结构会有key字符串的内存开销,针对复杂的嵌套类型写起来极其"恶心",下不了手,适合简单的类型还是可以考虑的

上面两种方式的性能对比
天之之前测试血条、蓝条将SendMessage的方式改成LuaTable共享的方式做的对比测试
-
SendMessage Call Function的方式

-
LuaTable共享的方式

由上面的图可见LuaTable的方式还是比方法调用的方式传参性能要好很多,但看他们性能图还是会稳定的性能尖峰,尽管是峰值从42ms降低到10ms,但稳定的10ms尖峰还是需要
相关文章:
基于ToLua的C#和Lua内存共享方案保姆级教程
C#和Lua内存共享方案保姆级教程 前言 在介绍C#和Lua内存共享方案之前,先介绍下面两个点来支撑这个方案的必要性 跨语言交互很费 Lua和C#交互最早是基于反射的方式实现的,后来为了提升性能发展成Luajit+C#静态方法导出注入到lua虚拟机的方式至此Lua+Unity的性能才达到了实…...
OpenCV与AI深度学习|16个含源码和数据集的计算机视觉实战项目(建议收藏!)
本文来源公众号“OpenCV与AI深度学习”,仅用于学术分享,侵权删,干货满满。 原文链接:分享|16个含源码和数据集的计算机视觉实战项目 本文将分享16个含源码和数据集的计算机视觉实战项目。具体包括: 1. 人…...
Vue 如何简单更快的对 TypeScript 中接口的理解?应用场景?
TypeScript 中接口(Interface)的理解与应用 在 TypeScript 中,接口(Interface) 是一种用来定义对象的结构或形状的方式。接口可以指定对象中应该包含哪些属性、这些属性的类型以及它们的函数签名。接口帮助我们在代码…...
R语言绘图过程中遇到图例的图块中出现字符“a“的解决方法
R语言绘图过程中遇到图例的图块中出现字符的解决方法 因为我遇到这个问题的时候没在网上找到合适的方法,找到个需要付费的,算了。也许是因为问的方式不同,问了半天AI也回答出来,莫名有些烦躁,打算对代码做个分析&…...
视图合并机制解析 | OceanBase查询优化
背景 在默认配置下,若查询语句中嵌入了视图,系统会先等待视图内部所包含的查询完全执行完成后,再继续执行父查询。这种方式造成优化器无法将视图查询与外层查询视为一个整体来进行优化处理,从而限制了优化效果。因此,…...
sql注入报错分享(mssql+mysql)
mysql mysql的报错内容比较多 网上也有比较多的 这里重复的就不多介绍了。一笔带过 溢出类 bigint 当超过mysql的整形的时候,就会导致溢出,mysql可能会将错误信息带出。这里user()是字母默认为0 取反以后1可能就会导致异常。 报错特征 BIGINT UNSIG…...
PHP 高并发解决方案
PHP作为一种脚本语言,在处理高并发请求时可能面临一些挑战。但通过合理的设计和优化,可以有效提升PHP应用程序的性能和并发处理的能力。 一、缓存 页面缓存:将生成的页面缓存起来,减少对数据库的查询,提高响应速度。…...
k8s1.30.0高可用集群部署
负载均衡 nginx负载均衡 两台nginx负载均衡 vim /etc/nginx/nginx.conf stream {upstream kube-apiserver {server 192.168.0.11:6443 max_fails3 fail_timeout30s;#server 192.168.0.12:6443 max_fails3 fail_timeout30s;#server 192.168.0.13:6443 max_fails3…...
多摩川编码器协议及单片机使用
参考: https://blog.csdn.net/qq_28149763/article/details/132718177 https://mp.weixin.qq.com/s/H4XoR1LZSMH6AxsjZuOw6g 1、多摩川编码器协议 多摩川数据通讯是基于485 硬件接口标准NRZ 协议,通讯波特率为2.5Mbps 的串行通讯,采用差分两…...
Android 网络通信(三)OkHttp实现登入
学习笔记 目录 一. 先写XML布局 二、创建 LoginResponse 类 :封装响应数据 目的和作用: 三、创建 MyOkHttp 类 :发送异步请求 代码分析 可能改进的地方 总结 四、LoginActivity 类中实现登录功能 详细分析与注释: 总结: 改进建议: 零、响应数据样例 通过 P…...
分享一下arr的意义(c基础)(必看)(牢记)
arr 即数组名 一般指数组首元素地址 在两种情况下不是 1:sizeof(arr) arr指整个数组简单讲解一下strlen与sizeof(c基础)_strzeof在c语言中什么意思-CSDN博客 2:printf("%p",&…...
AGENT AI 综述核心速览
研究背景 研究问题:这篇文章探讨了多模态人工智能(Agent AI)系统在理解和响应视觉和语言输入方面的潜力,特别是在物理和虚拟环境中的应用。Agent AI旨在通过感知和行动来增强人工智能系统的交互性和适应性。研究难点:…...
基于Java Springboot房屋租赁系统
一、作品包含 源码数据库设计文档万字PPT全套环境和工具资源部署教程 二、项目技术 前端技术:Html、Css、Js、Vue、Element-ui 数据库:MySQL 后端技术:Java、Spring Boot、MyBatis 三、运行环境 开发工具:IDEA/eclipse 数据…...
力扣 LeetCode 701. 二叉搜索树中的插入操作(Day10:二叉树)
解题思路: 全部插入到叶子节点即可 class Solution {public TreeNode insertIntoBST(TreeNode root, int val) {if (root null) {TreeNode node new TreeNode(val);return node;}if (root.val < val) {root.right insertIntoBST(root.right, val);}if (root…...
猎板科技:PCB 特殊定制领域的卓越引领者
一、专业团队,创新设计之源 猎板科技的核心竞争力首先源于其卓越的专业团队。这支队伍汇聚了经验丰富的资深工程师以及行业前沿的技术专家,他们在 PCB 设计领域拥有深厚的造诣和敏锐的洞察力。无论是面对常规 PCB 设计任务,还是应对极具挑战…...
centos stream 9安装docker教程
第一步:安装该dnf-plugins-core软件包(它提供了管理 DNF 存储库的命令) sudo dnf -y install dnf-plugins-core 第二步:设置存储库(这里使用的是阿里云的镜像源) sudo dnf config-manager --add-repo https://mirrors.aliyun.c…...
优化旧LabVIEW程序功能的方法
优化运行已久的LabVIEW程序时,需在不影响原有功能的基础上针对目标功能进行改进。以下结合一个数据采集功能优化的实例,详细说明操作步骤和注意事项,为工程师提供切实可行的方法。 优化背景 某企业的LabVIEW程序负责多通道数据采集…...
关于安卓模拟器或手机设置了BurpSuite代理和安装证书后仍然抓取不到APP数据包的解决办法
免责申明 本文仅是用于学习研究安卓系统设置代理后抓取不到App数据包实验,请勿用在非法途径上,若将其用于非法目的,所造成的一切后果由您自行承担,产生的一切风险和后果与笔者无关;本文开始前请认真详细学习《中华人民共和国网络安全法》【学法时习之丨网络安全在身边一…...
【电路笔记】-布尔逻辑AND函数
逻辑AND函数 文章目录 逻辑AND函数1、概述2、逻辑 AND 函数 仅当所有输入均为 true 时,逻辑与函数输出才为 true,否则输出为 false。 1、概述 布尔代数基于逻辑函数,其中每个布尔函数(例如逻辑 AND 函数)通常具有一个…...
C#(11) 运算符重载
前言 我们知道函数是可以重载的,重载后的作用是干嘛呢?其实就是为了方便适应不同的参数传递。 那运算符我们也可以理解是一个函数,只是我们希望为更多的参数引入运算符使得他们可以被计算。 c#设计这么一块功能,其实也是为了方…...
【原创改进代码】考虑电动汽车移动储能特性的多区域电网功率波动平抑优化调控附python代码
✅作者简介:热爱科研的Matlab仿真开发者,擅长毕业设计辅导、数学建模、数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。 🍎 往期回顾关注个人主页:Matlab科研工作室 👇 关注我领取海量matlab电子…...
Windows 11下Keil5 MDK与C51共存安装全攻略(附ST-Link驱动避坑指南)
Windows 11下Keil5 MDK与C51共存安装全攻略(附ST-Link驱动避坑指南) 在嵌入式开发领域,Keil作为经典开发工具链,其MDK(Microcontroller Development Kit)和C51版本分别服务于ARM架构和8051架构单片机开发。…...
intv_ai_mk11镜像部署教程:3条命令完成服务启动、状态检查、日志监控
intv_ai_mk11镜像部署教程:3条命令完成服务启动、状态检查、日志监控 1. 快速了解intv_ai_mk11 intv_ai_mk11是一款基于7B参数Llama架构的AI对话机器人,它能帮助你完成各种任务: 回答各类问题(技术、生活、知识等)辅…...
大厂高薪抢手!文科生如何抓住AI时代机遇,实现职业逆袭?
大厂纷纷高薪招聘文科生,引发社会关注。文科生凭借沟通、叙事、逻辑等优势,在大模型理解人类价值观、企业品牌宣传等方面发挥作用。高校也调整专业设置,培养跨学科人才。文章建议文科生根据自身专业,向文案策划、品牌宣传、法务、…...
零基础入门Python爬虫:借助快马AI生成你的第一个可运行爬虫脚本
今天想和大家分享一下我作为Python爬虫新手的学习经历。刚开始接触爬虫时,面对各种库和概念真的有点懵,直到发现了InsCode(快马)平台,它让我用自然语言描述需求就能生成可运行的代码,大大降低了入门门槛。 爬虫的基本原理 爬虫就像…...
Pspice仿真新手避坑大全:为什么你的TL431仿真总报错?可能是模型库没加对
Pspice仿真新手避坑大全:为什么你的TL431仿真总报错? 刚接触Pspice的工程师们,是否经常遇到这样的场景:精心设计的TL431电路图明明检查了无数遍,点击仿真按钮后却弹出一堆令人困惑的错误提示?这就像拼好了乐…...
像素冒险工坊初体验:维度裂变器真实使用报告,文字创作从未如此有趣
像素冒险工坊初体验:维度裂变器真实使用报告,文字创作从未如此有趣 1. 走进像素冒险工坊 当我第一次打开像素语言维度裂变器时,仿佛穿越回了16-bit游戏黄金年代。这款基于MT5-Zero-Shot-Augment核心引擎构建的文本增强工具,彻底…...
CSS 滚动驱动动画:让页面动起来的新维度
CSS 滚动驱动动画:让页面动起来的新维度代码如诗,滚动如歌。让我们用滚动驱动动画的魔法,为用户带来沉浸式的浏览体验。什么是滚动驱动动画? 滚动驱动动画(Scroll-driven Animations)是 CSS 中一项革命性的…...
避开这些坑!FFmpeg.wasm在Vue项目中的完整避坑指南(含SharedArrayBuffer报错解决方案)
FFmpeg.wasm在Vue项目中的深度实践与疑难解析 当现代Web应用需要处理音视频编辑、转码或流媒体时,FFmpeg.wasm正成为前端开发者的利器。本文将深入探讨如何在高安全要求的Vue项目中稳定集成这一技术方案,特别针对生产环境中可能遇到的SharedArrayBuffer限…...
双向充放电前馈控制:储能变流器PCS_PWM变流器的SVPWM调制与实现
【复现】储能变流器PCS_PWM变流器双向充放电前馈控制SVPWM调制 1、电路构成:三相电网、三相 PWM变流器、Buck/Boost 变换器和蓄电池 2、三相变流器控制:采用电压外环、电流内环双闭环PI 控制,电网电压和电容电流前馈,电感电流解耦…...
