Python3用多線程替代for循環提高程序運行速度

[本文出自天外歸雲的博客園]git

優化先後新老代碼以下:編程

from git_tools.git_tool import get_collect_projects, QQNews_Git
from threading import Thread, Lock
import datetime

base_url = "http://git.xx.com"
project_members_commits_lang_info = {}
lock = Lock()
threads = []

'''
Author:zenkilan
'''


def count_time(func):
    def took_up_time(*args, **kwargs):
        start_time = datetime.datetime.now()
        ret = func(*args, **kwargs)
        end_time = datetime.datetime.now()
        took_up_time = (end_time - start_time).total_seconds()
        print(f"{func.__name__} execution took up time:{took_up_time}")
        return ret

    return took_up_time


def get_project_member_lang_code_lines(git, member, begin_date, end_date):
    global project_members_commits_lang_info
    global lock
    member_name = member["username"]
    r = git.get_user_info(member_name)
    if not r["id"]:
        return
    user_commits_lang_info = git.get_commits_user_lang_diff_between(r["id"], begin_date, end_date)
    if len(user_commits_lang_info) == 0:
        return
    lock.acquire()
    project_members_commits_lang_info.setdefault(git.project, dict())
    project_members_commits_lang_info[git.project][member_name] = user_commits_lang_info
    lock.release()


def get_project_lang_code_lines(project, begin_date, end_date):
    global threads
    git = QQNews_Git(project[1], base_url, project[0])
    project_members = git.get_project_members()
    if len(project_members) == 0:
        return
    for member in project_members:
        thread = Thread(target=get_project_member_lang_code_lines, args=(git, member, begin_date, end_date))
        threads.append(thread)
        thread.start()


@count_time
def get_projects_lang_code_lines(begin_date, end_date):
    """
    獲取項目代碼行語言相關統計——新方法(提高效率)
    應用多線程替代for循環
    併發訪問共享外部資源
    :return:
    """
    global project_members_commits_lang_info
    global threads
    for project in get_collect_projects():
        thread = Thread(target=get_project_lang_code_lines, args=(project, begin_date, end_date))
        threads.append(thread)
        thread.start()


@count_time
def get_projects_lang_code_lines_old(begin_date, end_date):
    """
    獲取項目代碼行語言相關統計——老方法(耗時嚴重)
    使用最基本的思路進行編程
    雙層for循環嵌套而且每層都包含耗時操做
    :return:
    """
    project_members_commits_lang_info = {}
    for project in get_collect_projects():
        git = QQNews_Git(project[1], base_url, project[0])
        project_members = git.get_project_members()
        user_commits_lang_info_dict = {}
        if len(project_members) == 0:
            continue
        for member in project_members:
            member_name = member["username"]
            r = git.get_user_info(member_name, debug=False)
            if not r["id"]:
                continue
            try:
                user_commits_lang_info = git.get_commits_user_lang_diff_between(r["id"], begin_date, end_date)
                if len(user_commits_lang_info) == 0:
                    continue
                user_commits_lang_info_dict[member_name] = user_commits_lang_info
                project_members_commits_lang_info[git.project] = user_commits_lang_info_dict
            except:
                pass
    return project_members_commits_lang_info


def test_results_equal(resultA, resultB):
    """
    測試方法
    :param resultA:
    :param resultB:
    :return:
    """
    print(resultA)
    print(resultB)
    assert len(str(resultA)) == len(str(resultB))


if __name__ == '__main__':
    from git_tools.config import begin_date, end_date

    get_projects_lang_code_lines(begin_date, end_date)
    for t in threads:
        t.join()
    old_result = get_projects_lang_code_lines_old(begin_date, end_date)
    test_results_equal(old_result, project_members_commits_lang_info)

老方法裏外層for循環和內層for循環裏均存在耗時操做:多線程

1)git.get_project_members()併發

2)git.get_user_info(member_name, debug=False)app

分兩步來優化,先裏後外或先外后里都行。用多線程替換for循環,併發共享外部資源,加鎖避免寫衝突。函數

測試結果經過,函數運行時間裝飾器顯示(單位秒):測試

get_projects_lang_code_lines execution took up time:1.85294優化

get_projects_lang_code_lines_old execution took up time:108.604177ui

速度提高了約58倍url

相關文章
相關標籤/搜索