이름으로 파일을 삭제하는 것이 고통스러울 정도로 느리지만 엄청나게 빠른 이유는 무엇입니까?

이름으로 파일을 삭제하는 것이 고통스러울 정도로 느리지만 엄청나게 빠른 이유는 무엇입니까?

무례함: 아래에서 언급하는 "빠른" 방법은 느린 방법보다 60배 빠르지는 않습니다. 30배 더 빨라졌습니다. 나는 이 실수를 그 시간에 비난할 것이다. (오전 3시는 내가 명확하게 생각하기에 가장 좋은 시간이 아니다 :)..

업데이트: 테스트 시간 요약을 추가했습니다(아래).
속도 요소에는 두 가지 문제가 관련된 것으로 보입니다.

  • 사용된 명령 선택(아래 타이밍 비교 참조)
  • 디렉토리에 많은 수의 파일이 있다는 특성은..."큰 것은 나쁜 것"처럼 보입니다. 숫자가 증가하면 상황이 불균형적으로 느려집니다.

모든 테스트는 1백만 개의 파일을 사용하여 수행되었습니다.
(실시간, 사용자 시간 및 시스템 시간은 테스트 스크립트에 있습니다.)
테스트 스크립트는 다음에서 찾을 수 있습니다.Paste.ubuntu.com

#
# 1 million files           
# ===============
#
#  |time   |new dir   |Files added in  ASCENDING order  
#  +----   +-------   +------------------------------------------------- 
#   real    01m 33s    Add files only (ASCENDING order) ...just for ref.
#   real    02m 04s    Add files, and make 'rm' source (ASCENDING order) 
#                      Add files, and make 'rm' source (DESCENDING order) 
#   real    00m 01s    Count of filenames
#   real    00m 01s    List of filenames, one per line
#   ----    -------    ------
#   real    01m 34s    'rm -rf dir'
#   real    01m 33s    'rm filename' via rm1000filesPerCall   (1000 files per 'rm' call)
#   real    01m 40s    'rm filename' via  ASCENDING algorithm (1000 files per 'rm' call)
#   real    01m 46s    'rm filename' via DESCENDING algorithm (1000 files per 'rm' call)
#   real    21m 14s    'rm -r dir'
#   real    21m 27s    'find  dir -name "hello*" -print0 | xargs -0 -n 1000 rm'
#   real    21m 56s    'find  dir -name "hello*" -delete'
#   real    23m 09s    'find  dir -name "hello*" -print0 | xargs -0 -P 0 rm'
#   real    39m 44s    'rm filename' (one file per rm call) ASCENDING
#   real    47m 26s    'rm filename' (one file per rm call) UNSORTED
#                                                       

최근에 만들고 삭제했습니다.1010,000개의 빈 테스트 파일. 이름(예 rm filename: ) 으로 파일을 삭제하려면거대한두 가지 방법의 시간 차이...

두 방법 모두 완전히 동일한 rm filename명령을 사용합니다.

업데이트: 이 명령은 정확히 동일하지 않은 것으로 나타났습니다... 그 중 하나는 "rm"으로 한 번에 1000개의 파일 이름을 보내고 있습니다... 쉘 버팀대 확장 문제입니다. 각 파일 이름이 피더 파일에 기록되는 것 같습니다. 한 줄이 있지만 실제로는 한 줄에 1000개가 있습니다.

파일 이름은 while read"피드 파일"을 통해 루프에 제공됩니다.
피드 파일은 이러한 메소드의 출력이며 ls -1 -f
다음 한 가지를 제외하고 모든 측면에서 동일합니다.

  • 이것느린정렬되지 않은 피더 파일을 직접 사용하는 방법ls -1 -f
  • 이것빠르게메서드는 정렬되지 않은 동일한 파일의 정렬된 버전을 사용합니다.

여기서는 정렬이 문제인지, 아니면 정렬된 피드 파일이 파일이 생성된 순서와 일치하는지 잘 모르겠습니다(간단한 오름차순 정수 알고리즘을 사용했습니다).

1백만 개의 파일에 대해,빠르게 rm filename방법은60비교하다느린방법... 다시 말하지만, 이것이 "정렬" 문제인지 아니면 배후의 해시 테이블 문제인지는 모르겠습니다... 단순한 정렬 문제가 아닌 것 같습니다. 왜 의도적으로 ls -1 -f나에게정렬 해제새로 추가된 "정렬된" 파일 이름 시퀀스 목록...

다음 천만 개의 파일을 삭제하는 데 며칠(예 며칠)이 걸리지 않도록 여기에서 무슨 일이 일어나고 있는지 알고 싶습니다. :) ....많은 대안을 시도했기 때문에 "일"이라고 말합니다. 관련된 파일 수에 따라 관련 항목이 불균형적으로 증가합니다. 그래서 테스트만 했습니다.1수천 개의 세부정보

참고: 이름의 "정렬된 목록"으로 파일을 삭제하는 것은 실제로 rm -rf"정렬된 목록" 방법보다 2배 빠릅니다.
AND: rm -r"정렬된 목록" 접근 방식보다 30배 느림

...하지만 여기서 질문이 "정렬"되어 있나요? 아니면 ext4에서 사용하는 해싱(또는 기타) 저장 방법과 더 관련이 있습니까?

나를 혼란스럽게 하는 것은 각 호출이 rm filename이전 호출과 아무런 관련이 없다는 것입니다. (적어도 "bash" 관점에서는)

저는 Ubuntu/bash/'ext4'/SATA II 드라이브를 사용하고 있습니다.

답변1

rm -r은 재귀로 인해 속도가 느려질 것으로 예상됩니다. 디렉터리 구조의 깊이 우선 탐색이 수행되어야 합니다.

그렇다면 천만 개의 파일을 어떻게 생성합니까? 어떤 순서로 반복되는 스크립트를 사용하고 있습니까? 1.txt,2.txt,3.txt... 그렇다면 이러한 파일은 동일한 순서로 HDD의 연속 블록에 할당될 수도 있습니다. 따라서 동일한 순서로 삭제하는 것이 더 빠릅니다.

"ls -f"는 -aU를 활성화합니다. 이는 다시 재귀적인 디렉터리 순서로 나열됩니다.

답변2

파일 구조를 최적화해야 합니다. 그래서 대신

for i in $(seq 1 1000); do touch file.$i; done

다음과 같이 더 스마트하게 수행하십시오(bash 가정).

function bucklocate() 
{ 
    hash=$(echo -n "$1"|md5sum|cut -f1); 
    echo -n "${hash:1:1}/${hash:7:1}/${hash:9:2}/$1"; 
}

hexdig="{0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f}"
eval mkdir -p $hexdig/$hexdig/$hexdig$hexdig


for i in $(seq 1 1000); do touch $(bucklocate file.$i); done

이제 이 예제는 md5sum[1]을 사용하기 때문에 상당히 느립니다. 다음과 같은 것을 사용하면 특정 파일 이름이 필요하지 않고 중복에 대해 걱정할 필요가 없는 한 응답성이 더 좋아질 것입니다. 반복 가능하려면 특정 이름이 필요합니까? 하 희망합니다 :)

mkdir -pv {0,1,2,3,4,5,6}/{0,1,2,3,4,5,6,7,8,9,10,12}
for  a in $(seq 1 100); do i=$RANDOM; echo touch "$(($i%7))/$(($i%13))/file.$i"; done

물론 이것은 모두 해시 테이블 개념을 성급하게 차용한 것입니다.

관련 정보