Bash에서 많은 파일 내용을 읽을 때 HDD 탐색 시간 단축

Bash에서 많은 파일 내용을 읽을 때 HDD 탐색 시간 단축

/XX/XX/XX/각 파일의 내용을 처리하기 위해 하위 디렉터리에 있는 수백만 개의 파일을 읽었습니다 . PHP에서는 다음과 같이 파일을 읽었습니다.

foreach(glob("/folder/*") as $a){
  foreach(glob("$a/*") as $b){
    foreach(glob("$b/*") as $c){
      foreach(glob("$c/*") as $file){
      // Processing
      }
    }
  }
}

문제는 이 코드가 특정 순서로 파일을 가져오지만 가능한 순서대로(최소 검색 시간으로) 모든 파일을 읽어야 한다는 것입니다.

탐색 시간을 줄이기 위해 HDD 섹터에 저장된 파일을 읽는 방법이 있습니까?

PHP 코드는 내가 어떻게 여기까지 왔는지 보여주기 위한 것이며 PHP에서 해결책을 찾을 것으로 기대하지는 않습니다. 내 질문은 실제로 shell.

고쳐 쓰다:

나는 문제를 명확하게 설명하지 않았습니다. 이미 전체 파일 목록이 있습니다. 문제는 그것을 찾는 것이 아니라 탐색 시간을 줄이기 위해 내용을 읽는 가장 좋은 순서입니다.

glob대신 사용해 봤습니다

foreach($files as $file){
  $content=file_get_contents($file);
}

각 파일에 대한 검색 시간을 줄이고 싶습니다.

앞서 말했듯이 언어는 중요하지 않습니다. bash나 C로 전체 코드를 다시 작성할 수 있습니다.

내 질문을 다시 표현하겠습니다.중첩된 폴더(HDD, ext4 포함)에 저장된 수백만 개의 파일 내용을 가장 빠르게 읽는 방법은 무엇입니까?

답변1

여기서 "HDD 섹터"는 중요하지 않습니다. 폴더 내용이 저장되고 액세스되는 방식은 저장 장치의 블록 구조와 거의 관련이 없습니다(그러나 파일 시스템에 따라 다름).

귀하의 PHP 코드는 매우 비효율적입니다. (저는 PHP를 비난합니다. PHP의 표준 라이브러리로 인해 효율적인 코드를 작성하기가 매우 어렵습니다.) 또한 올바르지 않습니다. 폴더의 4개 수준보다 더 깊은 것이 있는 경우(실제로 무언가를 작성해야 합니다)재귀디렉토리를 통해서는 그렇게 할 수 없습니다).

어쨌든 bash간단합니다.

shopt -s globstar
for file in **/** ; do
  echo "${file} found!"
done

그러나 이는 PHP에서 파일 목록이 필요한 경우에는 실제로 도움이 되지 않습니다. 디렉토리를 탐색하는 데 와일드카드가 필요하지 않습니다. 사실 이는 분명히 잘못된 도구입니다. PHP의 메소드를 사용하여 디렉토리를 나열하고 디렉토리가 발견될 때마다 방금 찾은 디렉토리에서 동일한 메소드를 호출하십시오.

답변2

나는 추천한다find

find /folder/ -mindepth 3 -maxdepth 3 -type f

그리고 사용 여부는 처리 방법에 따라 -exec다릅니다 .-execdir-print0 | xargs -0

findAFAIK는 파일을 검색하는 가장 빠른 방법 중 하나입니다.

답변3

1967년부터 컴퓨터 프로그래머로서 나는 작고 느린 컴퓨터에 연결된 작고 느린 기계적으로 배치된 디스크에서 파일을 정렬하는 것이 문제였던 것을 기억합니다. 진보는 이러한 우려를 없애줍니다. 더 빠르고 더 큰 컴퓨터, 더 빠르고 더 큰 소프트웨어(RAM의 버퍼링으로 디스크가 RAM 속도에 가까워짐), 더 빠르고 더 크고 더 스마트한 디스크 및 디스크와 유사한 개체, 디스크 드라이버의 추가 개발...파일의 실제 위치에 관심을 갖는 사람은 거의 없습니다. 디스크에(C/H/S 의미에서). "최신" 디스크 드라이버는 검색 시간을 최소화하기 위해 요청 순서를 변경했으며 수십 년 동안 이를 수행해 왔습니다.

파일 이름 목록을 생성하는 것은 까다롭습니다. 처음에는 수백만 개의 이름이 모두 필요하지 않습니다.

find(읽기- 반복-읽기)를 사용 man find하거나 자신만의 디렉터리 탐색 코드를 굴립니다.

"디렉토리"는 d------권한에 비트가 설정된 파일입니다.
여기에는 파일이나 디렉터리에 대한 포인터가 포함되어 있습니다.

readdir합리적인 프로그래밍 언어를 사용하면 인터페이스( ) 에 액세스할 수 있습니다 man readdir.

답변4

내 질문을 다시 표현하겠습니다. 중첩된 폴더(ext4가 포함된 HDD)에 저장된 수백만 개의 파일 내용을 읽는 가장 빠른 방법은 무엇입니까?

파일 시스템이 제공하는 것보다 더 나은 순서는 없습니다.

특정 순서로 정렬된 파일(하드 드라이브 섹터에 저장됨)

파일이 디스크에서 어떻게든 "정렬"되어 있고 경로에 따라 다르다고 가정합니다.그러나 실제로는 그렇지 않습니다.

파일 시스템, 특히 ext2/3/4에는 파일 설명이 포함된 디스크 레이아웃이 있으며(여기서 디렉토리는 실제로 다른 파일 목록을 가리키는 일부 특수 파일일 뿐입니다) 이러한 설명에는 파일 이름과 데이터를 저장하는 블록/블록이 포함됩니다. 파일 범위 목록(파일이 메타데이터를 저장할 만큼 짧지 않은 경우)

이제 이러한 파일은 일반적으로아니요해당 경로가 어떤 방식으로든 관련되어 있으면 디스크에서 연속된 것입니다. 이런 일은 일어나지 않습니다. 가능한 경우 새 파일 데이터를 위한 여유 공간이 선택됩니다. 게다가 단일 파일 자체는 연속적이라는 보장이 없습니다! 데이터가 저장되는 블록이 차례로 있을 필요는 없습니다.

그러니까 당신은 정말로할 수 없다사용자 관점에서 더 빠르게 만들기: 파일 시스템을 사용하는 목적은 파일을 사용하는 프로그램에서 파일이 모두 저장 매체의 블록이라는 사실을 숨기는 것입니다.

당신이 할 수 있는 최선은아니요파일을 재정렬합니다. 시스템 호출과 상호작용할 때 파일 시스템에서 파일을 가져오는 순서가 readdir다를 가능성이 있습니다(프로그래밍 언어가 무엇이든 상관없이 파일 시스템에 파일 목록을 요청하는 방법이 있습니다). 공간이 할당되는 순서에서 순서는 블록과 inode 매핑의 순서일 수 있으며 디스크의 순서와 어느 정도 일치할 수 있습니다.

더 중요한 것은 단일 스레드(SSD에 액세스할 수 있는 경우에는 이 작업을 수행하지 마십시오)와 파일 시스템에서 HDD에 대해 탐색 시간 집약적인 일부 작업을 수행하려고 한다는 사실로 인해 근본적으로 제한이 있다는 것입니다. 이 클래스는 최적화된 액세스를 제공합니다.아니요이를 위해 좋은 클래식 파일 시스템을 찾으십시오. 이는 클래식 파일 시스템이 잘해야 하는 것이 아니기 때문입니다.

따라서 구조적으로 접근 방식을 개선할 수 있습니다(내가 말하는 PHP 코드가 비효율적이라는 것은 바로 이것이다는 의미입니다).

  1. 나중에가 아니라 파일이 발견되면 파일 내용을 읽습니다. 메타데이터는 파일 데이터와 마찬가지로 디스크에 배포되므로 디렉터리의 파일 목록을 읽기 위해 다른 위치로 점프하는 데는 파일 내용을 읽는 것과 동일한 탐색 시간이 있습니다. 따라서 "파일 목록을 가져온 다음 각 파일을 읽는" 대신 다음을 수행하십시오.

    1. 디렉토리의 첫 번째 항목 가져오기
    2. 파일인 경우 읽기를 시작합니다
      (즉,
      • openING
      • 대기열에 파일 설명자를 추가합니다.
      • 대기열을 읽는 별도의 스레드에서
      • 거기에서 현재 처리 중인 파일 수를 추적하고
      • 합리적인 임계값보다 낮으면 대기열의 끝을 팝하고,
      • fadvise전체 파일을 읽고 싶은데,
      • 이벤트에 파일 설명자를 추가 epoll하고
      • 별도의 위협에서는 epoll_wait.

    디스크를 유휴 상태로 두지 마십시오. 커널이 버퍼를 완전히 활용할 수 있는 기회를 제공하므로 디스크에서 동일한 위치를 두 번 찾을 필요가 없습니다.

    디렉터리인 경우 해당 디렉터리의 1로 이동합니다.

    1. 다음 디렉터리로 이동합니다.
  2. 파일 시스템 버퍼가 충분히 큰지 확인하십시오. 모든 파일 시스템 메타데이터를 캐시할 수 있기를 원합니다. 최신 Linux 시스템에서는 충분한 RAM을 제공하는 것 외에는 많은 작업을 수행할 필요가 없습니다.

  3. 전염병과 같은 PHP와 같은 언어를 피하십시오(시스템 호출로 인해 완전히 다른 곳을 보게 될 수 있으며 이것이 첫 번째 성능 문제일 때 아래에서 어떤 시스템 호출이 실행되는지 알기 어렵게 만듭니다) (또한 전염병을 피하십시오) PHP와 같은 언어에서는) 코드 조각이 너무 아름답게 설명되어 있듯이 잘못된 언어 디자인의 전형입니다! )

  4. 이 작업을 여러 번 수행해야 하는 경우 cp -ar데이터를 새 파일 시스템으로 이동하는 것을 잠시 고려해 보십시오(아마도외부 4, 그러나 FS Mark 및 기타 포괄적인 "많은 파일 처리" 문제에는 잘 작동합니다. 이렇게 하면 디렉토리 항목이 생성(복사) 순서로 지정되고 파일 이름의 순서에 따라 실제로 뭔가가 있을 가능성이 더 높아집니다. 디스크 저장소를 사용합니다. 그래도 보장은 없습니다!
    읽기 전용인 경우 특정 순서를 보장하는 몇 가지 방법이 있습니다. 읽기 전용 파일 시스템에 넣습니다(저는 압축하는 squashfs를 좋아합니다.진짜생각보다 중요합니다.) 해당 파일 시스템을 다른 파일 시스템이 아닌 디스크에 저장하십시오!

  5. 정말로 파일 액세스가 필요한지 고려하십시오. 파일 시스템이 정말로 귀하가 가지고 있는 정보를 저장하는 올바른 방법입니까? 아니면 관계형 데이터베이스(sqlite? Postgresql?)이거나 문서 지향 데이터베이스일까요?

관련 정보