OpenResty 从入门到实战
温铭
OpenResty 软件基金会第一任主席,Apache APISIX 项目 VP
20903 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 52 讲
结束语 (1讲)
OpenResty 从入门到实战
15
15
1.0x
00:00/00:00
登录|注册

33 | 性能提升10倍的秘诀:必须用好 table

release方法
fetch方法
示例代码
示例代码
LuaJIT中的table.new(narray, nhash)函数
lua-tablepool
示例代码
清理原有数据
table.clear函数
自己计算table下标
计算数组长度
table.insert函数
预先生成数组
初始化数据
空数组
table池
循环使用单个table
清空数组
插入元素
创建数组
table
性能提升10倍的秘诀

该思维导图由 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
立即购买
登录 后留言

全部留言(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-11
    3
  • HelloBug
    OpenResty是从哪个版本开始完全绑定LuaJIT的呢?

    作者回复: 我记得是 1.15 这个版本开始就只支持自己的 LuaJIT 了。lua 和官方的 luajit 都不再支持了

    2019-08-25
    2
  • HelloBug
    老师好,文章中提到table. new 函数属于LuaJIT的扩展,是OpenResty维护的LuaJIT分支的扩展还是就是LuaJIT的扩展?

    作者回复: 这个函数是 LuaJIT 的扩展

    2019-08-25
    1
  • 见习勇者
    问老师,您好,我有个疑问,您举例的table复用的阶段是在init_worker阶段,这个阶段只会在初始化worker的时候调用一次,并不会影响实际的请求,有必要进行这样的优化么?对后续的请求处理有提升么?

    作者回复: 算是一个习惯了,如果是 init worker 阶段确实优化不了多少

    2019-08-13
    1
  • dingjiayi
    温老师,有没有比较优雅的方式去切割 access.log 和 error.log 现在我看到网上介绍的方案都是 lograte 或者crontab 启动定时任务去切割 想请问nginx 有自带切割日志的功能吗?或者有比crontab 更优雅的方案吗

    作者回复: 你可以使用 OpenResty 的特权进程来做日志文件的切割,等于自己用 timer.every 来实现了crontab的功能。

    2019-08-10
    1
  • HelloBug
    table. 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
收起评论
显示
设置
留言
12
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部