代码之家  ›  专栏  ›  技术社区  ›  SilentGhost

大型数据结构操作/处理中的内存使用

  •  4
  • SilentGhost  · 技术社区  · 17 年前

    我有许多大的(~100MB)文件,我正在定期处理这些文件。当我试图在处理过程中删除不需要的数据结构时,内存消耗有点太高。我想知道是否有一种方法可以有效地处理大型数据,例如:

    def read(self, filename):
        fc = read_100_mb_file(filename)
        self.process(fc)
    def process(self, content):
        # do some processing of file content
    

    是否存在数据结构重复?使用像self.fc这样的类范围属性不是更节省内存吗?

    我应该什么时候使用垃圾收集?我知道gc模块,但我在完成后调用它吗 del fc 例如

    使现代化

    6 回复  |  直到 12 年前
        1
  •  7
  •   Ryan Ginstrom    17 年前

    我建议你看看 presentation by David Beazley 在Python中使用生成器。这项技术允许您处理大量数据,并进行复杂的处理,快速且不会占用内存。在我看来,诀窍不是尽可能有效地在内存中保存大量数据;诀窍是避免同时将大量数据加载到内存中。

        2
  •  3
  •   Crashworks    17 年前

    在您开始对垃圾收集器大惊小怪之前,通过使用内存映射文件对象,您可能可以避免将整个文件加载到内存中的100mb开销。见 mmap

        3
  •  3
  •   Sam Corder    17 年前

    不要一次读取整个100兆欧的文件。使用流一次处理一点点。查看这篇关于处理大型csv和xml文件的博客文章。 http://lethain.com/entry/2009/jan/22/handling-very-large-csv-and-xml-files-in-python/

    下面是本文中的代码示例。

    from __future__ import with_statement # for python 2.5
    
    with open('data.in','r') as fin:
        with open('data.out','w') as fout:
            for line in fin:
                fout.write(','.join(line.split(' ')))
    
        4
  •  2
  •   Torsten Marek    17 年前

    因此,根据您的评论,我假设您的文件如下所示:

    item1,item2,item3,item4,item5,item6,item7,...,itemn
    

    通过反复应用一些组合函数,你们都可以将其简化为一个值。作为解决方案,一次只能读取一个值:

    def read_values(f):
        buf = []
        while True:
            c = f.read(1)
            if c == ",":
                yield parse("".join(buf))
                buf = []
            elif c == "":
                yield parse("".join(buf))
                return
            else:
                buf.append(c)
    
    with open("some_file", "r") as f:
         agg = initial
         for v in read_values(f):
             agg = combine(agg, v)
    

    这样,内存消耗保持不变,除非 agg 时间在增长。

    1. 提供适当的 initial , parse combine
    2. 这基本上是内置的 reduce 减少 :

      with open("some_file", "r") as f:
          agg = reduce(combine, read_values(f), initial)
      

    我希望我正确地解释了你的问题。

        5
  •  1
  •   user26294    17 年前

    首先,不要碰垃圾收集器。这不是问题,也不是解决办法。

    冷凝使用 删除处理过程中不再需要的结构。此外,您可以考虑使用 元帅 在处理下一个100mb的输入文件时,将一些已处理的数据转储到磁盘。

    对于文件读取,基本上有两种选择:unix样式的文件作为流,或内存映射文件。对于基于流的文件,默认的python文件对象已经被缓冲,因此最简单的代码可能也是最有效的:

      with open("filename", "r") as f:
        for line in f:
           # do something with a line of the files
    

    或者,您可以使用f.read([size])来读取文件块。但是,通常这样做是为了提高CPU性能,方法是对脚本的处理部分进行多线程处理,以便可以同时读取和处理。但这对内存使用没有帮助;事实上,它使用了更多的内存。

    另一个选项是mmap,如下所示:

      with open("filename", "r+") as f:
        map = mmap.mmap(f.fileno(), 0)
        line = map.readline()
        while line != '':
           # process a line
           line = map.readline()
    

    这有时优于流,但也不会提高内存使用率。

        6
  •  1
  •   nosklo    17 年前

    fc 足球俱乐部 大约,当 read 方法结束。

    你在某处留了一份推荐信 read_100_mb_file ,也许在 process . 如果没有引用,CPython实现将几乎立即取消分配它。

    有一些工具可以帮助您找到此参考的位置, guppy , dowser , pysizer ...

    推荐文章