“ls *”가“ls”보다 훨씬 오래 걸리는 이유는 무엇입니까? /dev/null real

디렉토리에 몇 개의 파일이 있습니다.

$ ls | wc -l
9376

사용하여 이러한 엄청난 시간 차이가 왜 아무도 설명 할 수 ls *및이 ls?

$ time ls > /dev/null
real    0m0.118s
user    0m0.106s
sys     0m0.011s

$ time ls * > /dev/null
real    1m32.602s
user    0m0.233s
sys     0m0.438s

이 디렉토리는 GPFS (General Parallel File System)에 있기 때문에 이는 대단한 예일 수 있습니다. 그러나 로컬 파일 시스템이 크게 느려지는 것을 볼 수 있습니다.

편집하다:

$ time ls -l > /dev/null
real    0m58.772s
user    0m0.113s
sys     0m0.452s
$ time ls -l * > /dev/null
real    1m19.538s
user    0m0.252s
sys     0m0.461s

내 예제에는 하위 디렉토리가 없다는 것을 추가해야합니다.

$ diff <(ls) <(ls *)
$


답변

ls인수없이 실행 하면 디렉토리가 열리고 모든 내용을 읽고 정렬 한 후 인쇄합니다.

당신이 실행할 때 ls *, 쉘은 먼저 확장된다 *. 이것은 간단 ls했던 것과 똑같 으며, 현재 디렉토리에있는 모든 파일을 가진 인자 벡터를 만들고 호출한다 ls. ls그런 다음 해당 인수 벡터와 각 인수에 대해 처리 access(2)하고 파일의 ¹를 호출 하여 존재 여부를 확인해야합니다. 그런 다음 첫 번째 (간단한) 출력과 동일한 출력을 인쇄합니다 ls. 쉘이 큰 인수 벡터를 처리 ls하는 데에는 작은 블록의 많은 메모리 할당이 필요할 수 있으며 시간이 오래 걸릴 수 있습니다. 작은 거기 때문에, sys그리고 user시간,하지만 많은 real시간을, 대부분의 시간은 디스크를 기다리는 것이 아니라 메모리 할당을하는 CPU를 사용하여 소요되었을 것입니다.

각 호출 access(2)은 권한 정보를 얻기 위해 파일의 inode를 읽어야합니다. 즉, 단순히 디렉토리를 읽는 것보다 훨씬 더 많은 디스크를 읽고 찾습니다. GPFS에서 이러한 작업이 얼마나 비싸는지 모르겠지만 ls -l와일드 카드 사례와 비슷한 런타임을 가진 비교를 통해 inode 정보를 검색하는 데 필요한 시간이 지배적 인 것으로 보입니다. GPFS가 각 읽기 작업에서 로컬 파일 시스템보다 약간 높은 대기 시간을 갖는 경우 이러한 경우 더 두드러 질 것으로 예상됩니다.

와일드 카드 케이스와 ls -l50 % 의 차이 는 디스크의 inode 순서로 설명 할 수 있습니다. inode가 디렉토리의 파일 이름과 동일한 순서로 순차적으로 배치되고 ls -l정렬하기 전에 stat (2)가 파일을 디렉토리 순서대로 디렉토리에 배치 한 경우 ls -l대부분의 inode를 스윕으로 읽을 수 있습니다. 와일드 카드를 사용하면 셸은 파일 이름을로 전달하기 전에 파일 이름을 정렬 ls하므로 ls다른 순서로 inode를 읽어 디스크 헤드 이동을 추가 할 수 있습니다.

당신의 주목해야한다 time출력이 와일드 카드를 확장하기 위해 쉘에 의해 걸리는 시간은 포함되지 않습니다.

실제로 무슨 일이 일어나고 있는지 보려면 strace(1)다음을 사용하십시오 .

strace -o /tmp/ls-star.trace ls *
strace -o /tmp/ls-l-star.trace ls -l *

각 시스템에서 어떤 시스템 호출이 수행되고 있는지 살펴보십시오.

¹ access(2)실제로 사용 되는지 또는 다른 것과 같은지 모르겠습니다 stat(2). 그러나 둘 다 아마도 inode 조회가 필요할 것입니다 (inode 조회를 access(file, 0)우회 할지 확실하지 않습니다 .)