33 | 性能提升10倍的秘诀:必须用好 table
温铭
该思维导图由 AI 生成,仅供参考
你好,我是温铭。
在 OpenResty 中,除了字符串经常出现性能问题外,table 也是性能的拦路虎。在之前的章节中,我们零零散散地介绍过 table 相关的函数,但并没有专门提到它对性能方面的提升。今天,我就带你专门来聊聊,table 操作对性能的影响。
不同于对字符串的熟悉,开发者对于 table 相关的性能优化知之甚少,这主要有两个方面的原因。
其一,OpenResty 中使用的是 Lua ,是自己的 LuaJIT 分支,不是标准的 LuaJIT,也不是标准的 Lua。而大部分开发者并不知道它们之间的区别,倾向于使用标准 Lua 的 table 库来写 OpenResty 代码。
其二,在标准 LuaJIT 和 OpenResty 自己的 LuaJIT 分支中,table 操作相关的文档都藏得非常深,开发者很难找到;而且文档中也没有示例代码,需要开发者自己去开源项目中寻找示例。
这就形成了比较高的认知壁垒,导致了两极分化的结果——资深的 OpenResty 开发者能够写出很高性能的代码,而刚入门的则会怀疑 OpenResty 的高性能是不是一个泡沫。当然,等你学习完这节课的内容,你就可以轻松地戳破这层窗户纸,让性能提升 10 倍不是梦。
在详细介绍 table 优化之前,我想先强调的一点是,table 相关的优化,有一个自己的简单原则:
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
- 深入了解
- 翻译
- 解释
- 总结
在OpenResty中,对table操作进行优化可以显著提升性能。本文介绍了如何通过复用、预先生成数组、自行计算下标以及循环使用单个table等方法来优化table操作。作者还提到了使用table.clear函数清空数组以及使用table池的方法。通过这些优化技巧,可以有效提升OpenResty代码的性能。文章最后鼓励读者进行性能测试,以便对比使用优化技巧前后的性能差异。这些技巧不仅能帮助读者更好地理解table操作对性能的影响,还能让他们学会如何优化table操作以提升代码性能。
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《OpenResty 从入门到实战》,新⼈⾸单¥59
《OpenResty 从入门到实战》,新⼈⾸单¥59
立即购买
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
登录 后留言
全部留言(12)
- 最新
- 精选
- wusiration尝试了以下性能测试: (1)预先生成数组 resty -e ' local begin = ngx.now() local t = {} for i = 1,100000000 do table.insert(t, i) end ngx.update_time() print(ngx.now()-begin) ' 用时:21.62700009346 resty -e ' local new_tab = require "table.new" local begin = ngx.now() local t = new_tab(100000000, 0) for i = 1,100000000 do table.insert(t, i) end ngx.update_time() print(ngx.now()-begin) ' 用时:7.595999956131 (2)自己计算table下标 --使用insert函数 resty -e ' local new_tab = require "table.new" local begin = ngx.now() local t = new_tab(100000000, 0) for i = 1,100000000 do table.insert(t, i) end ngx.update_time() print(ngx.now()-begin) ' 用时:7.6459999084473 --自己计算下标 resty -e ' local new_tab = require "table.new" local begin = ngx.now() local t = new_tab(100000000, 0) for i = 1,100000000 do t[i] = i end ngx.update_time() print(ngx.now()-begin) ' 用时:0.33599996566772 (3)循环使用单个table --分别建立两个table resty -e ' local new_tab = require "table.new" local begin = ngx.now() local t1 = new_tab(100000000, 0) for i = 1,100000000 do t1[i] = i end local t2 = new_tab(100000000, 0) for i = 1,100000000 do t2[i] = i end ngx.update_time() print(ngx.now()-begin) ' 用时:0.66700005531311 --复用table resty -e ' local new_tab = require "table.new" local begin = ngx.now() local t = new_tab(100000000, 0) for i = 1,100000000 do t[i] = i end for i = 1,100000000 do t[i] = i end ngx.update_time() print(ngx.now()-begin) ' 用时:0.40800023078918
作者回复: 👍
2019-08-113 - HelloBugOpenResty是从哪个版本开始完全绑定LuaJIT的呢?
作者回复: 我记得是 1.15 这个版本开始就只支持自己的 LuaJIT 了。lua 和官方的 luajit 都不再支持了
2019-08-252 - HelloBug老师好,文章中提到table. new 函数属于LuaJIT的扩展,是OpenResty维护的LuaJIT分支的扩展还是就是LuaJIT的扩展?
作者回复: 这个函数是 LuaJIT 的扩展
2019-08-251 - 见习勇者问老师,您好,我有个疑问,您举例的table复用的阶段是在init_worker阶段,这个阶段只会在初始化worker的时候调用一次,并不会影响实际的请求,有必要进行这样的优化么?对后续的请求处理有提升么?
作者回复: 算是一个习惯了,如果是 init worker 阶段确实优化不了多少
2019-08-131 - dingjiayi温老师,有没有比较优雅的方式去切割 access.log 和 error.log 现在我看到网上介绍的方案都是 lograte 或者crontab 启动定时任务去切割 想请问nginx 有自带切割日志的功能吗?或者有比crontab 更优雅的方案吗
作者回复: 你可以使用 OpenResty 的特权进程来做日志文件的切割,等于自己用 timer.every 来实现了crontab的功能。
2019-08-101 - HelloBugtable. clean函数的实现是循环遍历每一个元素,然后置空,相比重新创建一个table来说效率更高。这个是和table的大小无关的是吧,table的重利用的效率总是高于新建一个表格。 这样也有一个要求,重利用的table的大小需要满足多重情况。APISIX中的表格变量都没有使用table. new 来创建,是因为大小不确定吗?
作者回复: APISIX 里面是做了一层封装:core.table.new(),其实底层还是 table.new
2019-08-25 - HelloBug老师,APISIX中的load函数少个end.
作者回复: 多谢
2019-08-25 - HelloBug老师,文中有这样一段话: 也就是说,你用 table.new(narray, nhash) 生了一个长度为 100 的数组,clear 后,长度还是 100。 哈哈,生了一个数组
作者回复: 好眼神:)
2019-08-25 - HelloBug老师,数组以空间换时间创建时,应该是没有resize 和rehash 操作的,而不是这些操作一次完成的是吧?
作者回复: 是的,如果不超过 table.new 的预设大小,是没有这些操作的。
2019-08-25 - 许童童table优化总结: 预先定义大小:空间换时间 table池:对象复用 计算下标:改进算法
作者回复: 是的,很多优化都是抠出来的
2019-08-09
收起评论