diff는 많은 메모리와 CPU를 소비합니다.

diff는 많은 메모리와 CPU를 소비합니다.

파일이 2개 있는데,모두.txt(525,953,272개 레코드) 및하위 집합.txt(525,298,281개의 레코드). 각 레코드는 17비트 ASCII 정수에 지나지 않습니다. 두 파일이 모두 정렬되었으며 각 파일의 중복 기록이 제거되었습니다. 모든 값하위 집합.txt에도 존재합니다모두.txt. 다음 기록을 찾고 싶습니다.모두.txt거기에없는 사람들하위 집합.txt.

나는 diff이 두 파일 사이에서 줄을 쓸 것이라고 생각하고 실행 하려고 합니다.모두.txt하지만 거기엔 없어하위 집합.txt. 이 기기에는 64GB의 메모리가 있습니다. 30분 동안 실행 되었으며 diff메모리의 약 75%를 얻었습니다.

무슨 일이 일어나고 있는지 추측할 수 있는 사람이 있나요? diff도움이 될 만한 주장이 있나요? 내가 diff하고 싶은 건 이게 아닌데 ? 다른 접근 방식을 사용해야 합니까?

답변1

무슨 일이 일어나고 있는지, 그리고 diff에 도움이 될 만한 주장이 있는지 추측할 수 있는 사람이 있나요? 이게 diff의 원래 의도 아닌가요? 다른 접근 방식을 사용해야 합니까?

이것은 의도한 바가 아닙니다 diff. 입력이 정렬될 때(보시다시피) 해당 작업을 위한 도구는 입니다 comm.

$ seq 10 15 > subset.txt
$ seq 10 20 > all.txt
$ comm -13 subset.txt all.txt
16
17
18
19
20

이것옵션comm회전하기 때문에 조금 특이합니다.떠나다산출. 열 1에는 파일 1에 고유한 행이 포함되고, 열 2에는 파일 2에 고유한 행이 포함되며, 열 3에는 두 파일 모두에 "공통"되는 행이 포함됩니다. 옵션을 사용하여 -13"all.txt"에 있는 줄만 표시하도록 통신에 요청합니다.

답변2

diff아마도 가장 적합한 도구는 아닐 것입니다. 나는 당신이 원하는 것을 정확하게 수행하는 간단한 스크립트를 작성해 볼 것입니다.

모든 것은 기억 속에 있다

이것은 매우 간단하고 다양한 솔루션입니다. 두 개의 파일을 최소 메모리 구조에 로드하고 subset.txt레코드에서 레코드를 빼고 all.txt나머지를 씁니다.

#!/usr/bin/env python

with open('diff.txt', 'w') as diff:

    for record in set(open('all.txt', 'r')) - set(open('subset.txt', 'r')):
        diff.write(record)

유사한 파일에 저장 create_diff.py하고 chmod +x create_diff.py두 파일이 모두 있는 디렉터리에서 실행합니다.

메모리의 고유한 하위 집합

메모리 공간을 줄이기 위해 추가 최적화가 필요한 경우 전체 파일을 메모리에 로드하지 않고 이를 달성할 수도 있습니다. 특히 all.txt파일을 메모리에 완전히 로드하지 않고 한 번만 반복하면 됩니다.

#!/usr/bin/env python

subset_txt = open('subset.txt', 'r')
subset = subset_txt.readlines()
subset_txt.close()

with open('diff.txt', 'w') as diff_txt:
    with open('all.txt', 'r') as all_txt:
        for line in all_txt:
            if line not in subset:
                diff_txt.write(line)

입력/출력 기준

이는 I/O에 크게 의존하기 때문에 가장 느린 변형이어야 하지만 전체 파일을 메모리에 로드할 필요가 없기 때문에 메모리 공간이 더 적습니다. 파일이 정렬/고유한지 여부에 관계없이 작동합니다.

#!/usr/bin/env python

diff_txt = open('diff.txt', 'w')

with open('all.txt', 'r') as all_txt:
    with open('subset.txt', 'r') as subset_txt:
        for all_line in all_txt:
            found = False

            for sub_line in subset_txt:
                if all_line == sub_line:
                    found = True
                    break

            if found is False:
                diff_txt.write(all_line)
                subset_txt.seek(0)

diff_txt.close()

중복되지 않은 정렬된 파일에서만 작동합니다.<- 상황에 따라 추천

두 파일이 모두 정렬되어 있고 중복 항목이 없다고 확신하는 경우 이것이 최선의 솔루션입니다. 두 파일 모두 한 번만 읽혀지며 메모리에 완전히 로드될 필요가 없습니다.

#!/usr/bin/env python

diff_txt = open('diff.txt', 'w')

with open('all.txt', 'r') as all_txt:
    with open('subset.txt', 'r') as subset_txt:
        subset_line = subset_txt.readline()

        for all_line in all_txt:
            if all_line == subset_line:
                subset_line = subset_txt.readline()
            else:
                diff_txt.write(all_line)

diff_txt.close()

관련 정보