Disk performansı sorunları, sysadmin hayatının en can sıkıcı konularından biridir. Kullanıcılar “sistem yavaş” der, siz CPU ve RAM’e bakarsınız, her şey normal görünür. Ama disk I/O grafiğine bakınca iş anlaşılır. Peki bu performansı doğru ölçüyor musunuz? Çoğu sysadmin ilk aklına gelen dd komutunu çalıştırır, bir sayı alır ve “tamam” der. Ama bu yaklaşım, gerçek dünya iş yükünü hiç yansıtmayabilir. Bu yazıda hem dd hem de çok daha güçlü olan fio aracını detaylıca inceleyeceğiz.
Neden Disk I/O Ölçümü Bu Kadar Önemli
Bir veritabanı sunucusunda yaşanan yavaşlık, bir NFS mount’un beklenenden düşük throughput vermesi, SSD yükseltmesi sonrası beklenen performans artışının görülmemesi… Tüm bu senaryolarda güvenilir ölçüm araçlarına ihtiyaç duyarsınız.
Disk I/O performansını etkileyen birkaç temel metrik vardır:
- IOPS (Input/Output Operations Per Second): Saniyede kaç okuma/yazma işlemi yapılabildiği
- Throughput (MB/s): Saniyede transfer edilen veri miktarı
- Latency (ms/µs): Her bir I/O işleminin tamamlanma süresi
- Queue Depth: Eş zamanlı bekleyen I/O işlemi sayısı
Bu metriklerin hepsi farklı senaryolarda kritik olabilir. Bir veritabanı için IOPS ve latency ön plandayken, bir yedekleme sistemi için throughput daha önemlidir.
dd ile Temel Disk Testleri
dd komutu Linux’ta yıllardır var olan, basit ama hızlı sonuç veren bir araçtır. Karmaşık kurulum gerektirmez, her sistemde hazır bulunur. Ancak sınırlamalarını bilmek şarttır.
dd’nin Temel Kullanımı
En basit yazma testi şöyle yapılır:
dd if=/dev/zero of=/tmp/test_write bs=1M count=1024 conv=fdatasync status=progress
Bu komut 1 GB’lık veri yazar. Parametreleri açıklayalım:
- if=/dev/zero: Kaynak olarak sıfır dolu sanal cihazı kullanır (CPU yükü minimumda kalır)
- of=/tmp/test_write: Hedef dosya
- bs=1M: Block size, yani her seferinde 1 MB’lık bloklar yazar
- count=1024: 1024 blok yani toplam 1 GB
- conv=fdatasync: Yazma tamamlanana kadar bekler, kernel buffer’ı diske flush eder
- status=progress: Gerçek zamanlı ilerleme gösterir
conv=fdatasync parametresi çok kritiktir. Bu olmadan dd, veriyi sadece kernel cache’e yazar ve gerçek disk performansını değil, RAM hızını ölçmüş olursunuz.
dd ile Okuma Testi
# Önce disk cache'i temizleyelim
sync && echo 3 > /proc/sys/vm/drop_caches
# Ardından okuma testini çalıştıralım
dd if=/tmp/test_write of=/dev/null bs=1M status=progress
Cache temizlemek şart. Aksi takdirde veriler RAM’den okunur ve disk performansı yerine bellek hızı ölçülür. Bu hata düşündüğünüzden çok daha sık yapılır.
Farklı Block Size ile Test
# Küçük bloklar (random I/O simülasyonu)
dd if=/dev/zero of=/tmp/test_small bs=4K count=102400 conv=fdatasync status=progress
# Büyük bloklar (sequential I/O simülasyonu)
dd if=/dev/zero of=/tmp/test_large bs=128M count=8 conv=fdatasync status=progress
4K blok boyutu, veritabanlarının tipik çalışma modunu simüle eder. 128M ise yedekleme veya büyük dosya transferi senaryolarına yakındır.
/dev/sda’dan Doğrudan Okuma
# Dikkat: Çalışan sistemde bunu yapmak risklidir
# Test sisteminde veya unmount edilmiş diskte kullanın
dd if=/dev/sda of=/dev/null bs=1M count=1000 status=progress
Bu komut, dosya sistemi overhead’i olmadan doğrudan disk okuma hızını ölçer. Ama production sistemde yaparken dikkatli olun.
dd’nin Sınırları
dd birkaç kritik konuda yetersiz kalır:
- Sadece sequential I/O test edebilir, random I/O için uygun değildir
- Tek thread çalışır, modern depolama sistemlerinin paralel işlem kapasitesini test edemez
- Latency ölçümü yapmaz
- Queue depth kontrolü yoktur
- Tekrarlanabilir ve kapsamlı benchmark için yeterli değildir
İşte burada fio devreye girer.
fio: Ciddi Benchmark Aracı
fio (Flexible I/O Tester), gerçek anlamda profesyonel disk benchmark aracıdır. LinkedIn, Facebook gibi şirketlerin depolama altyapılarını test etmek için kullandığı bir araçtır. Öğrenme eğrisi biraz dik, ama bir kez öğrenince vazgeçemezsiniz.
fio Kurulumu
# Ubuntu/Debian
apt install fio
# RHEL/CentOS/Rocky Linux
yum install fio
# veya
dnf install fio
# Kaynak koddan derleme (en güncel sürüm için)
git clone https://github.com/axboe/fio.git
cd fio && ./configure && make && make install
fio’nun Temel Parametreleri
Bir fio komutunu anlamak için parametreleri tanımak gerekir:
- –name: Test adı, log dosyalarında kullanılır
- –ioengine: I/O motoru (libaio, sync, psync, mmap vb.)
- –iodepth: Eş zamanlı bekleyen I/O sayısı (queue depth)
- –rw: I/O tipi (read, write, randread, randwrite, randrw, rw)
- –bs: Block size
- –direct: 1 olursa kernel cache bypass edilir, gerçek disk test edilir
- –size: Test dosyası boyutu
- –numjobs: Paralel iş parçacığı sayısı
- –runtime: Test süresi (saniye)
- –group_reporting: Tüm job’ların sonuçlarını birleştirerek gösterir
- –filename: Test dosyasının yolu
Sequential Read/Write Testi
# Sequential Write
fio --name=seq-write
--ioengine=libaio
--iodepth=32
--rw=write
--bs=1M
--direct=1
--size=4G
--numjobs=1
--runtime=60
--group_reporting
--filename=/tmp/fio_test
# Sequential Read
fio --name=seq-read
--ioengine=libaio
--iodepth=32
--rw=read
--bs=1M
--direct=1
--size=4G
--numjobs=1
--runtime=60
--group_reporting
--filename=/tmp/fio_test
Random Read/Write Testi (Veritabanı Simülasyonu)
# Random 4K Write - Veritabanı yazma işlemlerini simüle eder
fio --name=rand-write-4k
--ioengine=libaio
--iodepth=64
--rw=randwrite
--bs=4K
--direct=1
--size=4G
--numjobs=4
--runtime=120
--group_reporting
--filename=/tmp/fio_test_db
Bu test çıktısında dikkat etmeniz gereken satırlar:
write: IOPS=45.2k, BW=176MiB/s
lat (usec): min=89, max=8432, avg=1415.23, stdev=892.44
clat percentiles (usec):
| 1.00th=[ 245], 5.00th=[ 388], 10.00th=[ 494],
| 90.00th=[ 2638], 95.00th=[ 3326], 99.00th=[ 5080],
| 99.50th=[ 5800], 99.90th=[ 6849], 99.99th=[ 8160]
Percentile değerleri çok önemlidir. p99 latency, kullanıcıların %1’inin yaşadığı en kötü durumu gösterir. Bir web uygulaması için bu değer kritik olabilir.
Mixed Read/Write Testi
Gerçek dünya iş yükleri genellikle karma okuma/yazma içerir:
# %70 okuma, %30 yazma - Tipik OLTP veritabanı profili
fio --name=mixed-rw
--ioengine=libaio
--iodepth=32
--rw=randrw
--rwmixread=70
--bs=4K
--direct=1
--size=8G
--numjobs=8
--runtime=180
--group_reporting
--filename=/tmp/fio_mixed
fio Job Dosyası Kullanımı
Uzun komut satırları yerine, tekrarlanabilir testler için job dosyası kullanmak çok daha profesyoneldir. İşte kapsamlı bir örnek:
cat > /tmp/disk_benchmark.fio << 'EOF'
[global]
ioengine=libaio
direct=1
runtime=60
time_based=1
group_reporting=1
filename=/tmp/fio_benchmark_file
[seq-read]
rw=read
bs=1M
iodepth=8
numjobs=1
[seq-write]
rw=write
bs=1M
iodepth=8
numjobs=1
stonewall
[rand-read-4k]
rw=randread
bs=4K
iodepth=64
numjobs=4
stonewall
[rand-write-4k]
rw=randwrite
bs=4K
iodepth=64
numjobs=4
stonewall
EOF
# Çalıştır
fio /tmp/disk_benchmark.fio
stonewall parametresi, bir önceki test bitmeden sonrakinin başlamamasını sağlar.
Gerçek Dünya Senaryoları
Senaryo 1: Yeni Sunucu Kabulü
Yeni bir fiziksel sunucu veya sanal makine geldiğinde, SLA’da yazılan disk performansını doğrulamak gerekir. Bulut sağlayıcılar “up to” diye başlayan performans değerleri verir. Bu değerleri gerçekte alıp almadığınızı doğrulamanız şarttır.
# Hızlı kabul testi scripti
#!/bin/bash
TEST_FILE="/tmp/fio_acceptance_test"
TEST_SIZE="8G"
echo "=== Acceptance Test Basliyor ==="
echo "Test dosyasi: $TEST_FILE"
echo "Test boyutu: $TEST_SIZE"
# Sequential throughput
fio --name=seq_throughput
--ioengine=libaio
--rw=rw
--bs=1M
--direct=1
--iodepth=16
--size=$TEST_SIZE
--numjobs=2
--runtime=60
--group_reporting
--output-format=json
--output=/tmp/fio_seq_results.json
--filename=$TEST_FILE
# Random IOPS
fio --name=rand_iops
--ioengine=libaio
--rw=randrw
--bs=4K
--direct=1
--iodepth=128
--size=$TEST_SIZE
--numjobs=8
--runtime=60
--group_reporting
--output-format=json
--output=/tmp/fio_rand_results.json
--filename=$TEST_FILE
rm -f $TEST_FILE
echo "Test tamamlandi. Sonuclar /tmp/fio_*_results.json dosyalarinda."
Senaryo 2: SSD vs HDD Karşılaştırması
Depolama yükseltmesi öncesinde ve sonrasında aynı testi çalıştırın. Sonuçları kaydedin ve karşılaştırın.
# Her iki diskte de çalıştırın, sadece filename değiştirin
fio --name=storage_compare
--ioengine=libaio
--iodepth=1
--rw=randread
--bs=4K
--direct=1
--size=2G
--numjobs=1
--runtime=30
--group_reporting
--filename=/mnt/hdd/fio_test # veya /mnt/ssd/fio_test
iodepth=1 ve numjobs=1 ile latency testini yaparsınız. HDD için bu değer genellikle 1-10ms aralığındadır. NVMe SSD için 50-200 microsecond olması beklenir. Bu farkı görmek için latency orientated test yapın.
Senaryo 3: NFS Performans Sorunları
Bir NFS mount’u yavaş görünüyorsa, hem local disk hem de NFS üzerinde aynı testi çalıştırın:
# Local disk testi
fio --name=local_test
--ioengine=sync
--rw=write
--bs=64K
--size=1G
--numjobs=4
--group_reporting
--filename=/tmp/local_fio_test
# NFS üzerinde aynı test
fio --name=nfs_test
--ioengine=sync
--rw=write
--bs=64K
--size=1G
--numjobs=4
--group_reporting
--filename=/mnt/nfs_share/fio_test
NFS için ioengine=sync kullanmak genellikle daha güvenilir sonuç verir. libaio ile NFS bazen beklenmedik sonuçlar üretebilir.
fio Çıktısını Yorumlamak
fio çıktısı ilk bakışta korkutucu görünebilir. Ama hangi satırlara bakacağınızı bilince iş kolaylaşır.
rand-write-4k: (g=0): rw=randwrite, bs=(R) 4096B-4096B, (W) 4096B-4096B, ioengine=libaio, iodepth=64
...
Run status group 0 (all jobs):
WRITE: bw=182MiB/s (191MB/s), 45.6MiB/s-45.6MiB/s (47.8MB/s-47.8MB/s), io=10.9GiB (11.7GB), run=61406-61406msec
write: IOPS=46.6k, BW=182MiB/s (191MB/s)(11.9GiB/61406msec)
lat (usec): min=88, max=15238, avg=1373.24, stdev=845.12
clat percentiles (usec):
| 50.00th=[ 1237], 90.00th=[ 2376], 99.00th=[ 4752], 99.99th=[13olean]
Yorumlama rehberi:
- bw (bandwidth): Throughput değeri, ne kadar veri transfer edildi
- IOPS: Saniyede kaç işlem yapıldı
- lat avg: Ortalama gecikme süresi
- lat percentiles: Dağılım bilgisi, p99 ve p99.99 değerleri en kritik olanlardır
- clat: Completion latency, I/O’nun kuyruğa girmesinden tamamlanmasına kadar geçen süre
- slat: Submission latency, kernel’a submit edilene kadar geçen süre
İzleme ile Test Sonuçlarını Desteklemek
Test çalışırken paralel olarak disk istatistiklerini izlemek, sonuçları doğrulamaya yardımcı olur:
# Terminal 1: fio testi
fio --name=test --ioengine=libaio --rw=randwrite --bs=4K
--direct=1 --iodepth=32 --size=2G --filename=/tmp/fio_t
# Terminal 2: iostat ile anlık izleme
iostat -x 1 /dev/sda
# veya
iostat -xz 1
# Terminal 3: iotop ile process bazlı izleme
iotop -o -d 2
iostat çıktısında dikkat edilecekler:
- %util: Diskin ne kadar meşgul olduğu, %100’e yaklaşıyorsa disk dolu kapasitede
- await: Ortalama I/O bekleme süresi (ms)
- r/s ve w/s: Saniyedeki okuma ve yazma sayısı
- rMB/s ve wMB/s: Throughput değerleri
Yaygın Hatalar ve Dikkat Edilecekler
Cache boyutunu göz ardı etmek: Test dosyanız RAM boyutundan küçükse, tüm veriler cache’lenir ve disk hiç test edilmez. Örneğin 16 GB RAM olan bir sunucuda 1 GB test dosyası kullanırsanız, ikinci okumada disk yerine RAM ölçersiniz. Test dosyası her zaman RAM’in en az 2 katı olmalıdır.
Production sistemde test yapmak: fio yoğun I/O üretir. Çalışan bir veritabanı sunucusunda test yapmak sistemi yavaşlatabilir veya çökertebilir. Test için ayrı bir zaman penceresi belirleyin ya da test ortamını kullanın.
Disk cache’ini temizlemeyi unutmak: dd testlerinde özellikle kritik. Cache temizliği şöyle yapılır:
sync
echo 3 > /proc/sys/vm/drop_caches
Yanlış ioengine seçimi: libaio çoğu durumda idealdir ama bazı dosya sistemleri veya yapılandırmalar için sync veya psync daha doğru sonuç verebilir.
Isınma süresini es geçmek: Flash depolama cihazları soğuk başlangıçta farklı performans gösterebilir. Gerçekçi sonuçlar için teste başlamadan önce 30-60 saniye isınma süresi bırakmak iyi bir alışkanlıktır. fio’da --ramp_time=30 parametresi bunu otomatik yapar.
fio --name=warmed_test
--ioengine=libaio
--rw=randread
--bs=4K
--direct=1
--iodepth=32
--size=4G
--runtime=120
--ramp_time=30
--filename=/tmp/fio_warm_test
Ne Zaman Hangisini Kullanmalı
dd kullanın şu durumlarda:
- Hızlı bir throughput tahminine ihtiyaç duyduğunuzda
- Script içinde basit sağlık kontrolü yapacaksanız
- fio kurulu değilse ve kurma imkanınız yoksa
- Sequential I/O bazlı senaryolarda
fio kullanın şu durumlarda:
- Sistemi üretime almadan önce kapsamlı kabul testi yapıyorsanız
- Veritabanı performans sorunlarını araştırıyorsanız
- SAN, NVMe veya yüksek kapasiteli depolama sistemlerini test ediyorsanız
- Vendor ile SLA tartışması yapıyorsanız, fio çıktısı çok daha ikna edicidir
- Random I/O, latency ve percentile değerlerine ihtiyaç duyuyorsanız
- Tekrarlanabilir ve belgelenebilir test sürecine ihtiyaç varsa
Sonuç
Disk I/O ölçümü, görünürde basit ama derinleşince oldukça katmanlı bir konu. dd ile hızlı bir fikir edinebilirsiniz, ama asıl sorunları bulmak ve doğrulamak için fio vazgeçilmez. Özellikle cache’i düzgün temizlemeden, direct=1 kullanmadan veya test dosyası boyutuna dikkat etmeden yapılan testler, sizi yanlış sonuçlara götürebilir.
Pratikte en iyi yaklaşım şudur: Yeni bir sistem geldiğinde fio ile kapsamlı bir kabul testi yapın ve sonuçları baseline olarak kaydedin. Zamanla performans düşüşü yaşandığında, bu baseline’a dönerek karşılaştırma yapabilirsiniz. Bir şeyin bozulduğunu kanıtlamak, tahmin yürütmekten çok daha güçlüdür.
Disk testleri yaparken her zaman test ortamını, test parametrelerini ve sonuçları belgeleyin. İleride “bu disk neden yavaş?” sorusu geldiğinde, elinizde geçmişe ait karşılaştırılabilir veriler olması, problemi saatler içinde değil dakikalar içinde çözmenizi sağlar.