9

コードは非常に単純です。すべてが関数内で行われるため、リークはありません。そして、何も返されません。ファイル (~20 MiB) 内のすべての行を調べて、それらすべてをリストに入れる関数があります。
言及された機能:

def read_art_file(filename, path_to_dir):
    import codecs
    corpus = []
    corpus_file = codecs.open(path_to_dir + filename, 'r', 'iso-8859-15')
    newline = corpus_file.readline().strip()
    while newline != '':
        # we put into @article a @newline of file and some other info
        # (i left those lists blank for readability)
        article = [newline, [], [], [], [], [], [], [], [], [], [], [], []]
        corpus.append(article)
        del newline
        del article
        newline = corpus_file.readline().strip()
    memory_usage('inside function')
    for article in corpus:
        for word in article:
            del word
        del article
    del corpus
    corpus_file.close()
    memory_usage('inside: after corp deleted')
    return

メインコードは次のとおりです。

memory_usage('START')
path_to_dir = '/home/soshial/internship/training_data/parser_output/'
read_art_file('accounting.n.txt.wpr.art', path_to_dir)
memory_usage('outside func')
time.sleep(5)
memory_usage('END')

すべてmemory_usageは、スクリプトによって割り当てられた KiB の量を出力するだけです。

スクリプトの実行

スクリプトを実行すると、次のようになります。

START メモリ: 6088 KiB
内部メモリ: 393752 KiB (20 MiB ファイル + リストは 400 MiB を占めます)
内部: corp 削除後メモリ: 43360 KiB
外部 func メモリ: 34300 KiB (34300-6088 = 28 MiB リーク)
FINISH メモリ: 34300 KiB

リストなしで実行する

そして、私がまったくarticle同じことをするが、corpusコメントアウトされたものに追加すると:

article = [newline, [], [], [], [], [], ...]  # we still assign data to `article`
# corpus.append(article)  # we don't have this string during second execution

この方法で出力が得られます:

START メモリ: 6076 KiB
内部メモリ: 6076 KiB
内部: corp 削除後メモリ: 6076 KiB
外部 func メモリ: 6076 KiB
FINISH メモリ: 6076 KiB

質問:

したがって、このようにしてすべてのメモリが解放されます。何百ものそのようなファイルを処理するので、すべてのメモリを解放する必要があります。
私が何か間違ったことをしているのですか、それとも CPython インタープリターのバグですか?

UPD。これは、メモリ消費を確認する方法です(他のスタックオーバーフローの質問から取得):

def memory_usage(text = ''):
    """Memory usage of the current process in kilobytes."""
    status = None
    result = {'peak': 0, 'rss': 0}
    try:
        # This will only work on systems with a /proc file system
        # (like Linux).
        status = open('/proc/self/status')
        for line in status:
            parts = line.split()
            key = parts[0][2:-1].lower()
            if key in result:
                result[key] = int(parts[1])
    finally:
        if status is not None:
            status.close()
    print('>', text, 'memory:', result['rss'], 'KiB  ')
    return
4

2 に答える 2

1

このループ

for article in corpus:
    for word in article:
        del word
    del article

メモリを解放しません。del wordname によって参照されるオブジェクトの参照カウントを単純にデクリメントしますword。ただし、ループ変数が設定されている場合、ループは各オブジェクトの参照カウントを 1 ずつ増やしますつまり、このループによるオブジェクトの参照カウントの正味の変化はありません。

への呼び出しをコメントアウトすると、corpus.appendある反復から次の反復までファイルから読み取られたオブジェクトへの参照が保持されないため、インタプリタは以前にメモリの割り当てを自由に解除できます。これは、観察したメモリの減少を説明します。

于 2013-05-07T16:16:26.070 に答える