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

32 | 让人又恨又爱的字符串操作

性能差异会有多大
写出不用字符串拼接的示例代码
对 LuaJIT 和 OpenResty 的 Lua API 了如指掌
抠细节
使用 string.byte 和 string.char
优化效果
示例代码分析
使用 string.byte 和 string.char
示例:字符串拼接操作
字符串不可变的好处
不阻塞主线程
在一个 API 中只做一件事情
请求生命周期要短
掌握优化技巧背后的理念
技巧随版本迭代而变化
学习和交流
作业题
OpenResty 的性能优化
利用 SDK 对 table 类型的支持
减少其他临时字符串
字符串拼接优化
利用 SDK 对 table 类型的支持
减少其他临时字符串
字符串是不可变的
理念二:避免产生中间数据
理念一:处理请求要短、平、快
优化技巧的背后
总结
性能优化实例
性能优化技巧

该思维导图由 AI 生成,仅供参考

你好,我是温铭。
上节课里,我带你熟悉了 OpenResty 中常见的阻塞函数,它们都是初学者经常犯错的地方。从今天开始,我们就要进入性能优化的核心部分了,这其中会涉及到很多优化的技巧,可以帮助你快速提升 OpenResty 代码的性能,所以千万不要掉以轻心。
在这个过程中,你需要多写一些测试代码,来体会这些优化技巧如何使用,并验证它们的有效性,做到心中有数,拿来即用。

性能优化技巧的背后

优化技巧都是属于“术”的部分,在此之前,我们不妨先来聊一下优化之“道”。
性能优化的技巧,会随着 LuaJIT 和 OpenResty 的版本迭代而发生变化,一些技巧可能直接被底层技术优化,不再需要我们掌握;同时,也另会有一些新的优化技巧产生。所以,掌握这些优化技巧背后的不变的理念,才是最为重要的。
下面,让我们先来看下,在 OpenResty 编程中,有关性能方面的几个重要理念。

理念一:处理请求要短、平、快

OpenResty 是一个 Web 服务器,所以经常会同时处理几千、几万甚至几十万的终端请求。想要在整体上达到最高性能,我们就一定要保证单个请求被快速地处理完成,并回收内存等各种资源。
这里提到的“短”,是指请求的生命周期要短,不要长时间占用资源而不释放;即使是长连接,也要设定一个时间或者请求次数的阈值,来定期地释放资源。
第二个字“平”,则是指在一个 API 中只做一件事情。要把复杂的业务逻辑拆散为多个 API,保持代码的简洁。
最后的“快”,是指不要阻塞主线程,不要有大量 CPU 运算。即使是不得不有这样的逻辑,也别忘了咱们上节课介绍的方法,要配合其他的服务去完成。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

OpenResty 中字符串操作的性能优化技巧是本文的重点。作者首先强调了性能优化的重要性,并提出了处理请求要短、平、快以及避免产生中间数据的两个重要理念。文章详细讲解了字符串在 Lua 中的不可变性质,以及对字符串进行拼接操作时可能产生的临时字符串,并给出了使用 table 进行优化的示例代码。此外,作者还提到了使用 `string.sub` 函数可能产生临时字符串的问题,并给出了使用 `string.byte` 和 `string.char` 函数来避免临时字符串生成的替代方案。通过具体的示例代码和优化方法,读者可以了解在 OpenResty 中进行字符串操作时的性能优化技巧,对于提升代码性能具有一定的指导意义。文章还提到了利用 SDK 对 table 类型的支持,以及在 `ngx.say`、`ngx.print` 、`ngx.log`、`cosocket:send` 等 API 中使用 table 作为参数来优化字符串拼接的方法。最后,读者被鼓励思考并分享自己的答案和感想,以及将文章分享给朋友一起学习和交流。整体来说,本文通过深入的技术讲解和实用的示例代码,帮助读者快速了解 OpenResty 中字符串操作的性能优化技巧。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《OpenResty 从入门到实战》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(10)

  • 最新
  • 精选
  • 林中木
    温老师,请教一个很困扰的问题: 根据你的指点,要尽量少用 .. 字符串拼接,特别是在代码热区 但是我在处理数据库访问时,需要动态构建sql语句(在语句中插入变量),这应该是非常常见的使用场景,但这个需求,我目前感觉字符串拼接是最简单办法了,其他我真的想不到即简单又高性能的办法。 另外我现在想用OR做一个web项目,但做起来很痛苦啊,主要是没找到成熟的框架,需要自己造很多轮子,就比如说上面的数据库操作问题(没找到可以动态构建sql语句、连贯操作的类库),在web框架上有什么好的可以推荐吗? 等候你的高见! 恳请多多指点。

    作者回复: 可以先用火焰图或者其他工具分析下,看 sql 语句的拼接是否是系统的瓶颈,如果不是,自然没有优化的必要性。如果是的话,可以利用数据库的 `prepare` 语句来做优化,也可以用数组的方式来做拼接。 OpenResty 现在确实没有好用的框架,lor、香草这两个可以尝试下。

    2019-09-10
    2
    2
  • HelloBug
    温铭老师,发现需要GC 操作的会是比较耗时的,可以介绍下GC操作的场景吗?

    作者回复: 一般是在处理完比较大的对象之后,需要手工 GC 一下。比如字符串对象有几十兆,处理完得到结果之后,手工调用collectgarbage一下。

    2019-08-18
    1
  • helloworld
    作业题: ngx.log(ngx.ERR, "Hello ", "world", "!") 另外我测试字符串10个a的拼接和1个a的拼接所用时间是一个数量级的,性能基本没变化。 还有一个就是我测试ngx.say(table)的性能比先table.concat拼接,再ngx.say打印拼接后的字符串的性能要低一倍,测几次都是这个结果,这个是什么原因呢

    作者回复: 能给下你测试的代码吗?

    2019-08-07
    2
    1
  • Shliesce
    作业题: local t = {} t[1] = "hello " t[2] = "world " t[3] = "!" ngx.log(ngx.ERR, t[1], t[2], t[3])

    作者回复: ngx.log(ngx.ERR, 'hello', ' world', '!') 是更简单的方式,你可以试下

    2019-08-12
  • wusiration
    作业题1:当字符串由"a"变成"aaaaaaaaaa"时,代码用时0.007000207901001,性能基本没有差别,因为指向的是同一个字符串,只不过是字符串的内容发生了变化; 作业题2: resty -e ' local helloworld = {"Hello", "World", "!"} helloworld = setmetatable(helloworld, { __tostring = function(t) return string.format("%s %s %s", t[1], t[2], t[3]) end }) ngx.log(ngx.WARN, helloworld) '

    作者回复: ngx.log是可以直接跟变参的,这一点文档中并没有写的很明确: ngx.log(ngx.WARN, 'hello ', 'world', '!') 这种是最简单的。

    2019-08-07
  • helloworld
    local ok, err = red:connect("127.0.0.1", 6379) if not ok then ngx.say("failed to connect: ", err) red:close() -- 老师,我看到有写项目代码里在这里加上这句,有必要吗? return end

    作者回复: 我觉得没必要,都没有连接上,close 也没啥意义。

    2019-08-07
  • Rye
    温老师,听说string.format的消耗大效 率低,不知道具体是什么原因,有什么好的字符串模板方案么?

    作者回复: 我都是用数组的方式自己拼接,比较笨的方法

    2019-08-07
  • helloworld
    老师,代码在这里,就是用的你文章中的代码: 测试ngx.say(table)的性能比先table.concat拼接,再ngx.say打印拼接后的字符串的性能要低一倍的问题。 local begin = ngx.now() local t = {} local index = 1 for i = 1, 100000 do t[index] = "a" index = index + 1 end --local s = table.concat(t, "") -- 测试1 --ngx.say(s) -- 测试1 用时:0.003000020980835 ngx.say(t) -- 测试 2 用时:0.01200008392334 ngx.update_time() ngx.say(ngx.now() - begin) 这次又测了一遍,貌似低了三四倍。
    2019-08-19
    1
    1
  • 宝仔
    思考题:如果新增的字符串是10个a,性能变化不大。但是如果是直接字符串拼接的方式,那性能差距就大了
    2020-02-03
  • 许童童
    新增的字符串是 10 个 a 的长度,个人分析,不会有什么性能差异,因为10个a这个字符串一但分配在内存中,在下一次GC前,都是指向这个相同的内存地址,并没有开辟新的内存空间。
    2019-08-07
收起评论
显示
设置
留言
10
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部