首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

黑科技:魔改TProto优化掉100MB的Lua内存

在前面有专门写一篇lua是怎样占用内存的: Lua数据的内存结构 - 知乎 (zhihu.com) 如果你的游戏也是一个lua开发的重度游戏,你可能会观察到其中有个结构TProto占用的内存非常夸张,...他的内存计算规则如下: 这里可以看到,lua计算内存时耍了一个小聪明,只是他认为需要计算的部分加了起来,而其中有一个占用内存比较大块的字段lineinfo,是没有被计算进内存里的 我们可以通过注释看到...方案3: 因为还剩了4分支1内存,还有没有办法再压缩一下这部分内存呢?...所以我们就可以这个代码改为一个BitArray,每一位代一行,如果相比前一个增加了1行,就设为1,否则为0,这样1字节就可以表示8个字节码的行号。最终内存占用就变成了原来的32分支1。...那么也可以像C++那样,符号信息离线存成一个符号,不跟着字节码一起打包对外发布。

1.7K20
您找到你想要的搜索结果了吗?
是的
没有找到

Lua中函数的使用

这里所谓的“一系列表达式”Lua中表现为4种情况:多重赋值、函数调用时传入的实参列表、构造器和return语句。...不过,某些罕见的情况下,如果可变长参数中包含无效的nil,那么{…}获得的可能不再是一个有效的序列。此时,就没有办法中判断原始参数究竟是不是以nil结尾的。...pack参数列表转换成Lua语言中一个真实的列表,而unpack则Lua语言中的真实的列表转换成一组返回值,进而可以作为另一个函数的参数被使用。...正确的尾调用 Lua语言中有关函数的另一个有趣的特性是,Lua语言是支持尾调用消除的。这意味着Lua语言可以正确地尾递归,虽然尾调用消除的概念并没有直接涉及递归。 尾调用是被当作函数调用使用的跳转。...-- 必须返回值限制为1个 lua语言中,只有形如return func(args)的调用才是尾调用。

1.6K20

【游戏开发】小白学Lua——从Lua查找元素的过程看元、元方法

引言 在上篇博客中,我们简单地学习了一下Lua的基本语法。其实在Lua中有一个还有一个叫元的概念,不得不着重地探讨一下。元实际地开发中,也是会被极大程度地所使用到。...本篇博客,就让我们从Lua查找元素的过程,来探讨学习一下Lua中的元。 一、什么是元 Lua table中我们可以访问对应的key来得到value值,但是却无法对两个table进行操作。...通俗来说,元就像是一个“操作指南”,里面包含了一系列操作的解决方案,例如__index方法就是定义了这个索引失败的情况下该怎么办,__add方法就是告诉table相加的时候应该怎么做。...很多人对Lua中的元和元方法都会有一个这样的误解:“如果A的元是B,那么如果访问了一个A中不存在的成员,就会访问查找B中有没有这个成员”。...Lua查找一个元素的规则可以归纳为如下几个步骤: Step1:自身中查找,如果找到了就返回该元素,如果没找到则执行Step2; Step2:判断该是否有元(操作指南),如果没有元,则直接返回

1.5K30

c语言中的用户自定义类型

当然,我们可以Lua中用来表示实现布尔数组。但是,C语言实现中,可以将每个布尔值存储一个比特中,所使用的内存量不到使用方法的3%。...,我们创建了一个数组用户获取分配给metaarray的元(我们无法Lua中设置用户数据的元,但是可以获取用户数据的元)。...每次使用lua_pushlightuserdata压入相同的地址时,我们都会得到相同的Lua值,也就是注册中相同的元素。 Lua语言中另一种典型的场景是Lua语言对象当做对应的C语言对象的代理。...例如,假设在输入/输出系统中有某些回调函数(例如,那些告诉我们还有多少数据需要被读取的函数),回调函数接收它要操作的C语言流,那么如何从中得到其相应的Lua对象呢?...回调函数中,一旦有了流地址,就可以将其作为轻量级用户数据,它当做这张的索引来获取对应的Lua对象(这张很可能得事弱引用的;否则,这些完全用户数据可能永远不会被作为垃圾回收)。

1.2K30

EmmyLua Attach Debugger浅析

尝试目标调试进程中开启一个独立的线程执行Backend的初始化 11. Backend初始化线程中尝试根据进程信息查找所有需要的Lua Api函数 12....没有正常的工作, 一开始我以为我们引擎的lua api没有正确导出, 后面通过检测引擎本身的代码, 以及使用dependency.exe进行查看, 确认我们的Core.dll中有导出所有的lua5.3的...定位后发现是emmylua中对5.2+的Lua版本, 依然使用lua_upvalueindex(4)的方式尝试获取global的索引, 这种方式lua5.2+已经不在支持, 所以会出现push到栈顶进行操作的...的错误处理函数退出后, 调用原来的Lua错误处理函数, 一般会将栈顶(-1位置)的变量当成字符串来处理, 因为栈顶并不是字符串, 会直接触发崩溃, 简单报错的message push回栈顶, 程序即可正常工作了...浅析>>中再去展开, 实现RemoteDebug的C++版加深了我对Attach版细节的理解, 这两个调试器EmmyLua的作者阿唐应该已经打算重构了, 对于我而言, 处理问题的过程中熟悉了一个Lua

2.8K10

lua学习笔记

它被保存在 C 注册一个特别索引下。 Lua 中,全局变量被初始化为这个值。 ( 不被内部任何地方使用。)...所以,在编译或运行 Lua 代码块的过程中,无论何时发生错误, 控制权都返回给宿主,由宿主负责采取恰当的措施(比如打印错误消息)。 元及元方法 Lua 中的每个值都可以有一个。...这个 元 就是一个普通的 Lua , 它用于定义原始值特定操作下的行为。 利用元可以修改值的默认行为。 垃圾收集 Lua 采用了自动内存管理。...a = [[alo 123"]] a = [==[ alo 123"]==] 变量 Lua 中有三种变量: 全局变量、局部变量和的域。...变量的首次赋值之前,变量的值均为 nil。 语句 Lua 一个代码块当作一个拥有不定参数的匿名函数 来处理。 正是这样,代码块内可以定义局部变量,它可以接收参数,返回若干值。

91620

【游戏开发】小白学Lua(上)

);   Lua中有几个标准库,它们提供了输入输出、算术计算、字符串操作等一系列的功能函数。...Lua中,有3中不同的变量:global(全局)、local(局部)、table fields()。如果一个变量没有用local修饰的话,那么它默认就是global的。...一个变量被赋值之前,它的值是nil。 2.Lua类型 Lua中有以下的8种基本数据类型:   (1)Nil空     nil和其他的类型都不同,她用来表示没有意义,空值。...    table是Lua中一种非常重要也非常强大的数据类型,你可以看成一种关联数组或者哈希。...这意味着你不但可以用整数来索引一个,也可以使用任何类型的键值来索引一个,而且lua是混合类型的,它们可以包含不同的数据类型。

1.7K30

Lua菜鸟②】数据类型

table Lua 中的(table)其实是一个"关联数组"(associative arrays),数组的索引可以是数字或者是字符串。... Lua 里,table 的创建是通过"构造表达式"来完成,最简单构造表达式是{},用来创建一个。...对于全局变量和 table,nil 还有一个"删除"作用,给全局变量或者 table 表里的变量赋一个 nil 值,等同于它们删掉,执行下面代码就知: ?...table( Lua 里,table 的创建是通过"构造表达式"来完成,最简单构造表达式是{},用来创建一个。也可以表里添加一些数据,直接初始化: ?...不同于其他语言的数组 0 作为数组的初始索引, Lua的默认初始索引一般以 1 开始。 ?

1.6K60

Lua中调用C语言

在打开目录后,该函数会创建一张新,然后用目录中的元素填充这张新。最后,该函数关闭目录并返回1,C语言中即表示该函数将其栈顶的值返回给了Lua。...,新版本用lua_pcallk替换了lua_pcall;其次,新版本调用完lua_pcallk后完成的状态传给了新的辅助函数finishpcall;第三,lua_pcallk返回的状态除了LUA_OK...但当被新的lua_pcallk调用的函数yield时,则不会出现发生错误:Lua会做一个长跳转并且丢弃C语言栈中有关luaB_pcall的元素,但是会在协程软栈中保存传递给函数lua_pcallk的延续函数的引用...当luaL_newlib返回时,它把这个新创建的留在栈中,中它打开了这个库。然后,函数luaopen_mylib返回1,表示将这个返回给Lua。 编写完这个库以后,我们还必须将其链接到解释器。...一个简答的做法是luaopen_mylib添加到由lua_openlibs打开的标住库列表中,这个列表位于文件linit.c中。

3.7K20

lua 和c的调用

lua中使用c动态库,像luacjson(支持unicode),luasocket,都是以动态链接库的形式lua中使用的,至于怎么写这些动态链接库很少有教程说到,下面我就说说如何c文件编译成动态库。...首先,假设需要在lua中调用一个c中实现的求和函数,函数名add(a,b)。 我给这个测试库取名为dylib,它包含一个函数add。...int c = a+b; lua_pop(L,2); lua_pushnumber(L,c); return 1; } 这函数就是两参数加起来,然后返回和。...但有的时候需要将一个模块改名,以避免名称冲突。比如有这样的场景,测试中需要加载同一模块的不同版本,而获得版本之间的性能区别。那么我们如何加载同一模块的不同版本呢?...对于一个Lua文件来说,我们可以很轻易的改掉它的名称,但是对于一个C程序库来说,我们是没有办法编辑其中的luaopen_函数的名称的。

64520

深入LUA脚本语言,让你彻底明白调试原理

后面我会继续自己项目开发中的实战经验进行总结。 ?...由于gdb的代码相对复杂,没有办法从代码层面仔细的分析调试细节,所以这次我们选择一个小巧、开源的Lua脚本语言,深入到最底层的代码中去探究一下代码调试真正是怎么一回事。...也就是说,我们写了一个test.lua程序,是没有办法直接运行它的。而实需要一个“宿主”程序,来加载test.lua文件。 ? 宿主程序可以是一个最简单的C程序,Lua官方提供了一个宿主程序。...Lua语法 语法层面,Lua涵盖的内容还是比较全面的,它是一门动态类型语言,基本概念包括:八种基本数据类型,是唯一的数据结构,环境与全局变量,元及元方法,协程,闭包,错误处理,垃圾收集。...计划录一个60分钟左右的视频,上面提到的内容都操作演示一遍,这样效果会更好一下。有兴趣的话可以B站搜一下我的ID(道哥分享)。内容主要包括: Linux平台下:编译和调试步骤。

4.2K43

Redis入坟(二)高级特性,发布订阅、事务、Lua脚本

目标 1、学习 Redis 的一些高级特性,包括发布订阅、事务、Lua 脚本 1、发布订阅模式 1.1列的局限 前面我们说通过队列的 rpush 和 lpop 可以实现消息队列(队尾进队头出),但是消费者需要不停地调用...2.4 事务可能遇到的问题 我们事务执行遇到的问题分成两种,一种是执行 exec 之前发生错误,一种是执行 exec 之后发生错误。...思考(作业): 为什么一个事务中存在错误,Redis 不回滚? 3 Lua 脚本 Lua是一种轻量级脚本语言,它是用 C 语言编写的,跟数据的存储过程有点类似。.../redis-cli –eval [lua 脚本] [key…]空格,空格[args…]  多个参数之间用一个 空格 分割 3.2.4 缓存 Lua 脚本 为什么要缓存 脚本比较长的情况下,如果每次调用脚本都需要把整个脚本传给...脚本,如果 Lua脚本执行超时或者陷入了死循环,是不是没有办法为客户端提供服务了呢?

85310

Redis中lua脚本的使用和作用能做什么?

如果在这个过程中有任何错误,那么所有的命令都不会被执行。 性能优化:对于一些复杂的操作,使用Lua脚本可以减少网络延迟和命令解析的时间,从而提高性能。...数据转换:你可以Lua脚本中进行数据的转换或处理,比如将某个键的值从一个格式转换为另一个格式。...可以命令行中通过以下方式调用该脚本: lua script.lua 2 3 # 输出5 判断一个数是否是偶数: local num = tonumber(ARGV[1]) if num % 2 ==...0 then print("偶数") else print("奇数") end 接收一个参数,它转换为数值,然后判断该数是否是偶数并打印结果。...可以命令行中通过以下方式调用该脚本: lualua script.lua 4 # 输出“偶数” lua script.lua 5 # 输出“奇数” 输出所有的: for i = 1, #ARGV

34640

Lua数据结构

虽然Lua语言中也可以使用来实现数组和列表,但实际上比数组和列表强大很多。使用时,很多算法可以被简化。例如,由于本身就支持任意数据类型的直接访问,因此我们很少Lua语言中编写搜索算法。...我们可以每个节点用一个来表示,链接则为一个包含指向其他的引用的简单表字段。例如,让我们实现一个单链表,其中每个节点具有两个字段value和next。...对于一个64为整型数而言,以每秒1000万次的速度进行插入也需要运行3万年才会发生溢出的问题。 反向 我们很少Lua语言中进行索引操作。但是,我们使用被称为索引或反向的数据结构。...Lua语言中,包的简单表示类似于此前集合的表示,只不过其中的每一个键都有一个对应的计数器。...Java提供了StringBuffer类还解决这个问题;而在Lua语言中,我们可以一个当做字符串缓冲区,其关键是使用函数table.concat,这个函数会将指定列表中的所有字符串连接起来并返回连接后的结果

85720

Lua:深拷贝与浅拷贝,强引用与弱引用

https://blog.mutoo.im/2015/10/deepclone-in-lua/ lua 中有 8 种基本类型,分别是:nil、boolean、number、string、userdata...同一段代码,程序中只需要有一个实例即可。所以我认为它也符合我们对拷贝的定义。 非赋值拷贝 另外三种 lua 基本类型 userdata、thread、table 都是非简单值类型。...其中 table 可以说是 lua 数据结构的根基,要实现其它的数据结构都要依赖它, lua 程序中模拟面向对象类也离不开它,然而它不能简单通过赋值进行拷贝,而是需要创建一个新的 table 并将原...4.表里有,就是执行_copy(v)时,进行递归,直到返回一个塞好的新newTab1 lua中强引用 a = {c = 1} b = a a = nil print(b.c) 输出1 a与b指向同一个内存...因为lua是具备自动内存管理的,我们只管创建,删除操作是lua自动进行的,因此这里的a = nil并不是删除,而是指将a对这张的引用去掉,当没有地方引用这张时,这张就会被lua自动清掉。

31140

Redis实现简单消息队列

如果队列暂时无法被插入新数据,有没有办法新数据暂时存储临时存储上等队列恢复时候再重新插入? 消费者读取数据时候是否需要一个“commit”的语义?是否需要确认已经读取处理完毕?...2.4 本文采取的方案 本文采用Redis的List作为队列可以用来不同程序之间交换消息。生成者使用LPUSH或者RPUSH将一个消息放入队列。...如果客户端消费一个消息时候崩溃,则未处理完的消息也就因此丢失。 因此需要 使用RPOPLPUSH命令(或者它的阻塞版本BRPOPLPUSH)。...最后,还可以添加一个客户端专门用于监视备份,它自动地将超过一定处理时限的消息重新放入队列中去(负责处理该消息的客户端可能已经崩溃),这样就不会丢失任何消息了。...因为我们需要在一个Redis操作中执行lpop和rpush两个操作,必须这两个操作构建成一个原子序列,所以这里涉及到了Lua脚本的使用。

94420
领券