Windows Resource Monitor ile Detaylı Performans Analizi
Bir üretim sunucusunda performans sorunu yaşandığında, ilk içgüdü genellikle Task Manager’ı açmak olur. CPU %90’da, bellek dolu, disk ışığı yanıp sönüyor. Ama Task Manager size sadece “ne kadar” tüketildiğini gösterir, “kim, neden ve nasıl” tüketiyor sorularına cevap vermez. İşte tam bu noktada Resource Monitor devreye girer ve çoğu Windows yöneticisinin sandığından çok daha güçlü bir araç olduğunu kanıtlar.
Resource Monitor Nedir ve Neden Task Manager Yetmez
Resource Monitor (resmon.exe), Windows Vista ile birlikte hayatımıza girdi ama gerçek olgunluğuna Windows Server 2008 R2 ile ulaştı. Task Manager’dan temel farkı şu: granüler, process bazlı, gerçek zamanlı veri sunar ve bu verileri birbiriyle ilişkilendirmenize olanak tanır.
Diyelim ki bir SQL Server instance’ınız var ve sunucu yavaşlıyor. Task Manager size sqlservr.exe’nin %70 CPU kullandığını söyler. Tamam, bunu biliyorduk zaten. Ama Resource Monitor size şunu söyler: bu process’in hangi thread’leri ne kadar CPU kullandığını, hangi dosyalara eriştiğini, hangi network bağlantılarını açık tuttuğunu ve fiziksel belleğin ne kadarını gerçekten kullandığını (working set vs commit size farkı burada kritik).
Resource Monitor’ü açmanın birkaç yolu var:
# Run dialog veya CMD'den
resmon.exe
# PowerShell'den
Start-Process resmon.exe
# Task Manager'dan: Performance sekmesi > "Open Resource Monitor" linki
# Windows Search
resmon
CPU Sekmesi: Sadece Yüzde Değil, Hikaye
CPU sekmesi açıldığında üst kısımda genel bir özet görürsünüz, ama asıl değer orta bölümde yatar. Her process için şunları görürsünüz:
- Image: Process adı
- PID: Process ID (bu kritik, aynı isimde birden fazla process olabilir)
- Description: Daha anlamlı bir açıklama
- Threads: Aktif thread sayısı
- CPU: Anlık CPU kullanımı
- Average CPU: Son 60 saniyenin ortalaması
“Average CPU” kolonuna dikkat edin. Bir process anlık olarak %0 gösterse bile average CPU %15 ise, o process sporadik ama yoğun burst’ler üretiyor demektir. Bunu Task Manager’da göremezsiniz.
Process’e Sağ Tıkladığınızda Gerçek Güç Açılır
Herhangi bir process’e sağ tıkladığınızda “Analyze Wait Chain” seçeneği çıkar. Bu özellik, bir process neden yanıt vermiyorsa, hangi başka process’i beklediğini gösterir. Klasik bir deadlock senaryosunu düşünün:
Bir müşteride IIS üzerinde çalışan bir .NET uygulamamız vardı. Uygulama periyodik olarak donuyor, worker process’ler birikiyor ve sonunda uygulama havuzu çöküyordu. Task Manager’da w3wp.exe’nin CPU kullanmadığını görüyorduk ama process’ler hayatta. Analyze Wait Chain’i açtığımızda, her w3wp.exe instance’ının bir named mutex beklediği ortaya çıktı. Kötü yazılmış bir lock mekanizması bütün thread havuzunu tıkıyordu.
Bellek Sekmesi: Working Set, Private ve Commit Arasındaki Fark
Bu sekme çoğu sysadmin’in en az anladığı yer. Ekrandaki kolonları tek tek ele alalım:
- Hard Faults/sec: Fiziksel RAM’de olmayan bir sayfanın diskten okunması gerekti. Bu sıfır ya da sıfıra çok yakın olmalı. Eğer sürekli yüksekse, sisteminiz swap kullanıyor demektir.
- Working Set: Process’in şu an aktif olarak kullandığı fiziksel RAM miktarı.
- Shareable: Diğer process’lerle paylaşılabilir bellek (örneğin DLL’ler).
- Private: Sadece bu process’e ait, paylaşılamaz bellek. Gerçek bellek tüketimini görmek için bu kolona bakın.
Bellek Sızıntısı Tespiti
Bir web sunucusunda zaman içinde artan bellek tüketimi şüphe uyandırıyorsa, Resource Monitor ile bunu izlemek için PowerShell’i kullanabiliriz:
# Belirli bir process'in working set'ini her 30 saniyede bir loglayalım
$processName = "w3wp"
$logFile = "C:Logsmemory_tracking.csv"
Add-Content $logFile "Timestamp,PID,WorkingSet_MB,Private_MB"
while ($true) {
Get-Process -Name $processName -ErrorAction SilentlyContinue | ForEach-Object {
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$ws = [math]::Round($_.WorkingSet64 / 1MB, 2)
$private = [math]::Round($_.PrivateMemorySize64 / 1MB, 2)
Add-Content $logFile "$timestamp,$($_.Id),$ws,$private"
}
Start-Sleep -Seconds 30
}
Bu scripti çalıştırıp CSV’yi Excel’de açtığınızda, private memory’nin lineer olarak artıp artmadığını görebilirsiniz. Artıyorsa bellek sızıntısı var demektir.
Fiziksel Bellek Dağılımı Grafiği
Resource Monitor’ün sağ alt köşesindeki “Physical Memory” grafiğine bakın. Oradaki renkler şunu ifade eder:
- Yeşil (In Use): Aktif olarak kullanılan RAM
- Mavi (Modified): Disk’e yazılmayı bekleyen, henüz temizlenmemiş sayfalar
- Sarı (Standby): Kullanılabilir ama henüz temizlenmemiş önbellek
- Koyu (Free): Gerçek anlamda boş, anında kullanılabilir RAM
Bir sistemde “Available” memory düşük görünse bile, Standby bellek yüksekse aslında sorun yoktur. Windows bu belleği yeni process’lere anında tahsis edebilir. Ama Modified bellek yüksekse ve disk I/O da yoğunsa, sistem swap yönetimi ile boğuşuyor olabilir.
Disk Sekmesi: I/O Darboğazlarını Yakalamak
Disk I/O analizi, Resource Monitor’ün en pratik kullanım alanlarından biri. Sekme açıldığında üç önemli bölüm var:
Disk Activity: Hangi process hangi dosyaya ne kadar okuma/yazma yapıyor. Storage: Disk bazında toplam aktivite.
Disk sekmesindeki kritik metrik Disk Queue Length‘dir. Bu değer sürekli 1’in üzerindeyse, diskler istek kuyruğuna giremeden tıkanıyor demektir. SSD’li sistemlerde bile bu değerin yüksek olması ciddi bir soruna işaret eder.
Gerçek Dünya Senaryosu: Gece Yarısı Disk I/O Fırtınası
Bir finansal kurumun sunucularında her gece 02:00-03:00 arasında sistem yavaşlıyor, backup job’ları zaman aşımına uğruyordu. Sabah geldiğimizde sorun geçmiş oluyordu. Task Manager logları elimizde yoktu ama bir sonraki gece için hazırlık yaptık.
Önce Performance Monitor ile bir Data Collector Set kurduk, sonra Resource Monitor’ün snapshot’larını almak için şu scripti bıraktık:
# Resource Monitor verilerini çekmek için WMI kullanımı
$startTime = "02:00:00"
$endTime = "03:00:00"
while ($true) {
$now = Get-Date -Format "HH:mm:ss"
if ($now -ge $startTime -and $now -le $endTime) {
$diskStats = Get-WmiObject -Class Win32_PerfFormattedData_PerfDisk_LogicalDisk |
Where-Object { $_.Name -ne "_Total" } |
Select-Object Name, DiskReadBytesPersec, DiskWriteBytesPersec,
AvgDiskQueueLength, PercentDiskTime
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$diskStats | ForEach-Object {
Write-Output "$timestamp | Drive: $($_.Name) | ReadMB/s: $([math]::Round($_.DiskReadBytesPersec/1MB,2)) | WriteMB/s: $([math]::Round($_.DiskWriteBytesPersec/1MB,2)) | Queue: $($_.AvgDiskQueueLength)" |
Add-Content "C:Logsdisk_audit.log"
}
}
Start-Sleep -Seconds 5
}
Sonuç ilginçti. Bir antivirus programı, backup agent’ı çalışırken tüm dosyaları gerçek zamanlı tarıyordu. Backup + antivirus I/O birleşimi diski felç ediyordu. Resource Monitor’ün disk activity bölümünden hem backup process’inin hem de antivirus process’inin aynı anda yüzlerce dosyaya eriştiğini gördük.
Network Sekmesi: Bağlantı Bazlı Trafik Analizi
Network sekmesi, güvenlik analistlerin de sık kullandığı bir alandır. Burada her process’in hangi remote adreslerle, hangi portlar üzerinden iletişim kurduğunu görebilirsiniz.
- Processes with Network Activity: Network kullanan her process
- Network Activity: Gerçek zamanlı send/receive değerleri
- TCP Connections: Aktif TCP bağlantıları, state’leri ve remote adresler
- Listening Ports: Hangi process hangi portu dinliyor
Şüpheli Network Aktivitesi Tespiti
Bir sunucuda olağandışı outbound trafik gördüğünüzde Resource Monitor’ün network sekmesi ilk bakacağınız yer olmalı. Şüpheli bir process fark ettiğinizde:
# Belirli bir PID'nin network bağlantılarını görmek
$pid = 4852 # şüpheli process'in PID'si
# netstat ile PID bazlı bağlantılar
netstat -ano | Where-Object { $_ -match "s$pid$" }
# Daha detaylı bilgi için
Get-NetTCPConnection | Where-Object { $_.OwningProcess -eq $pid } |
Select-Object LocalAddress, LocalPort, RemoteAddress, RemotePort, State |
Format-Table -AutoSize
# Tüm listening portları ve sahip process'leri listele
Get-NetTCPConnection -State Listen |
ForEach-Object {
$proc = Get-Process -Id $_.OwningProcess -ErrorAction SilentlyContinue
[PSCustomObject]@{
LocalPort = $_.LocalPort
ProcessName = $proc.Name
PID = $_.OwningProcess
Path = $proc.MainModule.FileName
}
} | Sort-Object LocalPort
Bu sorgu size sadece port dinleyen process’lerin adını değil, tam executable path’ini de verir. Meşru bir process mi, sahte bir isimle çalışan zararlı yazılım mı hemen ayırt edebilirsiniz.
Resource Monitor’ü Komut Satırından Kullanmak
Birçok sysadmin Resource Monitor’ün sadece GUI olduğunu düşünür. Oysa arka planda kullandığı veriler WMI ve Performance Counter üzerinden erişilebilir durumdadır.
CPU Kullanımını Komut Satırından İzleme
# Top 10 CPU tüketen process'i sürekli izle
while ($true) {
Clear-Host
Write-Host "=== CPU Top 10 - $(Get-Date -Format 'HH:mm:ss') ===" -ForegroundColor Cyan
Get-Process | Sort-Object CPU -Descending | Select-Object -First 10 |
Format-Table -Property Name, Id,
@{Name="CPU(s)"; Expression={[math]::Round($_.CPU, 2)}},
@{Name="Threads"; Expression={$_.Threads.Count}},
@{Name="WorkingSet(MB)"; Expression={[math]::Round($_.WorkingSet64/1MB, 2)}} -AutoSize
Start-Sleep -Seconds 3
}
Handle ve DLL Analizi
Resource Monitor’ün göstermediği ama tamamlayıcı olan bir analiz: hangi process hangi dosyayı kilitli tutuyor. Bu klasik “dosyayı silemiyorum, birisi kullanıyor” senaryosunda hayat kurtarır:
# Sysinternals Handle.exe ile dosya kilidi analizi
# (Handle.exe'nin PATH'te olduğunu varsayarak)
$targetFile = "C:Logsuygulama.log"
& handle.exe $targetFile
# Alternatif olarak OpenFiles komutu (sadece network share için çalışır)
openfiles /query /fo table | Where-Object { $_ -match "uygulama.log" }
# Belirli bir DLL'i hangi process'lerin yüklediğini bul
$dllName = "kernel32.dll"
Get-Process | ForEach-Object {
$proc = $_
try {
$modules = $proc.Modules | Where-Object { $_.ModuleName -like "*$dllName*" }
if ($modules) {
[PSCustomObject]@{
ProcessName = $proc.Name
PID = $proc.Id
DLLPath = ($modules | Select-Object -First 1).FileName
}
}
} catch { }
} | Where-Object { $_ -ne $null }
Data Collector Sets ile Resource Monitor Verilerini Kaydetmek
Resource Monitor gerçek zamanlı analiz için mükemmel ama geçmiş verileri saklamaz. Performans sorunlarını tarihsel olarak analiz etmek için Performance Monitor’ün Data Collector Sets özelliğini kullanın:
# Özel bir Data Collector Set oluştur
$dcName = "ProdServer_Baseline"
$outputPath = "C:PerfLogs$dcName"
# Temel sistem counter'larını topla
$counters = @(
"Processor(_Total)% Processor Time",
"MemoryAvailable MBytes",
"MemoryPages/sec",
"PhysicalDisk(_Total)Avg. Disk Queue Length",
"PhysicalDisk(_Total)Disk Bytes/sec",
"Network Interface(*)Bytes Total/sec",
"Process(*)% Processor Time",
"Process(*)Working Set",
"Process(*)Private Bytes"
)
# logman komutu ile Data Collector Set oluştur
$counterArgs = $counters | ForEach-Object { "-c `"$_`"" }
$command = "logman create counter $dcName -o `"$outputPath`" -f bincirc -max 512 -si 10 $($counterArgs -join ' ')"
Invoke-Expression $command
# Başlatmak için
logman start $dcName
# Durdurmak için
logman stop $dcName
Bu yöntemle topladığınız verileri daha sonra Performance Monitor’de açıp Resource Monitor görünümüne benzer bir analiz yapabilirsiniz. Özellikle “sorun geçtikten sonra inceleme” senaryolarında bu loglar paha biçilmezdir.
Pratik Sorun Giderme Akışı
Sunucu yavaşlıyor şikayeti geldiğinde izlediğim sıra şöyle:
İlk olarak Overview sekmesine bakıyorum. Hangi kaynak kırmızıya kaçmış? CPU mu, bellek mi, disk mi, network mi? Resource Monitor’ün üst bandındaki renk kodları hızlı bir triage yapmanızı sağlar.
CPU’da sorun varsa, CPU sekmesine geçiyorum ve “Average CPU” kolonuna göre sıralıyorum. Anlık spike’lar değil, ortalama yüksek olan process’e odaklanıyorum. Sağ tıklayıp “Analyze Wait Chain” deniyorum.
Bellek sorunuysa, Memory sekmesinde Hard Faults/sec’e bakıyorum. Sıfırın üzerindeyse swap kullanıyoruz demektir ve bu öncelikli sorun. Private bytes kolonunu takip ediyorum.
Disk sorunuysa, Disk sekmesinde en yüksek okuma/yazma yapan process’i buluyorum. Queue length’e bakıyorum. Sürekli yüksekse donanım sorunu olabilir, yoksa belirli bir process’in aşırı I/O yaptığı anlamına gelir.
Network sorunuysa, Network sekmesinde beklenmedik remote adresleri arıyorum. TCP Connections bölümünde ESTABLISHED bağlantı sayısına bakıyorum; olağandışı yüksekse connection leak veya DDoS olabilir.
Sonuç
Resource Monitor, Windows ekosisteminde fazlasıyla küçümsenen bir araç. Birçok ekip doğruca Perfmon’a ya da üçüncü parti monitoring çözümlerine atlıyor. Oysa Resource Monitor’ün sağladığı process-kaynak ilişkisi görünümü, anlık sorun gidermede bu araçların çoğundan daha hızlı sonuç verir.
Temel prensip şu: bir performans sorunu yaşandığında önce “ne tüketiyor” sorusunu sorun, sonra “neden tüketiyor” sorusuna geçin. Resource Monitor ilk soruya mükemmel cevap verir. PowerShell scriptlerini ve WMI sorgularını bu temelin üstüne inşa ettiğinizde, ikinci soruyu da çözebilecek kapasiteye ulaşırsınız.
Geceleri sizi uyandıran o sunucu alarmlarında, önce bir Resource Monitor açın. Çoğu zaman kök nedeni bulmak sandığınızdan çok daha az zaman alır.
