Lua 不是 C++
http://blog.codingnow.com/2008/08/lua_is_not_c_plus_plus.html
嗯,首先,此贴不是牢骚帖。
话题从最近私人的一点工作开始。应 dingdang 的建议,我最近在帮 大唐无双 做一些程序上的工作。接手做这件事情,是因为这个内部被我们称作 dt2 的游戏 engine 关系重大。公司有至少四个项目在使用(另外三个暂处于研发期,尚未公布)。
dt2 用了大量的 lua 代码构建系统,但从系统设计上,沿袭了老的大唐的许多代码。原来的大唐是用 C++ 构建的,为了利用上这些代码(虽然我觉得这种复用非常无意义,但是其中原因复杂,就不展开谈了),dt2 engine 的开发人员做了一套非常复杂的中间层,把 lua 和 C++ 几乎无缝的联系在了一起。
从表征上看,可以完全不修改 C++ 代码,只额外加上一些东西,便可以在 lua 中得到一个类对象,从语法上相当接近的使用 C++ 的类,并可以对其继承,用 lua 重载其虚函数。甚至可以实现多重继承。
由于项目组隔的比较远,所以直到最近一个月,我才拿到这套东西的文档和源码。我的直觉告诉我,这属于过厚的粘合层,是绝对需要抛弃的。如果不是无双内测初期频频的出现 bug ,可能不会有太多人赞同我这个观点。但事实上,即使这个粘合层实现的绝无问题,完全正确的使用它也几乎是不可能的。这么厚的粘合层很难做到 robust 。
这段时间,在开发维护人员的不懈努力(不包括我,在为这个项目修 bug 的工作上,我只是一打酱油的)下,主要的 bug 也修的差不多了,但是做一些适度的改造也必须开展。跟 engine 的前开发人员聊过,我很能理解这个东西被做成这个样子,以及为什么做这样一个东西的必然性:对 lua 的不熟悉,以及迫切的需要复用 C++ 代码。但是我依然想说,解决问题之道在于,先仔细考虑问题存不存在。不做是最好的做法。
表面上看起来,这个粘合层是设计的是很精妙的,它隐藏了 lua 虚拟机的细节。C++ 程序员在写代码的时候,并不需要实际上也的确是,不知道 lua 的存在。而 lua 程序也不需要关心那个类是用 C++ 实现的。在 lua 中,可以按照 C++ 的对象模型继续对类进行继承扩展。一切都展现的完美无缺。
C++ 的代码从某种程度上也显得非常有水准,template 的灵活使用,可以在可能存在的领域重复利用发挥出功效,大量使用的 stl 容器以及智能指针保证了底层领域的健壮。
如果不是这个粘合层的对象生命期管理出了一点设计上的小问题。在 C++ 的引用计数和 lua 的 gc 管理之间有点搅和不清,我想,这个东西可能就一直用下去了。我也不会被派来对这些代码做 code review 。
没错,代码的 bug 最终都可以改过来,这个设计点上的错误也可以想办法用比较小的代价纠正。但是,仔细的考虑一下,整件事情应该去做吗?在 lua 里实现一个 C++ 的面向对象的对象模型?
面向对象不是 C++ 语言向我们展示的那些东西。这不是 C++ 语言的错,因为 C++ 只是在用它的方式去表达而已。我们可以去寻求 lua 的表达方式,正像 ROR 追寻 ruby 的表达方式一样。
诚然,培养新的语言的程序员,比把一门语言模拟成另一种要困难的多。如果我们用写 C++ 程序的思考方式去写 lua 程序,那么当我们决定把游戏用 lua 重新实现一次。除了性能,我们还会失去很多。
前段时间去广州出差,和西游组的同事吃饭。据说最近一年来,他们改进了大话和梦幻的服务器设计,把处理连接的部分独立出来放到单独的进程中 ,使服务器性能大大提高。梦幻西游的服务器,已经可以做到单台机器支持一万人同时在线。
可惜的是,大话 3 的服务器,依然徘徊在单机三千人左右。表面上最大的区别是,梦幻西游的游戏逻辑是用一种类 C 的脚本语言 LPC 写的,而大话3 则是用的 lua 。
刨除大话 3 更为复杂的逻辑处理的因素,追根到底是,lua 的表达能力更强,导致了程序员用更 C++ 的方式去用 lua 。而原来的 LPC 的代码更接近 C 一些。
不是说 C++ 比 C 慢,对于编译语言来说 C++ 甚至比 C 的执行性能更高。但是对于解释型的动态语言。那种看起来更 C++ 的风格会拖垮运行性能许多。对于开发人员来说 lua 5 以后加入的 meta table 是个好东西,但是任何强大的特性都可能被滥用。有幸 lua 还是门简洁的语言,如果有一天 ruby 在游戏开发圈子里流行起来,我都不敢想会发生怎样的事情 ;)
对于那些新接触 lua 的 C/C++ 程序员来说,我的第一条建议通常是:看看 lisp/scheme 吧,可能 lua 的血统里,scheme 的成分比 C 更多一些。要不玩一下 Haskell ,增进对函数式编程的了解。C++ 借助 template 是可以玩玩函数式编程,但很少有人真的去用。进入 lua 的领域后,你得正正经经的理解一下了。
关于 dt2 engine ,这几天我为之做的最多的事情是重新实现了一个 timer tick 的系统,这个东西很早以前就做过,也有现成的代码。不过 200 行。
但是,重新实现一个的意义在于:把这个子模块剥离出来,绕过原来的厚粘合层。而不是先前的那种设计:在 C++ 里实现一个 CTick 类,然后从 lua 中继承它,再注册回 C++ 中的 CTickMgr 。
可能下一步还会协助开发组的同事把连接管理分离出来,并改进数据库的访问。
最后友情做一个广告:大唐无双 这个游戏还是不错的。美术和玩法方面都有了长足的进步。技术问题我相信在大家的努力下都会慢慢的解决。网易的开发团队还是很强的。
Lua 不是 C++的更多相关文章
- lua执行字节码的过程介绍
前面一篇文章中介绍了lua给下面代码生成最终的字节码的整个过程,这次我们来看看lua vm执行这些字节码的过程. foo = "bar" local a, b = "a& ...
- lua 学习笔记(1)
一.lua函数赋值与函数调用 在lua中函数名也是作为一种变量出现的,即函数和所有其他值一样都是匿名的,当要使用某个函数时,需要将该函数赋值给一个变量,这样在函数块的其他地方就可以通过 ...
- 在redis中使用lua脚本让你的灵活性提高5个逼格
在redis的官网上洋洋洒洒的大概提供了200多个命令,貌似看起来很多,但是这些都是别人预先给你定义好的,但你却不能按照自己的意图进行定制, 所以是不是感觉自己还是有一种被束缚的感觉,有这个感觉就对了 ...
- 使用Nginx+Lua代理Hadoop HA
一.Hadoop HA的Web页面访问 Hadoop开启HA后,会同时存在两个Master组件提供服务,其中正在使用的组件称为Active,另一个作为备份称为Standby,例如HDFS的NameNo ...
- 打印Lua的Table对象
小伙伴们再也不用为打印lua的Table对象而苦恼了, 本人曾也苦恼过,哈哈 不过今天刚完成了这个东西, 以前在网上搜过打印table的脚本,但是都感觉很不理想,于是,自己造轮子了~ 打印的效果,自己 ...
- lua解析赋值类型代码的过程
我们来看看lua vm在解析下面源码并生成bytecode时的整个过程: foo = "bar" local a, b = "a", "b" ...
- 怎么调试lua性能
怎么调试lua性能 我们的游戏使用的是Cocos2dx-lua 3.9的项目,最近发现我们的游戏.运行比较缓慢.想做一次性能优化了.其实主要分为GPU.CPU的分别优化.GPU部分的优化.网上有很多优 ...
- Lua 安全调用 metatable 的简单应用
事情的经过 我们的项目中存在好几个战斗界面,不过界面中的内容略有不同.跟同事出去吃饭的时候,他问我.我们现在的战斗界面.有很多是重复的,但是也有偶尔几个地方不太一样.我在战斗过程中驱动这些界面的时候. ...
- 让Lua自己把文件夹下面的所有文件自动加载起来吧
没有想到我也做了一回标题党.其实这里边说的自动还是有夸大其词的部分.其实只是指定文件夹,然后根据指定文件夹数据,加载目录下边的内容而已. 怎么来进行Lua文件的加载 一般情况下,相关的功能需要给他创建 ...
- 让Lua支持Linq吧
第一次接触Linq是在使用C#的时候,这种语法,在处理列表数据非常方便.如果想了解Linq的更多内容可以百度一下Linq,不过你不了解也没关系,让我在Lua中给你展示一下Linq的魅力.简单点说,Li ...
随机推荐
- angular ui $modal 使用 option
$modal是一个可以迅速创建模态窗口的服务,创建部分页,控制器,并关联他们 $modal仅有一个方法open(options) templateUrl:模态窗口的地址 template:用于显示ht ...
- 构建ASP.NET MVC5+EF6+EasyUI 1.4.3+Unity4.x注入的后台管理系统(62)-EF链接串加密
前言: 这一节提供一个简单的功能,这个功能看似简单,找了一下没找到EF链接数据库串的加密帮助文档,只能自己写了,这样也更加符合自己的加密要求 有时候我们发布程序为了避免程序外的SQL链接串明文暴露,需 ...
- oracle指定访问某表或某视图
在oracle中,想创建一个账号,然后只能只读地访问指定的表,怎么搞? 一.为特定的表创建视图 创建视图的时候还可以加上过滤条件,连访问哪些数据都可以指定. create or replace vie ...
- find命令用法
关于查找 文件查找: locate非实时查找:根据索引查找 find实时查找:根据文件的各种属性去找到相对应文件 根据文件的各种属性去找到相对应文件 文本搜索: gre ...
- vim学习之以退为进——可反复移动和可反复改动的美妙结合
时间:2014.06.29 地点:基地 -------------------------------------------------------------------------------- ...
- ABAP内存运用
(1)ABAP 内存运用语句: EXPORT LT_ITAB TO MEMORY ID ‘MM’. IMOIRT LT_ITTAB FROM MEMORY ID ‘MM’. (2)SAP内 ...
- C++ xml 解析器
C++的xml解析器有很多,这个知乎回答里有一个列表:https://www.zhihu.com/question/32046606 下面使用其中的RapidXml试试. 官方地址: https:// ...
- 我所认为的KVC和KVO
引子: 为什么要写这个,只是突然一个念头闪现,说一下本人目前理解.KVC: Key-value coding,它是一种使用字符串标识符,间接访问对象属性的机制.但是关就这一 ...
- Android Weekly Notes Issue #242
Android Weekly Issue #242 January 29th, 2017 Android Weekly Issue #242 本期内容包括: Android中常用的设计模式; 基于No ...
- DIY固件系列教程——实现开机LOGO三屏动画的完全替换【转】
本文转载自:http://blog.csdn.net/sdgaojian/article/details/9192433 本教程需要用到如下工具:1,7Z压缩工具2,AddCrc32效验工具3,raw ...