• Python 函数调用性能记录


    之前用 JS 写项目的时候,项目组用的组件模式,一直感觉很不错。最近用 Python 做新项目,项目结构也延续了组件模式。一直没有对函数调用的性能作了解,今天突发奇想测试了一下,写了一些测试代码

    首先定义了几个 class :

    class A(object):
        def test(self):
            pass
    
    class B(object):
        def __init__(self):
            self.a = A()
    
        def test(self):
            pass
    
    class C(object):
        def __init__(self):
            self.b = B()
    
        def test(self):
            pass
    
    class D(object):
        def __init__(self):
            self.c = C()
        def test(self):
            pass

    对比1:

    直接调用实例对象身上的方法 和 使用变量缓存该方法然后调用

    n = 10000000
    import timeit
    
    a = A()
    t_direct = timeit.Timer('a.test()', 'from __main__ import a').timeit(n)
    print 'direct call func : ', t_direct
    
    cache = a.test
    t_cache = timeit.Timer('cache()', 'from __main__ import cache').timeit(n)
    print 'cache func call  : ', t_cache
    
    print ' performance : ', (t_cache / t_direct)

    尝试多次后得出该情况下的时间结论:

    direct call func :  1.14136314392
    cache func call  :  0.745277881622
     performance :  0.652971743123

    缓存方法之后再调用,性能大约能提升 35%

    调用函数时,python 会临时创建一个对象,比如直接调用函数 a.test() 时,python 会执行如下步骤:

    1: temp = a.test

    2: temp()

    3: del temp

    所以频繁调用时,性能上是一个问题。内存上应该也是一个问题,感觉会更加频繁的触发 gc

    对比2:

    通过成员变量多层调用一个函数,和直接调用对象身上的函数的性能差

    t0 = timeit.Timer('d.test()', 'from __main__ import d').timeit(n)
    print '0 level:  ', t0
    
    t1 = timeit.Timer('d.c.test()', 'from __main__ import d').timeit(n)
    print '1 level:  ', t1, '    : ', (t1 / t0) * 100
    
    t2 = timeit.Timer('d.c.b.test()', 'from __main__ import d').timeit(n)
    print '2 level:  ', t2, '    : ', (t2 / t1) * 100, '    ', (t2 / t0 * 100)
    
    t3 = timeit.Timer('d.c.b.a.test()', 'from __main__ import d').timeit(n)
    print '3 level:  ', t3, '    : ', (t3 / t2) * 100, '    ', (t3 / t0 * 100)

    尝试多次后得出该情况下的时间结论:

    0 level:   1.26769399643

    1 level:   1.50338602066     :  118.592185882

    2 level:   1.74297595024     :  115.936687337      137.491851752

    3 level:   1.87865877151     :  107.784549251      148.194972667

    基本上,函数调用层次多一层,性能消耗会多 5% 到 15% 左右

    这个暂时无法详细的解答。手上也没有 JS 的测试数据,不确定当时 js 些写项目的时候,是否也存在这个性能问题。

    之前碰到一些项目的结构是,写的时候分成了多个文件来写,但是最后运行的时候,会把这多个文件中定义的 属性、函数都聚合到一个 class 身上,成为一个巨无霸级的 class。一直不理解这么做的意义是什么,感觉很臃肿,现在看来 估计为了减少函数调用的层次,提高性能。

  • 相关阅读:
    java、el表达式中保留小数的方法
    EL表达式取整数或者取固定小数位数的简单实现
    Spring框架学习之第8节
    shell脚本接收输入
    awk除去重复行
    awk过滤统计不重复的行
    Spring框架学习之第7节
    jsp中利用checkbox进行批量删除
    javaScript解决Form的嵌套
    Spring框架学习之第6节
  • 原文地址:https://www.cnblogs.com/cg-wang/p/6754748.html
Copyright © 2020-2023  润新知