zfs 파일 시스템을 백업하려고 할 때 이상한 성능 문제가 발생합니다.
zfs 파일 시스템의 내용을 100MB/s 이상으로 압축할 수 있지만 zfs 전송 전송 속도는 아마도 5MB/s일 것입니다. 파일 시스템에는 5~6개의 스냅샷만 있습니다. 타르는 약 1.5시간이 소요됩니다. zfs 전송에는 12시간 이상이 소요됩니다!
두 경우 모두 대상은 다른 풀에 있는 파일입니다. (즉, zfs send tank/myfs > /backup/myfs.zfsbackup
대 tar -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 스크립트일 것입니다. 왜냐하면 "시스템이 실제로 무엇을 하고 있습니까?"라는 질문에 대한 답을 알려주기 때문입니다.