Birden fazla thread aynı veriye, dosyaya veya bağlantıya aynı anda ulaşmak istediğinde küçük bir trafik kaosu doğar. Bu kaosu yönetmek için kullanılan en temel araçlardan ikisi mutex ve semaphore’dur. İkisi de erişimi sınırlar; ancak mutex tek anahtarlı bir oda kapısı gibi davranırken semaphore belirli sayıda araç kabul eden bir otoparka benzer.

Devamı...
Bilgisayarınızda müzik çalarken kod derleyebiliyor, tarayıcıda sekmeler arasında dolaşabiliyor ve arka planda dosya indirebiliyorsanız bunu CPU’nun gizli trafik polisi olan process scheduler’a borçlusunuz. İşlemci aynı anda sınırlı sayıda işi yürütebildiği için scheduler, hazır durumdaki process’lerden hangisinin ne zaman ve ne kadar süre çalışacağını belirler. Kısacası soru şudur: CPU zamanını kim hak ediyor?

Devamı...
Bir CPU’nun aynı anda birden fazla komut çalıştırdığını duyduğumuzda, işlemcinin düzinelerce eli olan bir robot gibi davrandığını düşünebiliriz. Gerçekteyse pipelining, tek bir işi parçalara ayırıp farklı komutların farklı parçalarını eş zamanlı yürütme tekniğidir. Bir otomobil fabrikasında bir araç boyanırken diğerinin motorunun takılması gibi, işlemci de bir komutu çözerken sıradaki komutu bellekten getirebilir.
Devamı...
Bir programdaki komutlar belirli bir sırayla yazılır; fakat modern işlemciler bu sıraya harfiyen uymak zorunda değildir. Sonuç değişmediği sürece hazır olan komutları erkenden çalıştırabilirler. Out-of-order execution, yani sıra dışı yürütme, işlemcinin boş boş beklemek yerine komutlar arasında küçük bir lojistik operasyon yürütmesidir.

Devamı...
Modern bir sunucuda bütün RAM modülleri aynı anakarta takılı olsa da işlemci çekirdekleri açısından eşit uzaklıkta değildir. NUMA, yani Non-Uniform Memory Access, tam olarak bu gerçeği ifade eder: Bir çekirdeğin bazı bellek bölgelerine erişimi hızlı ve ucuzken diğerlerine erişimi daha yavaş olabilir. Kısacası RAM ortak görünür, fakat ona giden yolların uzunluğu aynı değildir.
Devamı...
Bir program bellekteki 0x7FFF1234 adresine eriştiğinde CPU doğrudan RAM’in o noktasına koşmaz. Çünkü programın gördüğü adres, çoğunlukla fiziksel bir konum değil, işletim sistemi tarafından oluşturulmuş sanal bir adrestir. CPU içindeki Bellek Yönetim Birimi (MMU) bu adresi tercüme ederek gerçek RAM konumunu bulur. Kısacası MMU, belleğin simultane tercümanıdır; üstelik yanlış çeviri yaparsa program değil, bütün sistem homurdanabilir.
Devamı...
Büyük bir dosyanın içeriğine erişmek için genellikle read() çağrıları, tamponlar ve döngüler düşünürüz. Memory-mapped file yaklaşımıysa dosyanın belirli bir bölümünü sürecin sanal adres alanına bağlar. Böylece program, dosyayı gerçekten RAM’e bütünüyle yüklemeden ona sıradan bir bellek dizisiymiş gibi erişebilir. İşin arkasındaki sihir değil; sanal bellek, sayfa tabloları ve işletim sisteminin sayfa önbelleğidir.
Devamı...
Bir program çalışırken ihtiyaç duyduğu bütün sayfalar fiziksel belleğe sığmayabilir. İşletim sistemi bu durumda disk ile RAM arasında küçük bir sandalye kapmaca oyunu oynar: Yeni sayfa gelecek, fakat boş çerçeve yoksa içerideki sayfalardan biri çıkarılmalıdır. Peki kurban kim olacak? LRU, LFU ve CLOCK algoritmaları aynı soruya farklı ipuçlarıyla cevap verir.
Devamı...

Bilgisayarınızın işlemcisi milyonlarca komutu yürütürken klavyede bir tuşa bastığınızı nasıl fark eder? İşlemcinin sürekli “Klavye hazır mı, ağdan veri geldi mi?” diye sorması mümkün olsa da oldukça verimsizdir. Interrupt, yani kesme sistemi, donanımın işlemciye nazikçe değil, adeta omzuna dokunarak “Önemli bir olay oldu!” demesini sağlar.
Devamı...
Bir diskten belleğe megabaytlarca veri aktarırken işlemcinin her baytı tek tek taşıdığını düşünün. Bu, kargo şirketinin yöneticisinin kamyonu bırakıp bütün kutuları kendisinin taşımasına benzerdi. Direct Memory Access (DMA), veri aktarımını özel bir denetleyiciye devrederek işlemciyi asıl işi olan komut yürütme için serbest bırakır. Ancak işlemci tamamen devre dışı kalmaz; aktarımı başlatır, sonucunu takip eder ve gerektiğinde hatalarla ilgilenir.

Devamı...
Bir restoranda iki aşçı düşünün: Birinin tava, diğerinin bıçak tuttuğunu; fakat ikisinin de yemeği tamamlamak için diğer araç gerece ihtiyaç duyduğunu hayal edin. Kimse elindekini bırakmazsa mutfak sonsuza kadar bekler. İşletim sistemlerinde bu tatsız tabloya deadlock, yani kilitlenme denir.
Devamı...
Bir nesnenin kopyasını çıkarmak çoğu zaman masum görünür: bellekte yeni bir alan ayır, verileri taşı ve devam et. Ancak yüzlerce megabaytlık verilerle çalışıyorsak bu işlem hem zaman hem bellek tüketir. Copy-on-Write, kısaca CoW, “Gerçekten değiştirmeyeceksen neden kopyalıyorsun?” diyerek iki kopyanın aynı belleği geçici olarak paylaşmasını sağlar.
Devamı...
Bir thread’in sürekli “Hazır mı? Hazır mı? Şimdi hazır mı?” diye kontrol yapması, işlemciyi gereksiz yere meşgul eden dijital bir sabırsızlıktır. Condition variable, thread’lerin belirli bir koşul gerçekleşene kadar verimli biçimde uyumasını ve koşul değiştiğinde yeniden çalışmasını sağlayan bir senkronizasyon aracıdır.
Devamı...

Modern bir CPU, yalnızca komutları çalıştıran hızlı bir hesap makinesi değildir; aynı zamanda geleceği tahmin etmeye çalışan minik bir falcıdır. Programdaki if, switch ve döngü koşulları işlem akışını değiştirdiğinde CPU, sonucun hesaplanmasını beklemek yerine hangi yolun izleneceğini tahmin eder. Bu mekanizmaya branch prediction, yani dallanma tahmini denir.
Devamı...
Bir C fonksiyonunu Rust’tan çağırdığınızda ya da işletim sistemi derlenmiş programınızı çalıştırdığında taraflar kaynak kodu tartışmaz. Bunun yerine; parametrelerin nereye konacağı, sonuçların nasıl döndürüleceği ve belleğin nasıl düzenleneceği gibi önceden belirlenmiş kurallara uyarlar. İşte bu görünmez anlaşmanın adı ABI, yani Application Binary Interface’tir.
Devamı...

İkili arama ağaçları hızlıdır; tabii ağaç bir bambu dalına dönüşmediği sürece! Sıralı veriler sıradan bir ikili arama ağacına eklendiğinde yapı doğrusal bir liste gibi uzayabilir. Treap, bu sorunu katı dengeleme kuralları yerine rastgelelik kullanarak çözer. İsmi de iki yapının birleşiminden gelir: tree ve heap. Sonuç, şaşırtıcı derecede basit ama beklenen performansı oldukça güçlü bir veri yapısıdır.
Devamı...
Tip sistemleri, programlarımızın hangi değerlerle hangi işlemleri yapabileceğini belirleyen görünmez trafik kurallarıdır. İlk bakışta yalnızca “bu değişken sayı mı, metin mi?” sorusuyla ilgileniyor gibi görünürler. Oysa weak typing’den dependent type’lara uzanan yolculuk; hataları ne zaman yakaladığımızı, kod hakkında neleri kanıtlayabildiğimizi ve derleyiciye ne kadar sorumluluk verdiğimizi anlatır.
Devamı...
Elimizde uzun bir metin olduğunu ve bu metindeki bütün bitişik alt dizeleri saklamak istediğimizi düşünelim. Uzunluğu $n$ olan bir metin, en fazla $n(n+1)/2$ farklı konum aralığı içerir. Hepsini ayrı ayrı depolamak karesel bir felakete dönüşebilir. Suffix Automaton, yani son ek otomatı, aynı bilgiyi yalnızca $O(n)$ durum ve geçişle temsil eden zarif bir veri yapısıdır.

Devamı...
Bir nesne kapıya geldiğinde tip sistemi ona iki farklı soru sorabilir: “Gerekli özelliklere sahip misin?” veya “Hangi sınıfa mensupsun?” Structural typing ilk soruyla, nominal typing ise ikinci soruyla ilgilenir. Bu ayrım yalnızca akademik bir sınıflandırma değildir; kodun yeniden kullanılabilirliğini, güvenliğini ve API tasarımını doğrudan etkiler.

Devamı...
Bir dizi üzerinde tekrar tekrar “şu aralıktaki en küçük eleman nedir?” diye sorulacağını, fakat dizinin hiçbir zaman değişmeyeceğini düşün. Her sorguda aralığı baştan sona dolaşmak gereksiz bir maraton olur. Sparse Table, biraz ön hazırlık yaparak minimum, maksimum ve EBOB gibi değişmeyen aralık sorgularını $O(1)$ sürede cevaplayan zarif bir veri yapısıdır.
Devamı...