zfs 전송 성능

zfs 전송 성능

zfs 파일 시스템을 백업하려고 할 때 이상한 성능 문제가 발생합니다.

zfs 파일 시스템의 내용을 100MB/s 이상으로 압축할 수 있지만 zfs 전송 전송 속도는 아마도 5MB/s일 것입니다. 파일 시스템에는 5~6개의 스냅샷만 있습니다. 타르는 약 1.5시간이 소요됩니다. zfs 전송에는 12시간 이상이 소요됩니다!

두 경우 모두 대상은 다른 풀에 있는 파일입니다. (즉, zfs send tank/myfs > /backup/myfs.zfsbackuptar -cf /backup/myfs.tar ./myfs)

처음에는 조각화라고 생각했는데, 그렇다면 타르도 그만큼 느리지 않을까요?

전체적인 디스크 성능은 괜찮은 편인데, 실제로 백업하는 데 시간이 오래 걸립니다.

저는 x64 하드웨어에서 Solaris 11.4를 실행하고 있습니다. 개념적으로 이 질문은 Linux의 zfs와 유사할 수 있지만 Linux 변형에는 그다지 익숙하지 않습니다.

zfs send가 실행되는 동안 약 12분 동안 아래 답변에 제공된 dtrace 스크립트를 실행했습니다.

dtrace -i 'profile:::profile-1001hz /arg0/ { @[ stack() ] = count(); }'

결과를 어떻게 해석해야 할지 모르겠습니다. 요약의 두 부분에는 많은 수의 zfs 호출이 포함되어 있습니다.

      zfs`zfs_fletcher_4_native+0x79
      zfs`zfs_checksum_compute+0x181
      zfs`zio_checksum_compute+0x1d6
      zfs`zio_checksum_compute_dispatch+0x28
      zfs`zio_checksum_generate+0x59
      zfs`zio_execute+0xb4
      genunix`taskq_thread+0x3d5
      unix`thread_start+0x8
     1041

      unix`bcopy+0x55a
      genunix`uiomove+0xb3
      zfs`dmu_xuio_transform+0x83
      zfs`zfs_write+0x78a
      genunix`fop_write+0xf5
      genunix`vn_rdwr_impl+0x1f3
      genunix`vn_rdwr_uiov+0x63
      zfs`dump_buffer_flush+0x8e
      zfs`dump_buffer_append+0x85
      zfs`dump_bytes_impl+0x49
      zfs`dump_bytes+0x49
      zfs`dump_record+0x190
      zfs`dump_data+0x26a
      zfs`backup_cb+0x4b5
      zfs`traverse_visitbp+0x3df
      zfs`traverse_visitbp+0x8e4
      zfs`traverse_visitbp+0x8e4
      zfs`traverse_dnode+0x1dc
      zfs`traverse_visitbp+0x6d2
      zfs`traverse_visitbp+0x8e4
     1183

호출 수가 가장 많은 것은 CPU 유휴 호출인 것 같습니다.

          unix`mach_cpu_idle+0x17
          unix`cpu_idle+0x2b7
          unix`cpu_idle_adaptive+0x19
          unix`idle+0x11e
          unix`thread_start+0x8
      1147665

          unix`mach_cpu_idle+0x17
          unix`cpu_idle+0x2b7
          unix`cpu_idle_adaptive+0x19
          unix`idle+0x11e
          unix`thread_start+0x8
      2462890

zfs 전송 중에 드라이브는 바빴지만 대기 시간 없이 서비스 시간은 그리 나쁘지 않다고 생각했습니다...

                    extended device statistics
    r/s    w/s   Mr/s   Mw/s wait actv wsvc_t asvc_t  %w  %b device
 157.0    0.0    4.9    0.0  0.0  1.6    0.0   10.5   0  77 c0t5000C500A22D9330d0
 154.0    0.0    4.9    0.0  0.0  1.7    0.0   11.0   0  82 c0t5000C500A232AFA6d0
 186.0    0.0    6.4    0.0  0.0  2.4    0.0   12.7   0  93 c0t5000C500A24AD833d0
 185.0    0.0    6.3    0.0  0.0  1.8    0.0    9.9   0  79 c0t5000C500A243C8DEd0

tar 중에 디스크 사용량은 r/s, 서비스 시간, %busy 등 상당히 유사한 것처럼 보이지만 읽은 데이터 양은 매우 다릅니다.

                    extended device statistics
    r/s    w/s   Mr/s   Mw/s wait actv wsvc_t asvc_t  %w  %b device
 158.0    0.0   33.3    0.0  0.0  1.9    0.0   11.9   0  86 c0t5000C500A22D9330d0
 190.0    0.0   31.9    0.0  0.0  1.6    0.0    8.3   0  75 c0t5000C500A232AFA6d0
 170.0    0.0   37.1    0.0  0.0  1.7    0.0    9.7   0  80 c0t5000C500A24AD833d0
 168.0    0.0   38.4    0.0  0.0  1.7    0.0   10.1   0  80 c0t5000C500A243C8DEd0

답변1

명령을 실행할 때 zfs send ...이 dTrace 명령을 실행하여 커널이 시간을 소비하는 위치를 확인할 수 있습니다.

dtrace -i 'profile:::profile-1001hz /arg0/ { @[ stack() ] = count(); }'

명령을 시작 root하고 잠시 동안 실행한 후 클릭하여 CTRL-C중지하면 숫자가 증가하는 순서로 샘플링하는 모든 커널 스택 추적을 내보냅니다.

따라서 발견된 가장 일반적인 스택 추적은 마지막 스택 추적이 됩니다. 커널이 대부분의 시간을 보내는 곳이 바로 이곳입니다.

이 정보는 도움이 될 수도 있고 그렇지 않을 수도 있습니다.

또는 다음과 같은 파일에 저장할 수 있습니다.

#!/usr/sbin/dtrace -s

profile:::profile-1001hz
/arg0/
{
    @[ stack() ] = count();
}

나는 dTrace가 Solaris 10에 처음 등장한 이후로 이 작은 스크립트를 사용해 왔습니다. 이는 아마도 제가 본 것 중 가장 유용한 단일 dTrace 스크립트일 것입니다. 왜냐하면 "시스템이 실제로 무엇을 하고 있습니까?"라는 질문에 대한 답을 알려주기 때문입니다.

관련 정보