• lua协程并发下载简单测试


    下载8个1m大小文件,测试五次分别耗时12.038s,10.316s,8.955s,11.275s,9.499s(lua代码实现如下)

    require "socket"
    
    --host = "www.w3.org"
    --file = "/TR/REC-html32.html"
    
    function lua_string_split(str, split_char)    --字符串拆分
    
        local sub_str_tab = {};
        while (true and str ~= nil) do
            local pos = string.find(str, split_char);
            if (not pos) then
                sub_str_tab[#sub_str_tab + 1] = str;
                break;
            end
            local sub_str = string.sub(str, 1, pos - 1);
            sub_str_tab[#sub_str_tab + 1] = sub_str;
            str = string.sub(str, pos + 1, #str);
        end
    
        return sub_str_tab;
    end
    
    
    function download(url)
        local infolist = lua_string_split(url,"/")
        local cache_file = infolist[#infolist]
    
        local host = infolist[3]
        local pos = string.find(url, host)
        local file = nil
        if pos then
            file = string.sub(url, pos + #host)
        end
        pos = nil
    
        local out = io.open(cache_file,"wb")
        local c = assert(socket.connect(host, 80))
        local count = 0
        local pos = nil
    
        c:send("GET " ..file .." HTTP/1.0
    
    ")
        while true do
            local s, status, partial = receive(c)
            count = count + #(s or partial)
            local data = s or partial
    
            if data then
                if pos == nil then            --去除响应头
                    pos = string.find(data, "
    
    ")
                    if pos then
                        out:write(string.sub(data, pos + #"
    
    "))
                    end
                else
                    out:write(data)
                end
            end
            if status == "closed" then break end
        end
        c:close()
    --  print(file, count)
        out:close()
    --    os.execute("del " .. cache_file)
    end
    
    function receive(connection)
        connection:settimeout(0)
        local s, status, partial = connection:receive(2^10*100)
        if status == 'timeout' then
            coroutine.yield(connection)
        end
        return s or partial, status
    end
    
    threads = {}
    
    function get(url)
        local co = coroutine.create(function ()
            download(url)
        end)
        table.insert(threads, co)
    end
    
    function dispatch()
        local i = 1
        local connections = {}
        while true do
            if threads[i] == nil then
                if threads[1] == nil then break end
                i = 1
                connections = {}
            end
            local status, res = coroutine.resume(threads[i])
            if not res then
                table.remove(threads, i)
            else
                i = i + 1
                connections[#connections + 1] = res
                if #connections == #threads then
                    local a, b, err = socket.select(connections)
                    for k, v in pairs(a) do
                        --print(k, 'a=a', v)
                    end
                    for k, v in pairs(b) do
                        --print(k, 'b=b', v)
                    end
                end
            end
        end
    end
    
    --get("http://www.w3.org/TR/REC-html32.html")
    --get("http:///1/将夜") --下载中文会出错
    
    
    local files = {'a','b','c','d','e','f','g','h'}
    for i=1,#files do
        get("http://127.0.0.1/" .. files[i] .. ".file")
    end
    
    dispatch()
    
    print(os.clock())

    下载8个1m大小文件,测试五次分别耗时12.324s,14.407s,13.883s,15.188s,8.887s(python代码实现如下)

    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    import sys
    import os
    import time
    import urllib
    import urllib2
    import multiprocessing
    from time import clock
    
    def worker(pline):
    
            rinfo = pline.split("/")
            filename, url = rinfo[len(rinfo)-1], pline
    
            filename = urllib2.unquote(filename)
            try:
                    f = urllib2.urlopen(url,timeout=10800)
                    with open(filename, "wb") as code:
                            code.write(f.read())
            except:
                    print sys.exc_info()
                    return 0
    
            return 1
    #
    # main
    #
    
    if __name__ == "__main__":
    
            start = clock()
            pool_size = multiprocessing.cpu_count() * 2
            pool = multiprocessing.Pool(processes=pool_size)
    
            for i in ["a","b","c","d","e","f","g","h"]:
                    url = "http://127.0.0.1/"+i+".file"
                    pool.apply_async(worker, (url,))
                    
            pool.close()
            pool.join()
            end = clock()
            print (end-start)

    就算把python的进程池设置为1个,利用单cpu跑,耗时结果测试也是一样的。看不出来lua的协程对性能有多大的提升,感觉用多进程能实现的,就还是不要去折腾协程吧,毕竟协程不能利用多核的优势,编程也麻烦很多。

    附:lua使用luasocket库发起http请求很方便

    local http = require("socket.http")
    
    local chunkbody = {}
    res, code, headers = http.request {
            method = "GET",
            url = "http://127.0.0.1/get.php",
            sink = ltn12.sink.table(chunkbody)
    }
    
    if res ~= nil then
            print(code)
            for k,v in pairs(headers) do
                    print(k .. ":" .. v)
            end
            print(table.concat(chunkbody))
    else
            io.write(code .. "
    ")
    end
    
    --res, code, headers = http.request("http://127.0.0.1/post","name=admin&passwd=adminpwd")
    local postdata = "name=admin&passwd=adminpwd"
    chunkbody = {}
    res, code, headers = http.request {
            method = "POST",
            url = "http://127.0.0.1/post",
            headers = {
                    ["Content-Type"] = "application/x-www-form-urlencoded",
                    ["Content-Length"] = string.len(postdata)
            },
            source = ltn12.source.string(postdata),
            sink = ltn12.sink.table(chunkbody)
    }
    if res ~= nil then
            print(code)
            for k,v in pairs(headers) do
                    print(k .. ":" .. v)
            end
            print(table.concat(chunkbody))
    else
            io.write(code .. "
    ")
    end
    
    --[[
    200
    connection:close
    content-type:text/html
    date:Sun, 16 Nov 2014 16:02:16 GMT
    transfer-encoding:chunked
    x-powered-by:PHP/5.3.3
    server:openresty/1.7.2.1
    a and b
    201
    connection:close
    content-type:application/octet-stream
    date:Sun, 16 Nov 2014 16:02:16 GMT
    transfer-encoding:chunked
    server:openresty/1.7.2.1
    pass
    --]]
  • 相关阅读:
    16 pymysql模块的使用
    15 可视化工具 Navicat的简单使用
    14 补充 MySQL的创建用户和授权
    13 多表查询
    linux常用查看文件或日志命令
    linux查找大文件命令
    linux测试环境维护之磁盘空间维护
    linux配置IP访问权限
    通过pytty工具代理连接数据库mysql(绕开数据库白名单限制)
    redis安装详解
  • 原文地址:https://www.cnblogs.com/ciaos/p/3159566.html
Copyright © 2020-2023  润新知