Kafayı yiyecektim! Şaka gibi ama, basit bir döngüde 10 milyon kere toplama yapan bir Python script'i yazdım. C'de yazdığım aynı mantıktaki kod, Python'un yanında ışık hızında kalıyordu. "Bu kadar basit bir işlemde bu fark nereden geliyor?" diye StackOverflow'da bile tam istediğim cevabı bulamadım, ta ki dilin temeline inene kadar.
Sorun Nerede Başlıyor?
Meğerse sorun, Python'un felsefesinde, "Her şey bir obje" prensibinde gizliymiş. C'de bir integer, hafızada sadece ham bir değer (örneğin 4 byte'lık bir alan). İşlemci direkt olarak onunla oynayabiliyor. Python'da ise 5 bile bir obje! Yani sadece değeri değil, tip bilgisi, referans sayacı gibi bir sürü ekstra bilgiyi de taşıyor.
Her basit a + b işleminde, Python interpreter'ı şunları yapıyor: Önce bu objelerin tiplerini kontrol et, uygun toplama metodunu bul (__add__), bellekten değerleri çek, işlemi yap, sonucu tutacak YENİ bir tane integer objesi oluştur ve onu döndür. C'de ise bu, birkaç assembly instruction'ına denk geliyor.
C Tarafındaki Sadelik
Karşılaştırma yapalım diye basit bir C kodu yazdım. Fark anında belli oluyor.
Burada result ve i, doğrudan bellek adreslerindeki (veya register'lardaki) sayılar. Toplama, işlemcinin doğal bir komutu. Hiçbir tip kontrolü, dinamik obje yaratma, çöp toplayıcıyı uyandırma yok. Bu yüzden de deli gibi hızlı.
Peki Bu, Python'u Kötü Mü Yapar?
Kesinlikle hayır! Bu bir trade-off. Python bize okunabilirlik, kolay yazım ve inanılmaz esneklik sunarken, bu gücü "soyutlama katmanı" pahasına veriyor. Günlük kullanımda, web sunucusu yazarken veya veri analizi yaparken bu farkı hissetmiyoruz çünkü asıl zamanı harcayan, ağ işlemleri veya NumPy gibi C ile yazılmış kütüphanelerin yaptığı işler oluyor.
Ama şunu anladım: Kritik bir performans döngüsü yazacaksan, ya o kısmı Cython ile yazacaksın, ya da NumPy'ın vektörleştirilmiş operasyonlarına güveneceksin. Saf Python, bu tür ham hesaplama işleri için değil.
Sonuç olarak, Python'da kod yazarken aslında sürekli bir "obje orkestrasyonu" yaptığımızı fark ettim. Bu yavaşlık, dilin doğasında var ve bu paha ödenerek bize çok daha büyük bir kolaylık sağlanıyor. Siz de bu farkı hissettiğiniz, "acaba neden?" diye düşündüğünüz anlar oldu mu? Ya da bu yavaşlığı aşmak için favori numaralarınız neler?
Meğerse sorun, Python'un felsefesinde, "Her şey bir obje" prensibinde gizliymiş. C'de bir integer, hafızada sadece ham bir değer (örneğin 4 byte'lık bir alan). İşlemci direkt olarak onunla oynayabiliyor. Python'da ise 5 bile bir obje! Yani sadece değeri değil, tip bilgisi, referans sayacı gibi bir sürü ekstra bilgiyi de taşıyor.
Python:
a = 5
# Arkada `PyObject` diye bir struct var, içinde:
# - obje tipi (int)
# - referans sayacı
# - değer (5)
Her basit a + b işleminde, Python interpreter'ı şunları yapıyor: Önce bu objelerin tiplerini kontrol et, uygun toplama metodunu bul (__add__), bellekten değerleri çek, işlemi yap, sonucu tutacak YENİ bir tane integer objesi oluştur ve onu döndür. C'de ise bu, birkaç assembly instruction'ına denk geliyor.
Karşılaştırma yapalım diye basit bir C kodu yazdım. Fark anında belli oluyor.
C:
int result = 0;
for (int i = 0; i < 10000000; i++) {
result += i; // İşlemci direkt bu değerler üzerinde çalışır.
}
Burada result ve i, doğrudan bellek adreslerindeki (veya register'lardaki) sayılar. Toplama, işlemcinin doğal bir komutu. Hiçbir tip kontrolü, dinamik obje yaratma, çöp toplayıcıyı uyandırma yok. Bu yüzden de deli gibi hızlı.
Kesinlikle hayır! Bu bir trade-off. Python bize okunabilirlik, kolay yazım ve inanılmaz esneklik sunarken, bu gücü "soyutlama katmanı" pahasına veriyor. Günlük kullanımda, web sunucusu yazarken veya veri analizi yaparken bu farkı hissetmiyoruz çünkü asıl zamanı harcayan, ağ işlemleri veya NumPy gibi C ile yazılmış kütüphanelerin yaptığı işler oluyor.
Ama şunu anladım: Kritik bir performans döngüsü yazacaksan, ya o kısmı Cython ile yazacaksın, ya da NumPy'ın vektörleştirilmiş operasyonlarına güveneceksin. Saf Python, bu tür ham hesaplama işleri için değil.
Sonuç olarak, Python'da kod yazarken aslında sürekli bir "obje orkestrasyonu" yaptığımızı fark ettim. Bu yavaşlık, dilin doğasında var ve bu paha ödenerek bize çok daha büyük bir kolaylık sağlanıyor. Siz de bu farkı hissettiğiniz, "acaba neden?" diye düşündüğünüz anlar oldu mu? Ya da bu yavaşlığı aşmak için favori numaralarınız neler?