Blog
Mert Özen'in yazılım geliştirme, backend, frontend ve DevOps üzerine blog yazıları.
Scheduling: OS Hangi Thread'i Ne Zaman Çalıştırır? Context Switch, Priority ve Linux EEVDF
Scheduler, core'lardan fazla olan thread'leri kısa dilimlerle çalıştırır ve her geçişte bir context switch yapar; Linux bunu 6.6'dan beri EEVDF ile, nice ağırlıklarına göre adil paylaştırarak yapar. Context switch'leri /proc ile sayıyor, maliyetini ölçüyor, nice 10'un CPU'nun onda birini aldığını, Linux'ta Process.PriorityClass'ın yalnız ana thread'i etkilediğini ve --cpus=0.5 container'ında 31 periyodun 30'unda throttling olduğunu gösteriyoruz.
Memory'yi Process Gözüyle Okumak: mmap, Copy-on-Write, Shared Memory ve Container Memory Limit
Bir process belleği OS'tan mmap ve VirtualAlloc ile alır; dosyaya bağlı sayfalar process'ler arasında paylaşılır, yazıldığında copy-on-write ile kopyalanır ve container'da .NET GC, cgroup limitinin yüzde 75'ini heap sınırı yapar. 256 MB'lık container'da managed allocation'ın OOMKilled yerine 189. MB'ta yakalanabilir bir OutOfMemoryException verdiğini, paylaşılan bir dosyanın iki process'in RSS'inde iki kez sayıldığını ve DATAS'ın Server GC'nin belleğini 593 MB'tan 167 MB'a indirdiğini ölçüyoruz.
I/O Modelleri ve IPC: Blocking, Non-Blocking, epoll/kqueue/IOCP, Pipe ve Signal
await sırasında bekleyen bir thread yoktur: .NET, Linux'ta socket'leri epoll'a kaydeder ve tek bir .NET Sockets thread'i hepsini izler, Windows'ta aynı işi IOCP yapar. 1000 boşta bağlantının async'te 14, blocking'de 1014 OS thread'i tuttuğunu strace ile gösteriyor; Unix domain socket ve named pipe'ı deniyor ve shell ile başlatılan bir container'ın SIGTERM'i neden hiç almayıp 10 saniye sonra 137 ile öldüğünü ölçüyoruz.
Container'ı İşletim Sistemi Gözüyle Anlamak: Namespace, cgroup v2 ve "Container Sadece Bir Process'tir"
Container, namespace'lerle neyi göreceği ve cgroup'larla ne kadar kullanacağı sınırlanmış sıradan bir process'tir; host'un kernel'ini paylaşır. Container'da PID 1 olan dotnet'in host'ta 300861 numaralı bir process olduğunu, user namespace'in paylaşıldığını, .NET'in CPU ve bellek limitini cgroup'tan okuduğunu ve pids.max'a çarpan bir thread açılışının bellek boşken "Out of memory." ile çöktüğünü gösteriyoruz.