Yapay zekadan makale özeti
- Kısa
- Ayrıntılı
- Bu video, Commensis'te Engineering Lead olarak çalışan ve kendisini "Code Jeter" olarak tanımlayan bir konuşmacının sunduğu eğitim sunumudur. Sunumda Uğur abi, Bilgem Çakır ve Suat gibi kişiler de yer almaktadır.
- Sunum, yazılımda yabancılaşma kavramından başlayarak programlama dillerinin performans yönetimi konusunu üç ana bölüme ayırarak ele almaktadır: memory allocation, memory management ve metod dispatching. İçerikte Swift, Java, C, C++, Ruby ve Python gibi farklı dillerin memory yönetimi yaklaşımları karşılaştırılmakta, value type ve reference type arasındaki farklar, stack ve heap memory'nin çalışma prensipleri, virtual memory kavramı ve memory allocation'un performans üzerindeki etkileri detaylı olarak açıklanmaktadır.
- Sunumda ayrıca statik ve dinamik dispatch, virtual function table, message dispatching, spekülatif execution, branch target buffer ve vectorization gibi optimizasyon teknikleri görsel örnekler ve kod örnekleri üzerinden anlatılmaktadır. Konuşmacı, fanboy olmaktan kaçınmanın, teoriyi anlamadan ezbere savunulan tezlere inanmamanın ve internet benchmarklarına güvenmemenin önemini vurgulamaktadır.
- Commensis ve Kişisel Tanıtım
- Konuşmacı Commensis'te engineering lead olarak çalışmaktadır.
- Commensis, Pozitron'un devamı olup, 2014 yılında sıfırdan başlayan bir start-up olarak İngiliz Monitise şirketine 100 milyon dolara satılmıştır.
- Monitise'nin global hedefleri birbirinden ayrılınca, Commensis markası adı altında yerli ve milli olarak devam etmeye karar verilmiştir.
- 00:44Code Jeter Tanımı
- Konuşmacı kendisini "code jeter" olarak tanımlamaktadır.
- Code jeter, hademe anlamına gelir ve projelerde gerçek featureları yapan değil, patlayan, çatlayan kısımları onaran, bir şeylerin arkasını toparlayan kişidir.
- Rock star developer kavramı gerçekçi değildir, farklı metriklerde bir developer diğerinden 10 kat, 100 kat daha hızlı kod yazabilir.
- 02:24Programlama Deneyimleri ve Deneyim Alanları
- Konuşmacı C++, Swift, Java, C, Objective C gibi farklı programlama dilleriyle çalışma fırsatı bulmuştur.
- Geçmişte savunma sanayi tecrübesi olmuş, T129 atak helikopteri projesi, denizaltı taktik simülatör projesi ve helikopter simülatör projesi (Helsim) gibi projelerde çalışmıştır.
- Finans tarafına geçtikten sonra İşcep, Cepteteb gibi projelerde çalışma imkanı bulmuştur.
- 03:09İlgi Alanları ve Hobiler
- Konuşmacının ilgi alanı, bir şey gördüğünde "bu nasıl çalışıyor?" sorusunu sormaktır.
- Compiler'lar, reverse engineering ve operating system internal'ları gibi konulara ilgi duymaktadır.
- Üniversite sonrası için meslek hayatında en az bir tane ciddi hobinin olması gerektiğini, meslek hayatı ve hobilerin sizi yutmaya uygun olduğunu belirtmektedir.
- 04:16Yabancılaşma Kavramı
- Felsefede yabancılaşma (alienation) kavramı vardır ve Hegel bu kavramı pozitif bir şey olarak değerlendirir.
- Marx'ın yabancılaşma tanımı emeğe ve insanın kendisine yabancılaşmasıdır.
- İnsanın kendi emeğine yabancılaşması, kendi insan olduğunu ve nasıl bir hayat yaşadığını belli aralıklarla sorgulaması gerektiğini vurgulamaktadır.
- 06:45Yazılımda Yabancılaşma
- Yazılımda yabancılaşma, abstractionlar (soyutlamalar) ile ilgilidir.
- Modern işlemci mimarisinde işletim sistemi üzerinde sanal makine, sanal makinenin üzerinde konteyner, konteynerin içinde tekrar işletim sistemi, uygulama sunucusu ve uygulama bulunur.
- Programlama dilleri ve framework'ler arasında sürekli tartışma ve polemikler yaşanmaktadır.
- 09:58Sunumun Genel İçeriği
- Sunumda programlama dillerinin performans yönetimi, memory allocation, memory management yöntemleri ve metod dispatching konuları ele alınacak.
- Sunumun orijinal 2 saat 20 dakikalık olması planlanırken, bugün 30-40 dakika civarında bitirilmesi hedefleniyor.
- Sunumun amacı, programlama dillerinin performans tarafını nasıl yönettiğini anlayarak, dilleri hurafelerle değil teorisi ve pratiği açısından değerlendirebilmek.
- 12:13Value Type ve Reference Type Farkları
- Swift'te value type'lar (struct'lar, inamlar, tapular, collection'lar, primitifler) ve reference type'lar (class'lar, function ve closu'lar) bulunur.
- Value type'lar kopyalandığında kopyası çıkarılırken, reference type'lar kopyalandığında referansı kopyalanır.
- Value type'lar için deep copy, reference type'lar için shallow copy denir; value type'lar immutable için iyi bir pratikken, reference type'lar programlama pratikleri açısından un safe olabilir.
- 14:02Memory'nin Hikayesi
- Bir programın execution'ı main fonksiyonundan başlar ve stack'te memory allocation işlemleri compile time'da belirlenir.
- Heap'te memory allocation işlemleri runtime'da dinamik olarak yapılır ve out of memory exception riski vardır.
- Her thread'in kendine ait stack'i varken, heap ortak kullanılan bir alan olarak kullanılır.
- 16:01Memory Allocation Süreci
- İşletim sistemi, fiziksel bellek için virtual memory kullanır ve bu virtual memory gerçek fiziksel bellek ile bir translationdan geçer.
- C'nin malloc fonksiyonu, Windows API'nin virtual memory allock fonksiyonunu çağırır ancak kendi optimizasyonları sayesinde daha hızlı çalışır.
- Modern programlama dillerinin runtime'ları (JVM, .NET Common Language Runtime, Go, Swift) memory allocation işlemlerini kendilerine göre yönetir.
- 18:56Value Type ve Reference Type Performans Karşılaştırması
- Value type'lar stack'te yer alır ve her thread'in kendi stack'i olduğu için senkronizasyon gerekmez, compile time'da belirlenmiş işlemlerdir.
- Value type'lar kopyalandığında kopyası çıkarılırken, referans type'lar kopyalandığında referansı kopyalanır.
- Heap'te memory allocation için maliyetler vardır ve referans type'lar için de benzer maliyetler mevcuttur.
- 20:30Value Type ve Reference Type Performans Karşılaştırması
- Value type'ların olmadığı dillerde (C, C++, Swift, Ruby, Python, Java) stack'ten yararlanma özgürlüğü kaybedilir.
- Value type'lar allocation için daha hızlıdır çünkü stack pointer'ı decrement edildiğinde otomatik olarak alan alınır.
- Performans için statik allocation'ı dynamic allocation'a tercih etmek gerekir, özellikle otomotiv endüstrisinde dinamik lokasyon yasaklanmıştır.
- 22:06Memory Erişim ve Cache Optimizasyonu
- İşlemcinin cache'i başta küçük bir alan alır ve level 1, level 2, level 3 şeklinde büyüyerek memory erişimini optimize eder.
- Memory erişiminde iki pattern vardır: aynı dataya tekrar erişim ve datanın yakınındaki datalara erişim.
- Data oriented design'ın en büyük amacı, memory erişiminde bir şeye eriştiğimizde yanındakine de erişiriz şeklinde datayı tasarlamaktır.
- 23:25Swift'in Array Özel Durumu
- Swift'in array'i değer tipi olarak davranır ancak arka planda referans tipi kullanır.
- Copy on write optimizasyonu sayesinde, değişmemesi gereken değerler sürekli kopyalanmaz, sadece değiştiğinde kopyalama yapılır.
- Bu optimizasyon Unix'ten beri kullanılmaktadır ve C++, Swift gibi dillerde mevcuttur.
- 24:51Memory Management Yöntemleri
- Manuel memory management (C gibi dillerde) insan beyni için zor olabilir, ancak objelerin sahibinin kim olduğunu ve life cycle'ını bilmek yazılım tasarımı açısından önemlidir.
- Otomatik memory management (reference counting ve garbage collection) yöntemleri vardır.
- Reference counting, Apple'ın Cocoa framework'leri için birincil memory management yöntemidir ve C++, Delphi, PHP, Python, Pearl gibi dillerde kullanılır.
- 26:25Reference Counting
- Reference counting'de obje yaratıldığında referans count'u 1 olur, başka bir referansa atandığında count artar, referanslar null'a set edildiğinde count azalır.
- Referans count sıfıra düştüğünde obje dealloc edilebilir, bu işlem sistem tarafından otomatik yapılır.
- Referans counting'in dezavantajı objelerin birbirine referans tutması durumunda count'un azalmaması ve bu durumun memory leak yaratabilmesidir.
- 28:05Value Type'larda Reference Counting
- Value type'larda reference counting yoktur, bu da değer tipi kullanabildiğiniz diller için önemli bir avantajdır.
- Referans count'u arttırırken veya azaltırken senkronizasyon yapılması gerekir, bu da performans kaybına neden olabilir.
- Fonksiyonlara obje geçirildiğinde referans count'u artar, fonksiyon çıkışında ise temizlenir, ancak compiler'lar escape analizi yaparak bu işlemi optimize edebilir.
- 29:45Garbage Collection
- Garbage collection, C, Java, Go gibi dillerde kullanılan bir yöntemdir.
- Garbage collector, stack'i tarayıp hangi objelere referans var diye bakar ve kimsenin referansı olmayan objeleri siler.
- Garbage collector, free memory'yi kaydırarak cache'in verimli kullanılabilmesi için memory'de bir şeylerin yan yana durmasını sağlar, ancak bu işlemi yaparken uygulamanın durması gerekebilir.
- 30:42Garbage Collector ve Predictable Performans
- Numblocking garbage collector gibi farklı yöntemler var ancak piyasadaki çoğu implementasyon bunu halledemiyor.
- Garbage collector'ın ne zaman çalışacağı öngörülemiyor, bu da kodun predictable performansını ortadan kaldırıyor.
- 31:24Metod Dispatching
- Metod dispatching, bir metodun nasıl çağrılacağı tanımıdır; statik dispatching en basit haliyle bir fonksiyonun adresini çağırmaktır.
- C++'ın default'u statik dispatching'tir, virtual tanımlananlar dinamik dispatching'e geçer; Java gibi dillerde her şey dinamik dispatching'tir.
- Dinamik dispatching'de runtime'da virtual function table oluşturulur ve her fonksiyonun adresleri bu tabloda tutulur.
- 32:47Message Dispatching
- Message dispatching, dinamik dispatching'in bir alt şeklidir ve Objective-C, Ruby, Python gibi dillerde kullanılır.
- Runtime'da inheritance hiyerarşisine göre mesaj gönderilir ve metot bulunamazsa bir alta inilir.
- Bu özellik sayesinde Objective-C'de swisting, Ruby'de monkey patching gibi dinamik metod ekleme ve çıkarma işlemleri yapılabilir.
- 34:09Görsel Örnekler
- Dynamic dispatching örneğinde, parent class'da metodlar var ve child class'ta metodlar eklenebilir veya değiştirilebilir.
- Message dispatching örneğinde, metot bulunamazsa inheritance hiyerarşisine göre bir alta inilir.
- Polimorfizm, bir fonksiyonun diğerini ezip farklı şekillerde davranabilmesidir ve bu yöntem sayesinde dinamik metod ekleme ve çıkarma yapılabilir.
- 37:01Fonksiyon Çağrısının Yükü
- Fonksiyon çağırmanın bir yükü vardır ve bu yük performans için önemlidir.
- Fonksiyon çağrıldığında prolog (register'lardan değerlerin siteye okunduğu veya yazıldığı) ve epilog (clean-up'ın yapıldığı) kısımlar çalışır.
- Inline etme, fonksiyon çağrısının overhead'inden kurtulmayı sağlar ve executable'ın boyutunu azaltır.
- 40:34Performans ve Optimizasyon
- Polimorfik kodlar veya message dispatch gibi sistemlerde, hangi metodun çağrıldığı son ana kadar bilinmediği için işlemci memory'den gerekli alanları getiremez ve bu keşmis (cache miss) oluşmasına neden olur.
- C, C++, C kısmen ve Swift gibi dinamik-statik dispatch yapabilen diller optimizasyona daha açık ve hızlı çıktılar üretebilir.
- JVM ve Chrome'un V8 gibi optimizasyonlar, hangi metodun çağrılacağını tahmin ederek spekülatif execution yaparak keşmis sorununu çözebilir.
- 42:14Spekülatif Execution ve Vectorization
- Spekülatif execution, if kontrolü gibi durumlarda sürekli true geleceğini tahmin ederek branch'i önceden çalıştırıp, false gelirse geriye dönerek toparlama yaparak performans kazanır.
- İşlemci üzerinde bu işlemi yapan kısmın adı branch target buffer'dur.
- Vectorization, tek bir komut yerine birden fazla komutu aynı anda çalıştırarak (single instruction multiple data - SMI) performansı artırır.
- 43:41Inline ve Dil Seçimi
- Inline edildiğinde compiler daha fazla şey görebilir ve referans kanunu gibi optimizasyonları daha kolay yapabilir.
- Diller, hardware ve operating system sadece abstractionlardır, yapacağınız işe en uygun olanı seçmelisiniz.
- Fanboy olmaktan, teoriyi anlamadan ezbere savunulan tezlere inanmaktan ve internet benchmarklarına güvenmekten kaçınmalısınız.
- 45:26Temellerden Yabancılaşma
- Temellerden kopup frameworklerin ve dillerin dünyasında kaybolmak performans konusunu anlamakta zorluk yaratabilir.
- Performans konusunu uçtan uca programlama dilleri açısından en temel prensipleri bilmeden tartışmak yanlış olabilir.