Lua协程使用困惑求解
最近学习Lua
的coroutine
章节时,总对其使用场景及其意义不明白,自己也试着写了一些代码,但仍然没搞明白。
下面是我写的一段模拟下载网页的程序,使用协程和不使用协程耗时几乎相同,实在没能理解coroutine
的非阻塞特性的价值。
-- 本例模拟耗时处理,如下载资源等,使用coroutine优化
local queue = {}
function insert( url )
local co = coroutine.create(function ( ... )
handle(url)
end)
table.insert(queue ,co)
end
-- 代表下载网页逻辑,这里使用休眠函数模拟
function handle( url )
sleep(1)
print('下载完成:' ,url)
end
-- 模拟休眠函数
function sleep(n)
if n > 0 then
os.execute("ping -n " .. tonumber(n+1) .. " localhost > NUL")
end
end
function start( ... )
for _ ,co in ipairs(queue) do
local status ,res = coroutine.resume(co)
print(status ,res)
end
end
insert('/image/1.png')
insert('/image/2.png')
insert('/image/3.png')
start()
-- XXX 测试 coroutine 并不能提升响应时间,如果体现其非阻塞特性?
-- handle('/image/1.png')
-- handle('/image/2.png')
-- handle('/image/3.png')
程序使用休眠代替实际下载逻辑,实际测试下来使用协程和不使用协程耗时并无区别,除了调用过程更加复杂,似乎没感觉到什么区别。当然非阻塞的价值也许并不体现在耗时优化上,但看很多socket
库使用coroutine
来优化,没太理解这样做的用意,如果说有10个下载任务,单线程上再怎么异步也不能提升性能吧。
有精通这块的,烦请给稍微讲解一下,后面也准备去读一些开源库的源码研究一下。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
用协程优化这种网络操作其实原理类似于一个脑筋急转弯:“用一个锅煎1个鸡蛋要3分钟,请问煎3个鸡蛋要几分钟?”
对于网络库而言,如果网络API用的是阻塞API的话,recv操作会阻塞到有合适的缓冲区内容为止,但是recv操作本身并不是用来准备缓冲区的操作,意思就是如果 recv 操作晚于网卡接收数据,也能正确的从缓存获取数据,因而如果在send操作之后就yield当前的coroutine,然后去做一些其他的事(比如再开几个连接),等一会儿再resume回来进行recv操作就可以提高并发度。
相当于说是从:
变成:
当然单是这样的话提高的并发度非常有限,要真正提高并发度到一个实用的水准还是得用IO多路复用。