Test & CI
TEKNİK REHBER TEST & CI RT TEST 2026

cyclictest —
RT latency ölçümü.

PREEMPT_RT kernel doğrulama, worst-case latency histogramı ve <50 µs industrial Linux hedefi için adım adım tuning süreci.

00 RT latency nedir? — jitter ve WCET kavramları

Real-time sistemlerde performans ölçütü ortalama süre değil, en kötü durum gecikme süresi (WCET — Worst-Case Execution Time) ve bunun öngörülebilirliğidir.

Latency, jitter ve WCET

Latency (gecikme), bir olayın gerçekleşmesi ile sistemin bu olaya yanıt vermesi arasındaki süredir. Örneğin: interrupt gelir, interrupt handler çalışır — aradaki geçen süre interrupt latency'dir.

Jitter, ardışık latency ölçümleri arasındaki varyasyondur. Latency'nin 47 µs ve 48 µs arasında dalgalanması düşük jitter anlamına gelir; 10 µs ile 200 µs arasında değişmesi yüksek jitter demektir. Hard RT sistemlerde düşük jitter, düşük ortalama kadar önemlidir.

WCET, uzun süre boyunca gözlemlenen maksimum latency değeridir. "1 milyon ölçümde hiçbiri 50 µs'yi geçmedi" ifadesi, o sistemin WCET'inin (ölçüm süresince) 50 µs olduğunu anlatır. Standart Linux'ta WCET tahmin edilemez; PREEMPT_RT ile kernel preemption engelleri kaldırılarak WCET düşürülür ve öngörülebilir hale getirilir.

Kernel yapısıTipik ortalama latencyTipik WCETÖngörülebilirlik
PREEMPT_NONE~5 µsonlarca msDüşük
PREEMPT (desktop)~2 µs~1 msOrta
PREEMPT_RT~5 µs<50 µs (iyi tuning)Yüksek
RTOS (FreeRTOS)<1 µs<10 µsÇok yüksek

Latency kaynakları

Linux'ta latency'ye katkıda bulunan başlıca faktörler şunlardır: non-preemptible kod bölgeleri (spinlock, RCU critical section), yüksek frekanslı timer interrupt'ları, NUMA ve cache miss'ler, SMI (System Management Interrupts) — bu son öge BIOS düzeyinde oluşur ve yazılımdan tamamen gizlenebilir, dolayısıyla en tehlikeli latency kaynağıdır.

Dikkat

SMI (System Management Interrupt), BIOS/UEFI firmware tarafından üretilir ve işlemciyi SMM (System Management Mode) moduna alır. Bu süre zarfında hiçbir OS kodu çalışmaz. Bazı BIOS implementasyonlarında SMI her saniye onlarca kez tetiklenebilir. hwlatdetect ile SMI kaynaklı latency spike'ları tespit edilebilir.

01 rt-tests paketi — araç ailesi

rt-tests, PREEMPT_RT çekirdeklerini doğrulamak için geliştirilmiş, birbirini tamamlayan araçlardan oluşan bir pakettir.

Kurulum

bash — rt-tests kurulumu
# Debian/Ubuntu paket deposundan
apt-get install rt-tests

# Kaynak koddan derleme (önerilen — güncel sürüm için)
git clone https://git.kernel.org/pub/scm/utils/rt-tests/rt-tests.git
cd rt-tests
make
sudo make install

Araç ailesi

AraçAmaçTipik kullanım
cyclictestTimer latency ölçümüRT kernel doğrulama, tuning
hackbenchScheduler yük üreticiCyclictest ile birlikte yük oluşturma
pi_stressPriority inheritance testiRT mutex priority inversion kontrolü
hwlatdetectSMI / hardware latency tespitiBIOS SMI spike analizi
oslatOS jitter ölçümüUserspace scheduling jitter
ssddSignal/syscall latencySignal delivery süresi ölçümü

hwlatdetect ile SMI tespiti

bash — SMI latency tespiti
# hwlatdetect 10 saniye boyunca polling yapar
# Kernel SMI sırasında döngüde boşluk görür

hwlatdetect --duration=30 --threshold=10

# Çıktı örneği:
# hwlatdetect:  version 1.0
# parameters:
#   Latency threshold: 10us
#   Sample window:     1000000us
#   Sample width:      500000us
#   Non-sampling period: 500000us
#   Output File:       None
# Starting detection...
# Max latency: 23us  (SMI kaynaklı spike!)

02 cyclictest parametreleri — kapsamlı referans

cyclictest, periyodik timer'lar oluşturarak beklenen uyku süresi ile gerçek uyku süresinin farkını ölçer. Bu fark, sistemin latency değerini verir.

Temel çalışma prensibi

  Thread başlar, t0 = şimdiki zaman
       │
       ▼
  clock_nanosleep(t0 + interval) ile uyur
       │
       ▼
  Uyanır, t1 = şimdiki zaman
       │
  Latency = t1 - (t0 + interval)
       │
       ▼
  Sonraki döngüye geç, tekrar et
    

Önemli parametreler

-t N
Thread sayısı. Varsayılan: 1. Her thread ayrı CPU çekirdeğinde çalıştırılabilir. Çok çekirdekli sistemlerde -t $(nproc) tüm çekirdekleri test eder.
-p PRIO
SCHED_FIFO önceliği (1-99). Yüksek öncelik latency ölçümünü sistem gürültüsünden korur. Tipik: -p 99.
-i INTERVAL
Timer periyodu (mikrosaniye). Varsayılan: 1000 µs (1 ms). Daha kısa interval (ör. 200 µs) daha agresif test sağlar.
-d DELTA
Thread'ler arası interval farkı (µs). Thread 0: interval, Thread 1: interval+delta, vb.
-h BUCKETS
Histogram bucket sayısı. Bu parametreyle histogram çıktısı aktif hale gelir. -h 400 → 0-400 µs arası dağılım.
-l LOOPS
Döngü sayısı. -l 0 sonsuz çalıştırır. Belirli test süresi için -D kullanılabilir.
-D DURATION
Test süresi. Örnekler: -D 60s, -D 10m, -D 24h.
--json=FILE
Sonuçları JSON formatında dosyaya yaz. CI entegrasyonu ve otomasyon için idealdir.
--smi
SMI sayacını etkinleştirir (x86). Her döngüde SMI sayacı okunur; artış SMI latency'si anlamına gelir.
-a CPULIST
Thread'lerin çalışacağı CPU listesi. -a 2-3 thread'leri CPU 2 ve 3'e bağlar.

Tipik kullanım senaryoları

bash — cyclictest kullanım örnekleri
# Hızlı doğrulama (1 thread, 100k döngü)
cyclictest -p 99 -t 1 -l 100000

# Tam RT doğrulama (tüm çekirdekler, 1M döngü, histogram)
cyclictest -p 99 -t $(nproc) -l 1000000 -h 400 -q

# 24 saatlik dayanıklılık testi
cyclictest -p 99 -t $(nproc) -D 24h -h 400 --json=/tmp/results.json

# CPU isolation ile belirli çekirdek
cyclictest -p 99 -t 2 -a 2,3 -i 200 -D 60m -h 400

# SMI tespiti ile (x86)
cyclictest -p 99 -t $(nproc) -D 60s -h 400 --smi

03 Latency histogramı çizimi

Histogram çıktısı, latency dağılımının görsel analizi için en değerli araçtır. Tek bir maksimum değerin ötesinde, tüm dağılımı görmek gerekir.

Histogram verisi üretimi

bash — histogram verisi toplama
# Histogram verisi üret (4 thread, 10 dakika)
cyclictest -p 99 -t 4 -a 2,3,4,5 -D 10m \
  -h 400 --histfile=/tmp/hist.dat -q

# Dosya formatı:
# #Histogram
# #Index  Thread0   Thread1   Thread2   Thread3
# 1       0         0         0         0
# 2       12        8         15        6
# 3       45238     41120     43001     40987
# ...
# Overflows: 0  0  0  0

gnuplot ile görselleştirme

gnuplot — latency histogram scripti
#!/bin/bash
# hist-plot.sh — Histogram grafiği oluştur

cat > /tmp/hist.gnuplot << 'EOF'
set terminal png size 1200,600 font "monospace,11"
set output "/tmp/latency-histogram.png"
set title "RT Latency Histogram — cyclictest"
set xlabel "Latency (µs)"
set ylabel "Occurrences"
set logscale y
set xrange [0:100]
set yrange [1:*]
set grid
set key top right

plot "/tmp/hist.dat" using 1:2 with impulses lc "blue"  title "CPU2", \
     "/tmp/hist.dat" using 1:3 with impulses lc "red"   title "CPU3", \
     "/tmp/hist.dat" using 1:4 with impulses lc "green" title "CPU4", \
     "/tmp/hist.dat" using 1:5 with impulses lc "orange" title "CPU5"
EOF

gnuplot /tmp/hist.gnuplot
echo "Grafik: /tmp/latency-histogram.png"

JSON çıktısından analiz

bash — JSON sonuç analizi
cyclictest -p 99 -t $(nproc) -D 60s \
  --json=/tmp/ct-results.json -q

# Maksimum ve ortalama latency
jq '.thread[] | {cpu: .id, max: .max, avg: .avg, min: .min}' \
  /tmp/ct-results.json

# Tüm thread'lerin global maksimumu
jq '[.thread[].max] | max' /tmp/ct-results.json

# 50 µs eşiğini geçen toplam ölçüm sayısı (histogram üzerinden)
jq '[.histogram.thread[].histogram | to_entries[]
     | select(.key | tonumber >= 50) | .value] | add // 0' \
  /tmp/ct-results.json

Histogramı okuma rehberi

İdeal bir PREEMPT_RT histogramı şu özelliklere sahip olmalıdır: büyük çoğunluk (>%99.9) 20-30 µs bandında yoğunlaşır, kuyruk kısmen 50 µs'e kadar uzanabilir, 100 µs üzerinde hiç ölçüm olmamalıdır. "Long tail" denen uzun kuyruk varlığı, tutarsız bir kaynağa işaret eder — genellikle SMI, NUMA erişimi veya kötü ayarlanmış IRQ affinity.

04 /proc/sys/kernel tunables

Kernel'in çalışma zamanında ayarlanabilen bazı parametreleri, RT latency üzerinde doğrudan etkiye sahiptir. Bu tunables sysctl veya doğrudan procfs üzerinden ayarlanabilir.

Kritik tunables

sched_rt_runtime_us
RT task'ların her saniyede kaç µs CPU kullanabileceğini sınırlar. Varsayılan 950000 µs (%95). RT task'ların CPU'yu tamamen ele geçirebilmesi için -1 yapın. Aksi hâlde SCHED_FIFO task'lar throttle edilebilir.
numa_balancing
NUMA otomatik dengeleme. Süreç migrasyonları latency spike'ına neden olabilir. 0 yaparak devre dışı bırakın.
sched_min_granularity_ns
CFS scheduler'ın minimum zaman dilimi. Düşürülmesi scheduling sıklığını artırır, ancak kontekst değiştirme maliyetini de yükseltir.
timer_migration
Timer'ların boştaki CPU'lara göç etmesini kontrol eder. RT sistemlerde 0 yapılması timer sürprizlerini önler.
bash — RT tunables ayarlama
# RT throttling'i kapat (kritik!)
sysctl -w kernel.sched_rt_runtime_us=-1

# NUMA dengelemeyi kapat
sysctl -w kernel.numa_balancing=0

# Timer migrasyonunu kapat
sysctl -w kernel.timer_migration=0

# Transparent HugePages kapat (TLB shootdown latency)
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag

# Kalıcı ayar için /etc/sysctl.d/99-rt.conf:
cat > /etc/sysctl.d/99-rt.conf << 'EOF'
kernel.sched_rt_runtime_us = -1
kernel.numa_balancing = 0
kernel.timer_migration = 0
EOF
sysctl --system

CPU frequency scaling

bash — CPU governor ayarları
# Tüm CPU'lar için performance governor
for cpu in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor; do
  echo performance > $cpu
done

# P-state ve turbo kontrolü (Intel)
echo 1 > /sys/devices/system/cpu/intel_pstate/no_turbo

# cpupower kullanarak (rt-tests paketinde bulunur)
cpupower frequency-set -g performance

05 IRQ affinity ve CPU isolation

RT task'ların çalıştığı CPU çekirdeklerini sistem kesmelerinden izole etmek, en etkili latency azaltma tekniklerinden biridir.

Kernel boot parametreleri

/boot/grub/grub.cfg veya extlinux.conf — kernel cmdline
# CPU 2 ve 3'ü izole et:
# isolcpus=    → Bu CPU'ları scheduler'dan çıkar
# rcu_nocbs=   → RCU callback'lerini bu CPU'lardan taşı
# nohz_full=   → Tick'siz mod (1 Hz'den az interrupt)
# kthread_cpus → Kernel thread'lerini bu CPU'lardan uzak tut

GRUB_CMDLINE_LINUX="isolcpus=2,3 rcu_nocbs=2,3 nohz_full=2,3 \
  kthread_cpus=0,1 irqaffinity=0,1 \
  processor.max_cstate=1 idle=poll"

IRQ affinity ayarı

bash — IRQ affinity yapılandırması
# irqbalance'ı durdur (otomatik IRQ dağıtımı RT'ye zararlı)
systemctl stop irqbalance
systemctl disable irqbalance

# Mevcut IRQ'ları listele
cat /proc/interrupts | head -20

# Belirli IRQ'yu CPU 0,1'e bağla (hexadecimal CPU mask)
# CPU 0 → mask 0x1, CPU 1 → mask 0x2, CPU 0+1 → mask 0x3
IRQ_NUM=24  # ör. ağ kartı IRQ'su
echo 3 > /proc/irq/${IRQ_NUM}/smp_affinity

# İnsan okunabilir liste formatı
echo 0,1 > /proc/irq/${IRQ_NUM}/smp_affinity_list

# Tüm IRQ'ları CPU 0,1'e toplu taşı
for irq in /proc/irq/*/smp_affinity_list; do
  echo 0,1 > $irq 2>/dev/null || true
done

RT task'ı izole CPU'ya bağlama

bash — RT task CPU affinity ve öncelik
# cyclictest'i izole CPU 2,3'te SCHED_FIFO prio 99 ile çalıştır
taskset -c 2,3 cyclictest -p 99 -t 2 -a 2,3 -D 60m -h 400

# Mevcut bir sürece CPU affinity ata
taskset -c 2,3 -p $PID

# SCHED_FIFO önceliği ata
chrt -f 80 -p $PID

# Doğrulama
grep Cpus_allowed_list /proc/$PID/status
chrt -p $PID

cgroup ile CPU izolasyonu

bash — cgroup v2 CPU izolasyonu
# RT görevler için özel cgroup oluştur
mkdir -p /sys/fs/cgroup/rt-tasks

# CPU partition olarak işaretle
echo isolated > /sys/fs/cgroup/rt-tasks/cpuset.cpus.partition
echo 2,3 > /sys/fs/cgroup/rt-tasks/cpuset.cpus

# RT görevini bu cgroup'a al
echo $PID > /sys/fs/cgroup/rt-tasks/cgroup.procs

06 stress-ng ile yük altında test

RT latency testleri yalnızca boşta değil, gerçekçi sistem yükü altında da yapılmalıdır. stress-ng, kontrollü yük senaryoları oluşturmak için idealdir.

stress-ng temel kullanımı

bash — stress-ng yük senaryoları
# CPU yükü (CPU 0,1 üzerinde — izole CPU'lara dokunma)
taskset -c 0,1 stress-ng --cpu 2 --timeout 60s &

# I/O yükü
taskset -c 0,1 stress-ng --io 4 --timeout 60s &

# VM yükü (bellek baskısı)
taskset -c 0,1 stress-ng --vm 2 --vm-bytes 512M --timeout 60s &

# Matrix (FPU yükü)
taskset -c 0,1 stress-ng --matrix 2 --timeout 60s &

# Kombinasyon: gerçekçi üretim benzeri yük
taskset -c 0,1 stress-ng \
  --cpu 2 --io 2 --vm 1 --vm-bytes 256M \
  --matrix 1 --timeout 300s &

STRESS_PID=$!
echo "Stress PID: $STRESS_PID"

Kombinasyon testi: cyclictest + stress-ng

bash — RT latency under load testi
#!/bin/bash
# rt-load-test.sh — Yük altında RT latency ölçümü

# 1. Ön hazırlık
sysctl -w kernel.sched_rt_runtime_us=-1
sysctl -w kernel.numa_balancing=0
for cpu in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor; do
  echo performance > $cpu 2>/dev/null || true
done

# 2. Yük başlat (CPU 0,1 üzerinde)
taskset -c 0,1 stress-ng \
  --cpu 2 --io 4 --vm 2 --vm-bytes 256M \
  --timeout 660s &
STRESS_PID=$!

# 3. Yükün oturması için bekle
sleep 5

# 4. cyclictest çalıştır (CPU 2,3 — izole)
cyclictest -p 99 -t 2 -a 2,3 \
  -D 600s -h 400 --json=/tmp/load-test.json -q

# 5. Stres'i durdur
kill $STRESS_PID 2>/dev/null

# 6. Sonuçları analiz et
echo "=== Yük altında RT Latency Sonuçları ==="
jq '.thread[] | "CPU\(.id): min=\(.min)µs avg=\(.avg)µs max=\(.max)µs"' \
  /tmp/load-test.json -r

Beklenen latency artışı

SenaryoBoşta max latencyYük altında max latency
CPU yükü (izole CPU'larda)~20 µs~25 µs (+%25)
CPU yükü (RT CPU'larda)~20 µs~200+ µs (kabul edilemez)
I/O yükü~20 µs~35 µs (+%75)
Bellek baskısı~20 µs~50 µs (TLB flush)

Bu tablo, CPU izolasyonunun neden kritik olduğunu net biçimde ortaya koyar. RT CPU'larda yük çalıştırmak latency'yi on katına çıkarabilirken, doğru izolasyonla yük etkisi minimum düzeyde tutulabilir.

07 Pratik: <50 µs Industrial Linux Tuning

Endüstriyel bir kontrol sistemi için <50 µs WCET hedefine ulaşmanın adım adım süreci. BIOS/UEFI ayarlarından kernel derlemeye, cmdline'dan runtime tuning'e.

Adım 1: BIOS/UEFI ayarları

BIOS AyarıHedef değerNeden
Hyper-Threading (SMT)DisableSibling thread interference önler
CPU C-statesC0 only (disable C1+)C-state exit latency'si ortadan kalkar
Turbo BoostDisableFrekans varyasyonu yok, öngörülebilir
NUMA interleavingDisableNUMA erişim sürprizleri önlenir
Legacy USB emulationDisableUSB SMI kaynağı ortadan kalkar
Power management (ACPI)High PerformanceP-state geçişi latency'ye neden olmaz

Adım 2: Kernel konfigürasyonu

Kconfig — RT kernel için kritik seçenekler
CONFIG_PREEMPT_RT=y                  # Full preemption
CONFIG_HZ_1000=y                     # 1 kHz timer (1 ms granülarite)
CONFIG_NO_HZ_FULL=y                  # Tickless mode
CONFIG_RCU_NOCB_CPU=y               # RCU callback offload
CONFIG_IRQ_FORCED_THREADING=y       # Tüm IRQ'ları thread yap

# Enerji tasarrufu özelliklerini kapat
# CONFIG_CPU_IDLE is not set
# CONFIG_CPU_FREQ is not set (alternatif: cpufreq-fixed)

# NUMA ve memory compaction
CONFIG_COMPACTION=n                  # Bellek compaction latency'si önler

Adım 3: Kernel cmdline

grub — Tam RT kernel cmdline
GRUB_CMDLINE_LINUX="
  isolcpus=2,3,4,5
  rcu_nocbs=2,3,4,5
  nohz_full=2,3,4,5
  kthread_cpus=0,1
  irqaffinity=0,1
  processor.max_cstate=0
  idle=poll
  intel_idle.max_cstate=0
  pcie_aspm=off
  audit=0
  nosoftlockup
  skew_tick=1
"

Adım 4: Runtime tuning scripti

bash — /usr/local/bin/rt-tune.sh
#!/bin/bash
# RT tuning — systemd servisi olarak boot'ta çalıştır

set -e

echo "[RT-TUNE] Kernel tunables ayarlanıyor..."
sysctl -w kernel.sched_rt_runtime_us=-1
sysctl -w kernel.numa_balancing=0
sysctl -w kernel.timer_migration=0
sysctl -w vm.swappiness=0

echo "[RT-TUNE] THP kapatılıyor..."
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag

echo "[RT-TUNE] CPU governor: performance..."
for gov in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor; do
  echo performance > $gov 2>/dev/null || true
done

echo "[RT-TUNE] irqbalance durduruluyor..."
systemctl stop irqbalance 2>/dev/null || true

echo "[RT-TUNE] IRQ affinity: CPU 0,1..."
for sma in /proc/irq/*/smp_affinity_list; do
  echo 0,1 > $sma 2>/dev/null || true
done

echo "[RT-TUNE] Tamamlandı."

Adım 5: Doğrulama ve kabul kriteri

bash — Tuning sonrası doğrulama
# 1 saatlik stres testi ile doğrulama
taskset -c 0,1 stress-ng --cpu 2 --io 4 --vm 2 \
  --vm-bytes 256M --timeout 3660s &

sleep 30  # Yükün oturması için bekle

cyclictest -p 99 -t 4 -a 2,3,4,5 \
  -D 3600s -h 400 --json=/tmp/rt-verify.json -q

# Kabul kriteri: max latency < 50 µs
MAX_US=$(jq '[.thread[].max] | max' /tmp/rt-verify.json)
echo "Global MAX latency: ${MAX_US} µs"

if [ "$MAX_US" -lt 50 ]; then
  echo "PASS: < 50 µs hedefi karşılandı"
else
  echo "FAIL: Hedef aşıldı — daha fazla tuning gerekiyor"
  exit 1
fi
Not

<50 µs hedefine ulaşmak mümkün olmadığında önce hwlatdetect ile SMI kaynaklı spike'lar kontrol edilmelidir. SMI latency'si donanım ve BIOS'a özgü olduğundan yazılım optimizasyonuyla çözülemez; farklı donanım tercih edilmesi gerekebilir.