시간 generateUserData.sh 테스트 {0..1000}

시간 generateUserData.sh 테스트 {0..1000}

일부 실험을 위해 대용량 파일을 생성하고 싶습니다.

이것은 내 스크립트입니다. 파일을 생성한 다음 변수로 읽은 다음 루프에서 정의된 횟수만큼 파일에 쓰려고 시도합니다.

#! /usr/bin/env bash

set -e
set -u

< /dev/urandom tr -dc "\t\n [:alnum:]" | head -c32768 > temp.txt
data=$(cat ./temp.txt)

for testdir in "$@"; do
    echo "create directory '$testdir'"
    mkdir -p $testdir
    for i in {1..3}; do
        counter=$(printf %02d $i)
        testfile=$testdir/test_${testdir##*/}_$counter.txt
        echo "create file '$testfile'"
        echo "$data" > $testfile
    done
done

이 스크립트를 사용하여 3000개의 파일(각 폴더에는 3개의 파일이 있음)을 생성하려고 하면 시스템에서 약 19초가 걸립니다.

시간 generateUserData.sh 테스트 {0..1000}

create directory 'TEST999'
create file 'TEST999/test_TEST999_01.txt'
create file 'TEST999/test_TEST999_02.txt'
create file 'TEST999/test_TEST999_03.txt'
create directory 'TEST1000'
create file 'TEST1000/test_TEST1000_01.txt'
create file 'TEST1000/test_TEST1000_02.txt'
create file 'TEST1000/test_TEST1000_03.txt'

real    0m19.333s
user    0m14.791s
sys     0m4.784s

echo나는 이것이 느린 부분일지도 모른다는 것을 안다 . 가능한 한 빨리 그를 끝내는 방법에 대한 아이디어가 있습니까?

답변1

느린 프로세스는 프로세스를 분기하고 외부 명령을 실행하는 것이 좋습니다.mkdir

counter=$(printf %02d $i)

또한 bash에서 프로세스를 포크합니다. 다음과 같이 작성하면 이를 방지할 수 있습니다.

printf -v counter %02d "$i"

또는:

printf -v testfile %s/%s_%02d.txt "$testdir" "${testdir##*/}" "$i"

mkdir파일당 하나씩 실행하는 대신 한 번의 호출로 모든 디렉터리를 만듭니다( mkdir -p -- "$@"; 잊지 마세요) .--mkdir

다음 중 하나에 임시 파일이 필요하지 않습니다.

data=$(< /dev/urandom tr -dc "\t\n [:alnum:]" | head -c32768; echo .)
data=${data%.}

.명령 대체가 제거되므로 32768바이트를 포함하도록 보장 하려면 $data추가가 필요합니다.모두후행 개행 문자. 또한 아무도 추가되지 echo않는다는 점에 유의하세요 . -n임의의 데이터의 경우 printf어쨌든 대신 사용해야 합니다.echo

또한 head -c 32768문자가 아닌 32768바이트를 제공하므로 문자가 중간에 잘릴 수 있습니다.

printf %s "$data" > "$file"

답변2

뭔가를 참다스티븐 차제라스그들은 약간의 수정을 가한 훌륭한 답변으로 말했습니다.

#!/usr/bin/env bash

set -e
set -u

main() {
  < /dev/urandom tr -dc "\t\n [:alnum:]" | dd iflag=fullblock of=./temp.txt bs=32K count=1
  mkdir -p -- "${@:?}"
  for testdir in "$@"; do
    for i in {1..3}; do
      printf "%s/%s_%02d.txt\n" "$testdir" "${testdir##*/}" "$i"
    done
  done | xargs -n1 -P${proc:-16} cp ./temp.txt
}

time main "${@}"

  • dd- 정확한 바이트 수를 얻는 다른 방법(비록 한 번만 발생하므로 어느 쪽이든 큰 차이는 없음)
  • 이 모든 것이 echo1000을 세게 되었을 때 약 3초가 추가되었습니다.
  • 멀티스레드, 런타임 시 조정 가능( proc변수를 통해) - 시스템에 가장 적합한 값을 찾으세요.

예를 들어

proc=32 bash ./foo.sh {1..1000}

참고 - 변수 채우기에 대한 원래 질문이 인스턴스라고 가정합니다.XY 문제... 만약에이것은 어려운 요구 사항이며 내 답변은 서면으로 유효하지 않습니다.

하지만 이 변경으로 인해 다음이 수행되어야 합니다.

data="$(< /dev/urandom tr -dc "\t\n [:alnum:]" | dd iflag=fullblock bs=32K count=1)"
dd iflag=fullblock bs=32K count=1 of=./temp.txt <<<"${data}"

두 번째는 dd생성된 데이터만 가져오도록 하는 것입니다. 그 사이 어딘가에서 어딘가에서 추가 바이트(암시된 줄 바꿈?)를 찾는 것처럼 보입니다 $( ). <<<이 문제를 해결해 드리겠습니다. 다소 번거롭다는 점은 인정합니다. 임의 데이터의 크기가 임의적이거나 중요하지 않은 경우 단순화할 수 있다고 확신합니다.

관련 정보