zoukankan      html  css  js  c++  java
  • 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
    --]]
  • 相关阅读:
    创建类以及引用一个类
    修改hosts文件
    微信第三方登录接口开发
    Android定位
    Leetcode 102. Binary Tree Level Order Traversal
    Leetcode 725. Split Linked List in Parts
    Leetcode 445. Add Two Numbers II
    Leetcode 328. Odd Even Linked List
    Leetcode 237. Delete Node in a Linked List
    Leetcode 234. Palindrome Linked List
  • 原文地址:https://www.cnblogs.com/ciaos/p/3159566.html
Copyright © 2011-2022 走看看