关于读写文件执行速度

Virace 24天前 22

代码不好贴, 因为涉及到很多个文件

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

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



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


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

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

占用内存波动不大, 一直是 300M 左右
最新回复 (24)
  • imn1 19天前
    引用 2
    那就加大内存使用量,A 全部读入内存后关闭
  • 楼主 Virace 19天前
    引用 3
    @imn1 还是内存的事么, 测试机内存倒是够用, 实际是要在一个 运行内存只有 1G 的机器上运行. = =
  • liprais 19天前
    引用 4
    解析完了记下来不就完了
  • abersheeran 19天前
    引用 5
    根据偏移量直接读文件某一部分这事可以先上 mmap 优化一下看看。另外你这个确定是慢在解析上吗?是不是内存超限了导致系统自动分配虚拟内存给你,疯狂交换虚拟内存页导致的。我以前遇到过类似问题。你可以先排查一下。
  • westoy 19天前
    引用 6
    不要管程序吃多少内存

    跑的时候观察下吃 swap 没有

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

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

    gc.collect 的优化看看能不能不要每次都做,还有 gc.collect 的参数你看能不能给 0 试试 gc 效果如何。
  • 楼主 Virace 19天前
    引用 24
    @clino 去掉这个函数了, 改用字典了, 时间缩短不少. 但开始运行和运行一段时间后性能还是有差别. 目前从 profiler 工具给的信息看, 大部分时间除了几个循环就是 GC 了.
  • clino 19天前
    引用 25
    gc.collect 的参数调整没用吗?
    另外不做 gc 的后果是什么?内存暴涨?能否重用 dict 之类的对象来减少新对象的创建?还有就是检测一下内存用量,超过临界值了再执行 gc 。
  • 游客
    26
返回