Lua 5.3为何很慢?windows10该不该升级级

为什么说DOM操作很慢_小组_ThinkSAAS
为什么说DOM操作很慢
为什么说DOM操作很慢
也可以在这里看:
一直都听说DOM很慢,要尽量少的去操作DOM,于是就想进一步去探究下为什么大家都会这样说,在网上学习了一些资料,这边整理出来。
首先,DOM对象本身也是一个js对象,所以严格来说,并不是操作这个对象慢,而是说操作了这个对象后,会触发一些浏览器行为,比如布局(layout)和绘制(paint)。下面主要先介绍下这些浏览器行为,阐述一个页面是怎么最终被呈现出来的,另外还会从代码的角度,来说明一些不好的实践以及一些优化方案。
浏览器是如何呈现一张页面的
一个浏览器有许多模块,其中负责呈现页面的是渲染引擎模块,比较熟悉的有WebKit和Gecko等,这里也只会涉及这个模块的内容。
先用文字大致阐述下这个过程:
解析HTML,并生成一棵DOM tree
解析各种样式并结合DOM tree生成一棵Render tree
对Render tree的各个节点计算布局信息,比如box的位置与尺寸
根据Render tree并利用浏览器的UI层进行绘制
其中DOM tree和Render tree上的节点并非一一对应,比如一个display:none的节点就在会存在与DOM tree上,而不会出现在Render tree上,因为这个节点不需要被绘制。
上图是Webkit的基本流程,在术语上和Gecko可能会有不同,这里贴上Gecko的流程图,不过文章下面的内容都会统一使用Webkit的术语。
影响页面呈现的因素有许多,比如link的位置会影响首屏呈现等。但这里主要集中讨论与layout相关的内容。
paint是一个耗时的过程,然而layout是一个更耗时的过程,我们无法确定layout一定是自上而下或是自下而上进行的,甚至一次layout会牵涉到整个文档布局的重新计算。
但是layout是肯定无法避免的,所以我们主要是要最小化layout的次数。
什么情况下浏览器会进行layout
在考虑如何最小化layout次数之前,要先了解什么时候浏览器会进行layout。
layout(reflow)一般被称为布局,这个操作是用来计算文档中元素的位置和大小,是渲染前重要的一步。在HTML第一次被加载的时候,会有一次layout之外,js脚本的执行和样式的改变同样会导致浏览器执行layout,这也是本文的主要要讨论的内容。
一般情况下,浏览器的layout是lazy的,也就是说:在js脚本执行时,是不会去更新DOM的,任何对DOM的修改都会被暂存在一个队列中,在当前js的执行上下文完成执行后,会根据这个队列中的修改,进行一次layout。
然而有时希望在js代码中立刻获取最新的DOM节点信息,浏览器就不得不提前执行layout,这是导致DOM性能问题的主因。
如下的操作会打破常规,并触发浏览器执行layout:
通过js获取需要计算的DOM属性
添加或删除DOM元素
resize浏览器窗口大小
css伪类的激活,比如:hover
通过js修改DOM元素样式且该样式涉及到尺寸的改变
我们来通过一个例子直观的感受下:
var h1 = element1.clientH
// Write (invalidates layout)
element1.style.height = (h1 * 2) + 'px';
// Read (triggers layout)
var h2 = element2.clientH
// Write (invalidates layout)
element2.style.height = (h2 * 2) + 'px';
// Read (triggers layout)
var h3 = element3.clientH
// Write (invalidates layout)
element3.style.height = (h3 * 2) + 'px';
这里涉及一个属性clientHeight,这个属性是需要计算得到的,于是就会触发浏览器的一次layout。我们来利用chrome(v47.0)的开发者工具看下(截图中的timeline record已经经过筛选,仅显示layout):
上面的例子中,代码首先修改了一个元素的样式,接下来读取另一个元素的clientHeight属性,由于之前的修改导致当前DOM被标记为脏,为了保证能准确的获取这个属性,浏览器会进行一次layout(我们发现chrome的开发者工具良心的提示了我们这个性能问题)。
优化这段代码很简单,预先读取所需要的属性,在一起修改即可。
var h1 = element1.clientH
var h2 = element2.clientH
var h3 = element3.clientH
// Write (invalidates layout)
element1.style.height = (h1 * 2) + 'px';
element2.style.height = (h2 * 2) + 'px';
element3.style.height = (h3 * 2) + 'px';
看下这次的情况:
下面再介绍一些其他的优化方案。
最小化layout的方案
上面提到的一个批量读写是一个,主要是因为获取一个需要计算的属性值导致的,那么哪些值是需要计算的呢?
这个链接里有介绍大部分需要计算的属性:
再来看看别的情况:
面对一系列DOM操作
针对一系列DOM操作(DOM元素的增删改),可以有如下方案:
documentFragment
display: none
比如(仅以documentFragment为例):
var fragment = document.createDocumentFragment();
for (var i=0; i & items. i++){
var item = document.createElement("li");
item.appendChild(document.createTextNode("Option"+ i);
fragment.appendChild(item);
list.appendChild(fragment);
这类优化方案的核心思想都是相同的,就是先对一个不在Render tree上的节点进行一系列操作,再把这个节点添加回Render tree,这样无论多么复杂的DOM操作,最终都只会触发一次layout。
面对样式的修改
针对样式的改变,我们首先需要知道并不是所有样式的修改都会触发layout,因为我们知道layout的工作是计算RenderObject的尺寸和大小信息,那么我如果只是改变一个颜色,是不会触发layout的。
这里有一个网站,详细列出了各个CSS属性对浏览器执行layout和paint的影响。
像下面这种情况,和上面讲优化的部分是一样的,注意下读写即可。
elem.style.height ="100px"; // mark invalidated
elem.style.width ="100px";
elem.style.marginRight ="10px";
elem.clientHeight // force layout here
但是要提一下动画,这边讲的是js动画,比如:
function animate (from, to) {
if (from === to) return
requestAnimationFrame(function () {
element1.style.height = from +"px"
animate(from, to)
animate(100, 500)
动画的每一帧都会导致layout,这是无法避免的,但是为了减少动画带来的layout的性能损失,可以将动画元素绝对定位,这样动画元素脱离文本流,layout的计算量会减少很多。
使用requestAnimationFrame
任何可能导致重绘的操作都应该放入requestAnimationFrame
在现实项目中,代码按模块划分,很难像上例那样组织批量读写。那么这时可以把写操作放在requestAnimationFrame的callback中,统一让写操作在下一次paint之前执行。
var h1 = element1.clientH
requestAnimationFrame(function() {
element1.style.height = (h1 * 2) + 'px';
var h2 = element2.clientH
requestAnimationFrame(function() {
element2.style.height = (h2 * 2) + 'px';
可以很清楚的观察到Animation Frame触发的时机,MDN上说是在paint之前触发,不过我估计是在js脚本交出控制权给浏览器进行DOM的invalidated check之前执行。
其他注意点
除了由于触发了layout而导致性能问题外,这边再列出一些其他细节:
缓存选择器的结果,减少DOM查询。这里要特别体下HTMLCollection。HTMLCollection是通过document.getElementByTagName得到的对象类型,和数组类型很类似但是每次获取这个对象的一个属性,都相当于进行一次DOM查询:
var divs = document.getElementsByTagName("div");
for (var i = 0; i & divs. i++){ //infinite loop
document.body.appendChild(document.createElement("div"));
比如上面的这段代码会导致无限循环,所以处理HTMLCollection对象的时候要最些缓存。
另外减少DOM元素的嵌套深度并优化css,去除无用的样式对减少layout的计算量有一定帮助。
在DOM查询时,querySelector和querySelectorAll应该是最后的选择,它们功能最强大,但执行效率很差,如果可以的话,尽量用其他方法替代。
下面两个jsperf的链接,可以对比下性能。
自己对View层的想法
上面的内容理论方面的东西偏多,从实践的角度来看,上面讨论的内容,正好是View层需要处理的事情。已经有一个库FastDOM来做这个事情,不过它的代码是这样的:
fastdom.read(function() {
console.log('read');
fastdom.write(function() {
console.log('write');
问题很明显,会导致callback hell,并且也可以预见到像FastDOM这样的imperative的代码缺乏扩展性,关键在于用了requestAnimationFrame后就变成了异步编程的问题了。要让读写状态同步,那必然需要在DOM的基础上写个Wrapper来内部控制异步读写,不过都到了这份上,感觉可以考虑直接上React了......
总之,尽量注意避免上面说到的问题,但如果用库,比如jQuery的话,layout的问题出在库本身的抽象上。像React引入自己的组件模型,用过virtual DOM来减少DOM操作,并可以在每次state改变时仅有一次layout,我不知道内部有没有用requestAnimationFrame之类的,感觉要做好一个View层就挺有难度的,之后准备学学React的代码。希望自己一两年后会过来再看这个问题的时候,可以有些新的见解。
PHP开发框架
缓存Memcache
服务器环境
ThinkSAAS商业授权:
ThinkSAAS为用户提供有偿个性定制开发服务
ThinkSAAS将为商业授权用户提供二次开发指导和技术支持
手机客户端
ThinkSAAS接收任何功能的Iphone(IOS)和Android手机的客户端定制开发服务
让ThinkSAAS更好,把建议拿来。今天有人转了个知乎上的帖子给我看: 。
首先,我不认为 10% 的性能差异能够称的上很大,和 10% 的性能下降相比,程序更清晰稳定、功能更完备(不是指功能多,而是指对各种边界条件处理的更好)要重要的多。毕竟,让 CPU 提升 10% 的性能很容易。
其次,在实际项目中,和简单的测试脚本不同,我很难观察到 10% 的差异。(我们的服务器用过 lua 5.2 和 lua 5.3 两个版本,很难从线上压力上感知到性能差别)。
如果你真的用那些简单的测试脚本做一个比较,lua 5.1 比它的前一个版本 lua 5.0 要慢得多。差别或许比 lua 5.1 到 5.3 还要大。而为什么很少人关心这个,去用回 5.0 呢?说到底还是因为 luajit 导致的 lua 社区的分裂,让 lua 5.1 这个中间版本变成了另一个 lua 而已。
我的硬盘上一直留有从 lua 4.0 开始几乎每个 lua 小版本的源代码副本。而近十年来,一直都在跟进 lua 的源码变迁,所以我对 lua 的每次修改都或多或少有一些印象。下面谈谈我对这个新版本越来越慢的一点个人看法吧。
这写这篇 blog 前,我花了一天做了大量的测试对比工作。包括做profile ,编译出汇编逐行对比,阅读版本间的 diff 等等。因为不是写 paper ,懒得把这些工作整理在 blog 里了。主要写写结论。
我认为,lua 小版本演化在一些简单测试脚本跑分中,性能 5% ~ 10% 的下降,主要是更健壮的实现的代价。也就是考虑到各种边界条件,逐渐增加的判断。以及一些不完备的功能在完善过程中增加的必要代码。另外,还包括了 gc 模块的不断改进。
比如,一开始的版本( 5.1 )不能在 pcall 中 yield ,不能在 hook 里 yield ;而后来的版本抹去了这些限制。同时,设计和实现都复杂了一些。但如果你仔细阅读代码,你会发现这些改动都不是简单的补丁,而精心考虑过的重设计,实现上都几乎无可挑剔。单从局部代码的来看,你都很难找到哪里是导致性能下降的热点。
再比如,有人怀疑 lua 5.3 把 number 类型在内部拆分成整数和浮点两个子类型会导致多余的判断和分支。这会造成一些性能下降。但其实增加子类型本身是几乎没有额外的性能开销的(尤其是最常见的 table index 操作)。你可以对比前后版本的实现,看看到底是否真的有多余的分支。
对比 lua 5.3 和 5.2 工作量很大,我们可以找个更简单的地方来看:
其实给数据类型区分子类型并不是从 5.3 开始的,甚至不是某个大版本变更。实现的变化发生在 lua 5.2.0 到 5.2.1 之间。在这个小版本升级的过程中,lua 利用 type 字段的高位开始为数据类型区分内部子类型。
在 lua 5.2.1 中,字符串被分为短字符串和长字符串两类。只有短字符串才做内部化(和之前版本的字符串行为一致),而长字符串则额外处理。
lua 5.2.1 和 5.2.0 的 diff 文件不大,只有 2000 行左右。而且一半都是周边库的实现变化。所以慢慢阅读几百行 diff 花上个把小时大家都能做了。
如果你写一些简单的测试脚本,你会发现很多情况下 lua 5.2.1 的确和 lua 5.2.0 有性能差异 1% 上下浮动。或快或慢和具体脚本怎么写有关。
但这个差异真的和 string 的实现有关吗?
我专门把和 string 有关的代码从 lua 5.2.1 patch 到 lua 5.2.0 上做了测试(而保留了其它的差异),发现性能差异几乎消失了。同时,我仔细查看了实现部分编译生成的汇编部分,在主要流程上基本是完全一致的。
而性能差异的部分,一部分来至 gc 部分的改写。而另一方面,lua function 和 c function 可以更清晰的用子类型区分开(而之前是在 function 结构中保留了一个 boolean 变量),代码清爽了很多,对于某些测试脚本,甚至比之前的版本跑的还要快一点点。
为什么很多简单的测试脚本却能感知到明显的差异呢?
这是因为,很多脚本使用了 for 循环去重复测试简单的函数。而 lua 5.3 在 for 数字循环中,需要多做一次子类型判断。对循环变量为整数和浮点数分别处理;而之前的版本是不需要的。
别小看这多一次判断,如果你的 for 循环中做的工作本身很简单,那么差异很可能被放大到 1%
的量级。但实际我们的项目中,却很难让 for 循环本身大比例占据 cpu 时间的。
至于四则运算,之前的版本同样要做类型判断。只要你不在 lua 5.3 中混用整数和浮点,那么甚至还会比老版本更快一些(尤其在不支持硬件浮点运算单元的时候)。
另一方面,由于 lua 5.3 原生支持了 64bit 整数以及新增加的语言级的位操作,对于特定领域来说,却可以对性能做更大幅度的加分。
有些变化的确会影响到性能。比如 lua 5.2 开始取消了 C 层面的对象环境的概念,改成了 _ENV 。这相对于 lua 5.1 ,api 和实现都得到了精简;同时,全局变量这个东西连同对应的 OPCODE 都去掉了,读取全局变量变成了访问 _ENV 这个 upvalue ,性能也收到了轻微了影响。
比如在最前面提到的知乎的帖子中,测试脚本在内循环里访问了 math.abs 函数。而 math 是一个全局变量。如果你能在脚本最前面加一行 local math = math 的话,你会发现 lua 5.1 和 lua 5.2 几乎没有区别。
至于 lua 5.3 的性能轻微下降,我个人认为是 for 循环的差异导致的。
lua 历代版本的源代码可以在 ,如果你对我上面的结论有异议,可以自己每个版本去对比。
btw, 在历史上,lua 5 对 lua 4 那次大版本的升级,几乎重新实现了一遍。而性能是得到了很大的提高的。是不是我们该期待 lua 6 的再次重构呢 :)
这是去年在 skynet mailling list 里讨论过的一个话题: ,今天 review 代码的时候又看到,觉得应该在 blog 记录一下。
简单说就是,当从 skynet 向外部发送相同内容的数据包时,虽然依旧需要一个个包的发送(除非在局域网做
UDP 组播),但在某些特定需求下,复制多份相同的数据包 buffer 是个不必要的开销。
尤其是在上面的帖子中提到的音视频广播的场合,几乎所有的业务都是在向 IO 写同样的数据。所以当时我在考虑后,给 skynet 的 socket 层增加了一个接口,供用户定义共享 buffer ,可以自己在待发送 buffer 对象中自己增加引用计数。
考虑到接口向前兼容,这个用户自定义 buffer 对象的方法要求用户在调用 socket send 时,将 size 设置为 -1 ,以便和 raw 指针区分。
这样,通过从 C 层面的定制,用户就可以自己实现共享指针了。skynet 的 socket 层会正确的从共享对象里取得指针、取得数据块的大小、以及在使用完毕后释放它。
我没有给出更多的用法范例、也没有给出 lua 封装接口,所以这个 C 接口只提供给了解自己的需求,希望做深度定制的同学去扩展。
如果日后做 MOBA 类游戏,需要大量同步场景中相同的状态信息,或许我会再做一些封装。当然,即使这类场合,我觉得多复制几遍数据,也未必会造成性能问题。请教Lua5.2出了很久了,为什么大多都在用5.1_lua吧_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:3,778贴子:
请教Lua5.2出了很久了,为什么大多都在用5.1收藏
看了5.2的特性决定学Lua的,可是中文的资料讲5.2的非常少,感觉大家都在用5.1,是因为第三方库的原因还是别的?初学者求解答
有啥特性,说来听听
你看一下版本升级说明,基本上没有特别的。而且5.1支持比较多
5.2是要比5.1好,而且也算稳定,少人用的原因一个是很多第三方库不支持5.2,一个是网上大部分资料都不是5.2的。
最重要原因,luajit不支持5.2。没有luajit就没兴趣玩lua。
曾经的RO伙伴!
lua和luajit分裂问题,我选择jit
网上没有5.2的下载
你想用反射做什么?
很多第三方库早已停止更新,最多支持到5.1,Luajit也不支持5.1
登录百度帐号推荐应用
为兴趣而生,贴吧更懂你。或为什么 Lua 的新版本越来越慢?
发表于 日 21:38 | Hits: 574
今天有人转了个知乎上的帖子给我看:。
首先,我不认为 10% 的性能差异能够称的上很大,和 10% 的性能下降相比,程序更清晰稳定、功能更完备(不是指功能多,而是指对各种边界条件处理的更好)要重要的多。毕竟,让 CPU 提升 10% 的性能很容易。
其次,在实际项目中,和简单的测试脚本不同,我很难观察到 10% 的差异。(我们的服务器用过 lua 5.2 和 lua 5.3 两个版本,很难从线上压力上感知到性能差别)。
如果你真的用那些简单的测试脚本做一个比较,lua 5.1 比它的前一个版本 lua 5.0 要慢得多。差别或许比 lua 5.1 到 5.3 还要大。而为什么很少人关心这个,去用回 5.0 呢?说到底还是因为 luajit 导致的 lua 社区的分裂,让 lua 5.1 这个中间版本变成了另一个 lua 而已。
我的硬盘上一直留有从 lua 4.0 开始几乎每个 lua 小版本的源代码副本。而近十年来,一直都在跟进 lua 的源码变迁,所以我对 lua 的每次修改都或多或少有一些印象。下面谈谈我对这个新版本越来越慢的一点个人看法吧。
这写这篇 blog 前,我花了一天做了大量的测试对比工作。包括做profile ,编译出汇编逐行对比,阅读版本间的 diff 等等。因为不是写 paper ,懒得把这些工作整理在 blog 里了。主要写写结论。
我认为,lua 小版本演化在一些简单测试脚本跑分中,性能 5% ~ 10% 的下降,主要是更健壮的实现的代价。也就是考虑到各种边界条件,逐渐增加的判断。以及一些不完备的功能在完善过程中增加的必要代码。另外,还包括了 gc 模块的不断改进。
比如,一开始的版本( 5.1 )不能在 pcall 中 yield ,不能在 hook 里 yield ;而后来的版本抹去了这些限制。同时,设计和实现都复杂了一些。但如果你仔细阅读代码,你会发现这些改动都不是简单的补丁,而精心考虑过的重设计,实现上都几乎无可挑剔。单从局部代码的来看,你都很难找到哪里是导致性能下降的热点。
再比如,有人怀疑 lua 5.3 把 number 类型在内部拆分成整数和浮点两个子类型会导致多余的判断和分支。这会造成一些性能下降。但其实增加子类型本身是几乎没有额外的性能开销的(尤其是最常见的 table index 操作)。你可以对比前后版本的实现,看看到底是否真的有多余的分支。
对比 lua 5.3 和 5.2 工作量很大,我们可以找个更简单的地方来看:
其实给数据类型区分子类型并不是从 5.3 开始的,甚至不是某个大版本变更。实现的变化发生在 lua 5.2.0 到 5.2.1 之间。在这个小版本升级的过程中,lua 利用 type 字段的高位开始为数据类型区分内部子类型。
在 lua 5.2.1 中,字符串被分为短字符串和长字符串两类。只有短字符串才做内部化(和之前版本的字符串行为一致),而长字符串则额外处理。
lua 5.2.1 和 5.2.0 的 diff 文件不大,只有 2000 行左右。而且一半都是周边库的实现变化。所以慢慢阅读几百行 diff 花上个把小时大家都能做了。
如果你写一些简单的测试脚本,你会发现很多情况下 lua 5.2.1 的确和 lua 5.2.0 有性能差异 1% 上下浮动。或快或慢和具体脚本怎么写有关。
但这个差异真的和 string 的实现有关吗?
我专门把和 string 有关的代码从 lua 5.2.1 patch 到 lua 5.2.0 上做了测试(而保留了其它的差异),发现性能差异几乎消失了。同时,我仔细查看了实现部分编译生成的汇编部分,在主要流程上基本是完全一致的。
而性能差异的部分,一部分来至 gc 部分的改写。而另一方面,lua function 和 c function 可以更清晰的用子类型区分开(而之前是在 function 结构中保留了一个 boolean 变量),代码清爽了很多,对于某些测试脚本,甚至比之前的版本跑的还要快一点点。
为什么很多简单的测试脚本却能感知到明显的差异呢?
这是因为,很多脚本使用了 for 循环去重复测试简单的函数。而 lua 5.3 在 for 数字循环中,需要多做一次子类型判断。对循环变量为整数和浮点数分别处理;而之前的版本是不需要的。
别小看这多一次判断,如果你的 for 循环中做的工作本身很简单,那么差异很可能被放大到 1%
的量级。但实际我们的项目中,却很难让 for 循环本身大比例占据 cpu 时间的。
至于四则运算,之前的版本同样要做类型判断。只要你不在 lua 5.3 中混用整数和浮点,那么甚至还会比老版本更快一些(尤其在不支持硬件浮点运算单元的时候)。
另一方面,由于 lua 5.3 原生支持了 64bit 整数以及新增加的语言级的位操作,对于特定领域来说,却可以对性能做更大幅度的加分。
有些变化的确会影响到性能。比如 lua 5.2 开始取消了 C 层面的对象环境的概念,改成了_ENV。这相对于 lua 5.1 ,api 和实现都得到了精简;同时,全局变量这个东西连同对应的 OPCODE 都去掉了,读取全局变量变成了访问_ENV这个 upvalue ,性能也收到了轻微了影响。
比如在最前面提到的知乎的帖子中,测试脚本在内循环里访问了 math.abs 函数。而 math 是一个全局变量。如果你能在脚本最前面加一行local math = math的话,你会发现 lua 5.1 和 lua 5.2 几乎没有区别。
至于 lua 5.3 的性能轻微下降,我个人认为是 for 循环的差异导致的。
lua 历代版本的源代码可以在,如果你对我上面的结论有异议,可以自己每个版本去对比。
btw, 在历史上,lua 5 对 lua 4 那次大版本的升级,几乎重新实现了一遍。而性能是得到了很大的提高的。是不是我们该期待 lua 6 的再次重构呢 :)
评价列表(0)发于 日 16:08
| 点击: 528
skynet 本质上只是一个消息分发器,以服务为单位,给每个服务一个独立的 id ,可以从任意服务向另一个服务发送消息。
在此基础上,我们在服务中接入 Lua 虚拟机,并将消息收发的 api 封装成 lua 模块。目前用 lua 编写的服务在最底层只有一个入口,就是接收并处理一条 skynet 框架转发过来的消息。我们可以通过 skynet.core.callback (这是一个内部 API ,用 C 编写,通常由 skynet.start 调用)把一个 lua 函数设置到
发于 日 21:14
| 点击: 480
今天同事提了个需求,他希望可以给部分 lua 代码(由策划编写)做一个沙盒关起来。在 lua 里做沙盒很容易,只需要控制函数的环境就可以了。不过另一个附加需求是,这些代码还可以直接利用 require 加载。
而我们又不想去修改系统的
api 接口,那么怎么做到这点呢?
首先, 我希望使用的时候看起来像这样:
local xxx = require "xxx" (myEnv)
和传统的 require 用法不同,可以在后面追加一个参数 myEnv 。这样的话,每次
发于 日 16:26
| 点击: 523
lua 中 40 字节以下的字符串会被内部化到一张表中,这张表挂在 global state 结构下。对于短字符串,相同的串在同一虚拟机上只会存在一份。
在 skynet 中,有大量的 lua vm ,它们很可能加载同一份 lua 代码。所以我之前改造过一次 lua 虚拟机,[让它们可以共享 Proto] 。这样可以加快多个虚拟机初始化的速度,并减少一些内存占用。
但是,共享 Proto 仅仅只完成了一半的工作。因为一段 lua 代码有一很大一部分包含了很多字符串常量。而
发于 日 15:50
| 点击: 500
Lua 是一门嵌入式语言,和 host 的联动非常重要。Lua 使用 userdata 来保存 host 里的数据,userdata 非常强大,可以有 metatable 还可以关联一个 uservalue ,可以封装一切 C/C++ 对象,非常强大。但有的时候却稍显不足,似乎缺了点什么,导致一些简单的需求要用很繁琐的方式解决。
有个想法想过很久,今天动了念头用英文写了一遍投递到 lua 邮件列表里去了。
那就是,如果我们可以给 userdata 的值关联一个整数,而不是
发于 日 14:33
| 点击: 473
从周末开始, 我一直在忙一个想法。我希望给 skynet 中的 lua 服务定制一个内存分配器。
倒不是为了提升性能。如果可以单独为每个 lua vm 配置一个内存分配器,自己调用 mmap 映射虚拟内存,就可以为独立的服务制作快照了。这样可以随时 fork 出子进程,只保留关心的 vm 的内存快照。主要可以有三个用途:
可以在快照上做序列化,并把结果返还父进程。通常做序列化有一定的时间代价,如果想定期保存的话,这个代码很可能导致服务暂停。
可以利用快照监控检查泄露。定
发于 日 21:38
| 点击: 576
今天有人转了个知乎上的帖子给我看:Lua 5.3为何很慢?该不该升级? 。
首先,我不认为 10% 的性能差异能够称的上很大,和 10% 的性能下降相比,程序更清晰稳定、功能更完备(不是指功能多,而是指对各种边界条件处理的更好)要重要的多。毕竟,让 CPU 提升 10% 的性能很容易。
其次,在实际项目中,和简单的测试脚本不同,我很难观察到 10% 的差异。(我们的服务器用过 lua 5.2 和 lua 5.3 两个版本,很难从线上压力上感知到性能差别)。
如果你真的用
发于 日 23:56
| 点击: 676
Lua 作为一门嵌入式语言,提供了完备的 C API 供 Lua 代码和宿主程序交互,当然,宿主语言最好是 C 或 C++ 。如果是其它语言,比如最近两年流行的在 mono 环境嵌入 Lua 另当别论。
正确将 Lua 嵌入是不太容易做对的事情,很多刚接触 Lua 的人都容易犯错误。好在做这种语言桥接工作都是项目开始阶段的设计者做的,不必人人学会,所以只要有熟悉 Lua 的人来搞,犯错误的危害不会太大。而且即使做的有问题,日后修改也比较容易。这篇 blog 主要就是谈谈,最
发于 日 21:43
| 点击: 1099
写这个东西的起源是,前段时间我们的平台组面试了一个同学,他最近一个作品叫做 luajit.io 。面试完了后,他专门找我聊了几个小时他的这个项目。他的核心想法是基于 luajit 做一个 web server ,和 ngx_lua 类似,但撇开 nginx
。当时他给我抱怨了许多 luajit 的问题,但是基于性能考虑又不想放弃 luajit 而转用 lua 。
我当时的建议是,不要把 lua/luajit 作为嵌入语言而自己写 host 程序,而是想办法做成供 lua
发于 日 11:39
| 点击: 528
最近,我们的合作方 陌陌 带了他们的一个 CP 到我们公司咨询一下 skynet 做 mmo 游戏项目中遇到的一些问题。因为他们即将上线一款 MMO ,在压力测试环节暴露了许多问题。虽然经过我们的分析,有很多问题出在他们的压力测试程序本身编写的 bug ,但同时也暴露出服务器的设计问题。
核心问题是,他们在实现 mmo 服务器时,虽然使用了 skynet 框架,但却把所有的业务逻辑都放在了同一个 lua 服务中,也就是一切都运行在一个 lua states 里。这样,几乎就
发于 日 16:29
| 点击: 747
在 skynet 中,有一个叫 monitor 的内部模块,它会监测是否有服务可能陷入了死循环。
工作原理是这样的:每次处理一个服务的一个消息时,都会在一个和服务相关的全局变量处自增 1 。而 monitor 是一个独立线程,它每隔一小段时间(5 秒左右)都检测一下所有的工作线程,看有没有长期没有自增的,若有就认为其正在处理的消息可能陷入死循环了。
而发现这种异常情况后,skynet 能做的也仅仅是输出一行 log 。它无法从外部中断消息处理过程,而死循环的服务,将永久占
发于 日 18:05
| 点击: 726
一直有人问,如果调试 skynet 构件的服务。
我的简单答案是,仔细 review 代码,加 log 输出。长一点的答案是,尽量熟悉 skynet 的构造,充分利用预留的监控接口,自己编写工具辅助调试。
之前的好多年,我也写过很多 lua 的调试器,这里就不一一翻旧帖了。今天要说的是,我最终还是计划加入 1.0 正式版的调试控制台。
也就是单步跟踪调试单个 lua coroutine 的能力。这对许多新手来说是个学走路的拐杖,虽然有人一辈子都扔不掉。
一开始我想实现
发于 日 15:42
| 点击: 642
最近想给 skynet 加一个在线调试器,方便调试 Lua 编写的服务。
Lua 本身没有提供现成的调试器,但有功能完备的 debug api 。通常、我们可以在代码中插入 debug.debug() 就可以进入一个交互环境,输入任何 Lua
指令。当然,你也可以在 debug hook 里调用它。
但这种交互方式有一个缺点:lua 直接用 load 翻译输入的文本,转译为一个 lua 函数并运行。这注定了这个输入的代码中不能直接访问到上下文的局部变量和 upvalue
|&&&1 一共7页, 73条记录

我要回帖

更多关于 win7该不该升级win10 的文章

 

随机推荐