CXYVIP官网源码交易平台_网站源码_商城源码_小程序源码平台-丞旭猿论坛
CXYVIP官网源码交易平台_网站源码_商城源码_小程序源码平台-丞旭猿论坛
CXYVIP官网源码交易平台_网站源码_商城源码_小程序源码平台-丞旭猿论坛

使用工具分析python代码优化性能提高90%-源码交易平台丞旭猿

背景

用户量增加,需要优化代码,本次优化性能提高近90%,
效果非常明显,优化点非常有意思,涉及到垃圾回收

我会造个示例展示给大家

关于性能分析的工具 可以网上搜 也可以看
effective python 第58章
  • 功能代码
import pandas as pd

res = []
for i in range(1000):
    res.extend([
        {location: i, name: x, age: 12},
        {location: i, name: x, age: 12}
    ])


def remove_duplicate(f):
    for _,_df in f.groupby(location):
        _df.drop_duplicates(inplace=True)
  • 使用cProfile分析工具
df = pd.DataFrame.from_records(res)

    profiler = Profile()
    profiler.runcall(remove_duplicate, df)

    stats = Stats(profiler)
    stats.strip_dirs()
    stats.sort_stats(cumulative)
    stats.print_stats()
  • 分析结果
ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.023    0.023   17.813   17.813 use_df_cprofile.py:35(remove_duplicate)
     1000    0.021    0.000   17.368    0.017 frame.py:3513(drop_duplicates)
     1000    0.007    0.000   15.475    0.015 generic.py:2586(_update_inplace)
     1000    0.003    0.000   15.446    0.015 generic.py:1897(_maybe_update_cacher)
     1000    0.031    0.000   15.440    0.015 generic.py:1987(_check_setitem_copy)
     1000   15.349    0.015   15.349    0.015 {gc.collect}
     1000    0.041    0.000    1.258    0.001 frame.py:3544(duplicated)
     3000    0.016    0.000    0.616    0.000 frame.py:3568(f)
     3001    0.052    0.000    0.582    0.000 algorithms.py:438(factorize)
     1001    0.016    0.000    0.504    0.001 internals.py:4243(take)

ncalls 代表总共调用次数
tottime 代表当前函数总的耗时 不含调用其他函数的耗时
cumtime  累计调用时间
percall  平均每次耗时

可以看出来 总耗时17.8s,其中执行垃圾回收(gc.collect)耗时15.349,
占总耗时的近90%,是什么导致的垃圾回收呢?
首先怀疑的是 remove_duplicate函数中的
inplace=True参数导致,为了验证猜想
修改函数代码
  • 新函数代码
def remove_duplicate(f):
    for _,_df in f.groupby(location):
        _df.drop_duplicates()
  • 新函数性能测试
ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.017    0.017    2.066    2.066 use_df_cprofile.py:35(remove_duplicate)
     1000    0.017    0.000    1.809    0.002 frame.py:3513(drop_duplicates)
     1000    0.035    0.000    1.079    0.001 frame.py:3544(duplicated)
     1001    0.010    0.000    0.622    0.001 frame.py:2115(__getitem__)
     1000    0.008    0.000    0.601    0.001 frame.py:2158(_getitem_array)
     1001    0.012    0.000    0.544    0.001 generic.py:2141(_take)
     3000    0.013    0.000    0.524    0.000 frame.py:3568(f)
     3001    0.044    0.000    0.495    0.000 algorithms.py:438(factorize)
     1001    0.013    0.000    0.468    0.000 internals.py:4243(take)
     1001    0.010    0.000    0.387    0.000 internals.py:4113(reindex_indexer)

耗时得到极大的优化,提升90%,猜想得到验证,
此时我们需要看下 到底为什么调用了gc.collect,
这时我们需要回到第一次的分析结果
  • 分析哪里调用的
一则通过看源码
二则结果分析结果的调用栈信息

ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.023    0.023   17.813   17.813 use_df_cprofile.py:35(remove_duplicate)
     1000    0.021    0.000   17.368    0.017 frame.py:3513(drop_duplicates)
     1000    0.007    0.000   15.475    0.015 generic.py:2586(_update_inplace)
     1000    0.003    0.000   15.446    0.015 generic.py:1897(_maybe_update_cacher)
     1000    0.031    0.000   15.440    0.015 generic.py:1987(_check_setitem_copy)
     1000   15.349    0.015   15.349    0.015 {gc.collect}

可以看到首先是frame.py中的drop_duplicates函数
drop_duplicates函数调用了generic.py文件中的_update_inplace函数
一次类推,generic.py文件中的 _check_setitem_copy函数
调用了C语言的 gc.collect
  • 阅读源码验证
_check_setitem_copy中的部分代码  可以看到确实显示调用了垃圾回收与之前的推测一致ifforceorself.is_copy:value=config.get_option(mode.chained_assignment)ifvalueisNone:returnsee if the copy is not actually refererd; if so, then disolvethe copy weakreftry:gc.collect(2)ifnotgc.get_referents(self.is_copy()):self.is_copy=Nonereturnexcept:pass
  • gc.collect 做了什么
python的垃圾回收 主要分为两个:
引用计算为主
标记清楚与分代回收为辅

分代回收主要针对容器对象(list,dict,instance等),解决循环引用的问题

分代回收会针对 0 1 2 代分别维护一个双链表,
系统触发分代回收或者显示调用gc.collect进行分代回收

当gc.collect(2)传入2时,代表针对0 1 2代所有维护的对象
进行垃圾回收,当服务端1,2代对象特别多时,整个遍历时间
也会变长,就会更耗时

有兴趣的可以去看下源码,非常推荐

实际生产代码优化效果会更明显,在工作中的实际代码之前执行要
70多秒,最后执行需要11秒

声明:本文部分素材转载自互联网,如有侵权立即删除 。

© 版权声明
THE END
喜欢就支持一下吧
点赞0赞赏 分享
相关推荐
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容