关于读写文件执行速度 - V2EX
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
Virace

关于读写文件执行速度

  •  
  •   Virace Apr 14, 2021 2424 views
    This topic created in 1880 days ago, the information mentioned may be changed or developed.
    代码不好贴, 因为涉及到很多个文件

    简单就是:
    读取 A 类 文件, 根据偏移量提取出 B 类文件, 解析 B 类文件中的数据.

    A 类文件中有可能有多个 B 类文件.
    A 类文件几十兆, B 类文件几兆.
    B 类文件是不写入本地的, 直接解析.



    大概有接近 1000 个 A 类文件, 随着循环时间越来越长, 解析 B 类文件数据的这个函数执行会越来越慢.
    多数使用过的变量 都有手动用 del 删除


    每次循环 A 文件前 关闭 gc, A 文件使用后开启 gc 手动调用 gc.collect()

    随着循环次数变多, 解析 B 类文件的函数, 就会从最开始的几十毫秒到后来的几秒甚至时间更长.

    占用内存波动不大, 一直是 300M 左右
    Supplement 1    Apr 14, 2021

    用pycharm的profiler工具分析了一下, 时间用在GC和一个函数中.

     def obj_find_one(obj, key, value): """ 查询对象数组中key属性等于value的对象 :param obj: 对象数组 :param key: 对象属性名 :param value: 要查找的属性值 :return: """ for item in obj: if getattr(item, key) == value: return item 

    这个函数是 解析用 模块中的函数

    26 replies    2021-04-20 10:19:18 +08:00
    imn1
        1
    imn1  
       Apr 14, 2021
    那就加大内存使用量,A 全部读入内存后关闭
    Virace
        2
    Virace  
    OP
       Apr 14, 2021
    @imn1 还是内存的事么, 测试机内存倒是够用, 实际是要在一个 运行内存只有 1G 的机器上运行. = =
    F281M6Dh8DXpD1g2
        3
    F281M6Dh8DXpD1g2  
       Apr 14, 2021 via iPhone
    解析完了记下来不就完了
    abersheeran
        4
    abersheeran  
       Apr 14, 2021
    根据偏移量直接读文件某一部分这事可以先上 mmap 优化一下看看。另外你这个确定是慢在解析上吗?是不是内存超限了导致系统自动分配虚拟内存给你,疯狂交换虚拟内存页导致的。我以前遇到过类似问题。你可以先排查一下。
    westoy
        5
    westoy  
       Apr 14, 2021
    不要管程序吃多少内存

    跑的时候观察下吃 swap 没有

    你不停做文件读写, 等于不停触发 linux 的文件缓存机制,linux 也不是彻底没内存才会触发 swap

    swap 占用不停变化的话, 直接禁用或者调整内核的 vm.swapiness
    Virace
        6
    Virace  
    OP
       Apr 14, 2021
    @abersheeran 对只是慢在解析上, 简单的装饰器计算运行时间的. 测试是在 win 环境下出现的.
    clino
        7
    clino  
       Apr 14, 2021
    "随着循环次数变多, 解析 B 类文件的函数, 就会从最开始的几十毫秒到后来的几秒甚至时间更长."
    是解析本身的耗时越来越长吗?不太理解这是什么导致的。
    Virace
        8
    Virace  
    OP
       Apr 14, 2021
    @westoy 测试是在 win 环境下出现的. 也会有类似的情况嘛.
    abersheeran
        9
    abersheeran  
       Apr 14, 2021
    @Virace Windows 也有虚拟内存的。先排查这个情况再考虑其他的。任何语言都不会因为整个程序的内存占用变多而运算变慢的。出现这情况大概率是虚拟内存的锅。
    geelaw
        10
    geelaw  
       Apr 14, 2021 via iPhone
    为什么你要关掉 GC ?
    Virace
        11
    Virace  
    OP
       Apr 14, 2021
    @geelaw 经过测试在读入文件后 关闭 GC 执行后续操作 操作完毕在打开 GC 手动清理, 比平常要快. 意思就是如果不关闭的话, 这种越运行越慢的问题会更严重
    crclz
        12
    crclz  
       Apr 14, 2021
    建议楼主把代码贴出来,给大家一个最小的可重现的代码,既方便大家调试,也方便排除其他问题。
    还有就是楼主一些地方的表述不太清晰,可能会让项目成员以外的路人产生困惑。例如“随着循环时间越来越长, 解析 B 类文件数据的这个函数执行会越来越慢”
    crclz
        13
    crclz  
       Apr 14, 2021
    还有一个建议:用某种 profiler 看看到底哪些函数是罪魁祸首,方便定位问题
    Virace
        14
    Virace  
    OP
       Apr 14, 2021
    代码不好贴, 解析的意思, B 类文件是个独有个格式, 经过几个循环能完全读完. 将读完的数据保存到本地. 这是这个解析函数要做的. 确实用 pycharm 的 profiler 运行了一下, 显示 76%的时间都在这个解析函数上.
    keakon
        15
    keakon  
       Apr 14, 2021
    如果解析的文件是 json 的话,市面上所有的 json 库都会内存泄露
    Virace
        16
    Virace  
    OP
       Apr 14, 2021
    @keakon 解析倒不是, 解析完毕保存的数据是 json.
    clino
        17
    clino  
       Apr 14, 2021
    你说解析函数有误导性,看起来其实这个函数不光做了解析还干了很多其他的事情,这里面有很多细节和可能性。
    我的建议是仔细研究这个函数,看到底越来越慢是这个函数的哪一步导致的,如果能找到,那大概率能猜出是什么导致越来越慢。
    xiaoming1992
        18
    xiaoming1992  
       Apr 14, 2021
    笨办法,把那个解析函数按照二分法,移除掉一部分功能后再运行试试
    Virace
        19
    Virace  
    OP
       Apr 14, 2021
    @clino 用 profiler 工具找出了一个运行比较长的函数, 已经贴到附言上了
    wuwukai007
        20
    wuwukai007  
       Apr 14, 2021
    要不用 pysnooper 逐行分析一下?
    gBurnX
        21
    gBurnX  
       Apr 15, 2021
    watch -n 1 'free -h'
    htop -d 1
    dstat -t -n -d -c -g -i -l -m -p -s -y --ipc --lock --raw --tcp --udp --unix
    iostat -x -m -d 1

    注意一下函数执行速度,与 内存使用率 / 磁盘活动时间的关系。
    clino
        22
    clino  
       Apr 15, 2021
    从 obj_find_one 的实现来看,应该是这个遍历耗时很长,看能否调整数据结构,让这个查询不需要遍历,或者看能否做预处理形成一个中间数据结构让查询不需要遍历。

    gc.collect 的优化看看能不能不要每次都做,还有 gc.collect 的参数你看能不能给 0 试试 gc 效果如何。
    Virace
        23
    Virace  
    OP
       Apr 15, 2021
    @clino 去掉这个函数了, 改用字典了, 时间缩短不少. 但开始运行和运行一段时间后性能还是有差别. 目前从 profiler 工具给的信息看, 大部分时间除了几个循环就是 GC 了.
    clino
        24
    clino  
       Apr 16, 2021
    gc.collect 的参数调整没用吗?
    另外不做 gc 的后果是什么?内存暴涨?能否重用 dict 之类的对象来减少新对象的创建?还有就是检测一下内存用量,超过临界值了再执行 gc 。
    Virace
        25
    Virace  
    OP
       Apr 19, 2021
    @clino 同等情况下手动执行 gc 和自动 gc 占用内存是有区别的, 比如 100 个 A 类文件循环处理时不调用 GC 可能最高内存会超过 1G, 手动调用最高也只在 400M 左右. 但是不管手动调用还是自动, 这个 gc 在整个程序执行时间时间里是得占用个 30 左右. 好多情况得需要额外复制对象在进行处理, 因为原对象后续还需要使用.
    clino
        26
    clino  
       Apr 20, 2021
    或者你实在优化有问题,考虑把对象内的数据外包给 redis 处理,这样 python 这里只要做数据查询就可以了,不用面临这种 python 内部内存暴涨的情况
    About     Help     Advertise     Blog     API     FAQ     Solana     923 Online   Highest 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 56ms UTC 19:06 PVG 03:06 LAX 12:06 JFK 15:06
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86