lua 的协程池写法

闲来,写了一个协程池
目标是能实现写成复用,而不需要反复去生成新的协程
具体见代码注释
代码如下:

local co_running    = assert(coroutine.running)
local co_create     = assert(coroutine.create)
local co_yield      = assert(coroutine.yield)
local co_resume     = assert(coroutine.resume)

local co_pools = {}

local function create_co(func)

    local co = table.remove(co_pools)
    if co then
        
        -- 如果有此协程,那么直接唤醒并进行使用
        -- 协程内部已经将执行函数设置为新的 func
        co_resume(co, func)

    else

        -- 如果没有此协程,那么需要新建一个辅助协程
        co = co_create(function()
            
            -- 执行入口函数
            func()
            
            -- 类似于一个主循环,永远不退出本协程
            while true do

                -- 执行完后,重新放入到池,等待下一次唤醒
                table.insert(co_pools, co)

                -- 执行完毕挂起来等待,下次唤醒之后,就是新的入口函数了
                func = co_yield(0)

                -- 先不执行,等待下一个唤醒,主动进行
                co_yield()

                -- 执行,外部调用了 resume
                func()
            
            end

        end)

    end

    return co

end

local function test_1()

    print("test 1 ----->>. ", co_running())

end

local function test_2()

    print("test 2 ------->>.", co_running())

    co_yield "aaa"

end

local function test_3()

    print("test 3 ------>>. ", co_running())

end

local function test_pool()

    local co_1 = create_co(test_1)
    co_resume(co_1)

    local co_2 = create_co(test_2)
    local co_3 = create_co(test_3)

    co_resume(co_2)
    co_resume(co_3)

end

function main()

    print("enter main function!")
        
    test_pool()
    

end

main()

代码输出:

nter main function!
test 1 ----->>.         thread: 0x7f9703402c88  false
test 2 ------->>.       thread: 0x7f9703402c88  false
test 3 ------>>.        thread: 0x7f9703407fb8  false

可以看到,test2 函数在执行的时候,复用了 test1 函数执行时的协程
test3 由于在执行时,test2 并未完全执行完并挂起,所以只能新启动了一个协程

那么,加上协程池跟使用原生协程的写法,有什么不同?
直观上来说,协程池避免了重复生成新协程,在运行效率、小对象生成上是能做到节省的

我们引入多个数量级的反复请求生成协程的场景来验证,测试代码如下:

local function test_co_loop(co_create_func)

    local function empty_func()

    end

    local start_test_time = os.time()
    local start_test_mem = collectgarbage("count")

    local test_times = 10000000
    for i = 1, test_times do
        local co = co_create_func(empty_func)
        co_resume(co)
    end

    local stop_test_mem = collectgarbage("count")
    local stop_test_time = os.time()

    print("loop create co multi times, ", test_times, "cost time:", stop_test_time - start_test_time, "mem:", stop_test_mem - start_test_mem)

end

local function test_2ways_create_pool()

    print("testing origin co_create...")
    test_co_loop(co_create)

    print("testing pool create_co...")
    test_co_loop(create_co)

end

得到的输出(仅参考)

1000000(百万级)

testing origin co_create...
loop create co multi times,     10000000        cost time:      4       mem:    19.5849609375
testing pool create_co...
loop create co multi times,     10000000        cost time:      5       mem:    0.0

100000(十万级)

testing origin co_create...
loop create co multi times,     100000  cost time:      0       mem:    5.0849609375
testing pool create_co...
loop create co multi times,     100000  cost time:      0       mem:    0.0

可以看到,两种用法在时间上是没有明显的优劣之分的
但在内存上可以看出差距(主要是小对象产生的、未来得及回收的垃圾)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值