Python3+profile性能分析


一、說明

我們簡單地分析性能,可以通過運行前后的datatime.datatime.now()相減來確定運行兩個時間中間的代碼花費了多少時間。

但這種做法只能記錄單次運行花費的時間、不能方便計算運行多次平均花費的時間,更不能深入分析整個程序各函數所花費的時間。

 

二、利用timeit分析語句/函數性能

示例代碼如下:

import timeit


def test():
    """Stupid test function"""
    for i in range(10000):
        # print(i)
        continue

# 運行test函數10次,返回平均每次耗費的時間
# timeit.timeit(stmt='pass', setup='pass', timer=<default timer>, number=1000000, globals=None)
print("timeit directly:")
print(timeit.timeit(stmt="test()", setup="from __main__ import test", number=10))
# stmt參數也可以是直接的一條語句,下同
# print(timeit.timeit(stmt="'-'.join(str(n) for n in range(100))", setup="from __main__ import test", number=10))
# 運行test函數10次,返回各次所耗費時間組成的列表
# timeit.repeat(stmt='pass', setup='pass', timer=<default timer>, repeat=5, number=1000000, globals=None)
print("\nrepeat directly:")
print(timeit.repeat(stmt="test()", setup="from __main__ import test", number=10))

# 使用類的用處是對於同一條語句或函數,只寫一次,就可以周時用來timeit和repeat
# class timeit.Timer(stmt='pass', setup='pass', timer=<timer function>, globals=None)
timeit_obj = timeit.Timer(stmt="test()", setup="from __main__ import test")
# timeit.Timer.timeit(number=1000000)
print("\ntimeit by class:")
print(timeit_obj.timeit(number=10))
# timeit.Timer.repeat(repeat=5, number=1000000)
print("\nrepeat by class:")
print(timeit_obj.repeat(number=10))

運行結果如下:

 

三、使用profile分析整個程序性能

示例代碼如下:

import time
import cProfile, pstats, profile


def add(x, y):
    time.sleep(1)
    value = x + y
    return value


def sub(x, y):
    time.sleep(1.5)
    value = x - y
    return value


class TestProfile:
    def calc(self, x, y):
        time.sleep(1)
        add_result = add(x, y)
        sub_result = sub(x, y)
        print(f"{x} add {y} result is: {add_result}")
        print(f"{x} sub {y} result is: {sub_result}")


if __name__ == '__main__':
    obj = TestProfile()
    # 要分析的函數。
    # 原來調用該怎么寫就寫成相應的字符串形式就好了
    be_analysed_function = "obj.calc(1,2)"
    # 給此次監測命個名,隨意起。
    analysed_tag_name = "test_analysed"
    # 使用c語言版的profile進行分析,好處是自身占用資源更少,對函數的耗時定位更准確
    cProfile.run(be_analysed_function, analysed_tag_name)
    # 使用python版的profile進行分析,格式都一樣的。
    # profile.run(be_analysed_function, analysed_tag_name)

    # 對此次監測進行分析。
    s = pstats.Stats(analysed_tag_name)
    # 移除文件目錄,減少打印輸出
    # s.strip_dirs()
    # 排序。
    # "time"表示按函數總耗時排序,python3.7后可用枚舉變量pstat.SortKey來取排序項
    s.sort_stats("time")
    # 打印統計結果
    # ncalls--函數被調用的次數
    # tottime--此函數在所有調用中共耗費的時間秒數(不包括其調用的子函數耗費的時間)。分析耗時主要看這個。
    # percall--此函數平均每次被調用耗時。分析耗時次要看這個
    # cumtime--執行此函數及其調用子函數所占用的時間。
    # percall--此函數平均每次調用每個子函數所用的時間。
    s.print_stats()
    # print_stats的結果並不顯示誰調用的誰,比如是A調用的C還是B調用的C是不清楚的
    # 要打印出函數的調用者,可使用print_callers()
    # 結果中右邊是被調用函數,左邊是調用該函數的函數
    # s.print_callers()

運行結果如下圖:

 

參考:

https://docs.python.org/3/library/profile.html#module-cProfile

https://pymotw.com/2/profile/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM