码迷,mamicode.com
首页 > 其他好文 > 详细

[原]异步编程的两种模型,闭包回调,和Lua的coroutine,到底哪一种消耗更大

时间:2016-08-16 07:01:11      阅读:382      评论:0      收藏:0      [点我收藏+]

标签:

今天和人讨论了一下CPS变形为闭包回调(典型为C#和JS),以及Lua这种具有真正堆栈,可以yield和resume的coroutine,两种以同步的形式写异步处理逻辑的解决方案的优缺点。之后突然想到,这两种做法,到底拿一种会更消耗。我自己的判断是,在一次调用只有一两个异步调用中断时(即有2次回调,或者2次yield),闭包回调的方式性能更好,因为coroutine的方式需要创建一个具有完全堆栈的协程,相对来说还是太重度了。但是如果一次调用中的异步调用非常多,那么coroutine的方式性能更好,因为不管多少次yield,coroutine始终只需要创建一次协程,而闭包回调的每一次调用都必须创建闭包函数,GC的开销不算小。直接上测试代码

CPS:

local count = 1000000

local list1 = {}
local list2 = {}
local clock = os.clock
local insert = table.insert
local remove = table.remove

local function setcb(fn)
    insert(list1, fn)
end

local function test1()
    setcb(function()
        
    end)
end

local time1 = clock()--开始
for i = 1, count do
    test1()
end
local time2 = clock()--调用
while true do
    list1, list2 = list2, list1
    for i = 1, #list2 do
        remove(list2)()
    end
    if #list1 == 0 then
        break
    end
end
local time3 = clock()--回调完全结束

print(time2 - time1, time3 - time2)

coroutine:

local count = 1000000

local list1 = {}
local list2 = {}
local clock = os.clock
local insert = table.insert
local remove = table.remove
local create = coroutine.create
local yield = coroutine.yield
local running = coroutine.running
local resume = coroutine.resume

local function setcb()
    insert(list1, running())
    yield()
end

local function test2()
    setcb()
end


local function test1()
    resume(create(test2))
end

local time1 = clock()--开始
for i = 1, count do
    test1()
end
local time2 = clock()--调用
while true do
    list1, list2 = list2, list1
    for i = 1, #list2 do
        resume(remove(list2))
    end
    if #list1 == 0 then
        break
    end
end
local time3 = clock()--回调完全结束

print(time2 - time1, time3 - time2)

输出:

技术分享

coroutine的调用和唤醒/回调,比闭包回调慢不少

(PS. 这里有个插曲,我之前设置的count = 10000000,但是测试coroutine时报内存不足的错误,因此只能下降一个数量级来测试了)

接下来我把单次调用的回调次数增多

CPS:

local count = 1000000

local list1 = {}
local list2 = {}
local clock = os.clock
local insert = table.insert
local remove = table.remove

local function setcb(fn)
    insert(list1, fn)
end

local function test1()
    setcb(function()
        setcb(function()
            setcb(function()
                setcb(function()
                    setcb(function()
                        setcb(function()
                            setcb(function()
                                
                            end)
                        end)
                    end)
                end)
            end)
        end)
    end)
end

local time1 = clock()--开始
for i = 1, count do
    test1()
end
local time2 = clock()--调用
while true do
    list1, list2 = list2, list1
    for i = 1, #list2 do
        remove(list2)()
    end
    if #list1 == 0 then
        break
    end
end
local time3 = clock()--回调完全结束

print(time2 - time1, time3 - time2)

coroutine:

local count = 1000000

local list1 = {}
local list2 = {}
local clock = os.clock
local insert = table.insert
local remove = table.remove
local create = coroutine.create
local yield = coroutine.yield
local running = coroutine.running
local resume = coroutine.resume

local function setcb()
    insert(list1, running())
    yield()
end

local function test2()
    setcb()
    setcb()
    setcb()
    setcb()
    setcb()
    setcb()
    setcb()
end


local function test1()
    resume(create(test2))
end

local time1 = clock()--开始
for i = 1, count do
    test1()
end
local time2 = clock()--调用
while true do
    list1, list2 = list2, list1
    for i = 1, #list2 do
        resume(remove(list2))
    end
    if #list1 == 0 then
        break
    end
end
local time3 = clock()--回调完全结束

print(time2 - time1, time3 - time2)

输出:

技术分享

回调的消耗仍然是coroutine处于劣势,但已经比较接近了。启动的消耗,由于coroutine需要创建比较大的堆栈,相对于闭包来说还是比较重度,因此启动仍然远远慢于闭包回调的方式。

最后,我把一次调用里的异步接口调用次数,改成到98次(再多lua会报错:chunk has too many syntax levels),对比如下(此时次数都改成了count = 100000):

技术分享

结论:闭包依然具备优势。

[原]异步编程的两种模型,闭包回调,和Lua的coroutine,到底哪一种消耗更大

标签:

原文地址:http://www.cnblogs.com/libla/p/5774924.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!