38 puan yazan GN⁺ 2026-01-02 | 1 yorum | WhatsApp'ta paylaş
  • Python’un işlem, bellek ve girdi/çıktı performans değerlerini sistematik olarak ölçen benchmark sonuçları; her işlemin süresi ve bellek kullanımını nicel olarak ortaya koyuyor
  • Hız açısından öznitelik erişimi 14ns, listeye ekleme 29ns, dosya açma 9μs, FastAPI yanıtı 8.6μs gibi çeşitli işlemlerin göreli gecikmeleri sunuluyor
  • Bellek açısından boş string 41 bayt, tamsayı 28 bayt, boş liste 56 bayt, boş sözlük 64 bayt, boş süreç 16MB gibi somut değerler veriliyor
  • Veri yapıları, serileştirme, asenkron işleme gibi alanlarda standart kütüphane ile alternatif kütüphaneler (orjson, msgspec vb.) arasındaki performans farkları karşılaştırılıyor
  • Temel çıkarımlar olarak Python nesnelerinin yüksek bellek ek yükü, dict/set’in hızlı sorgulaması, __slots__’un bellek tasarrufu etkisi ve asenkron işlemenin ek yükünü dikkate alma gereği vurgulanıyor

Genel bakış

  • Python geliştiricilerinin bilmesi gereken performans göstergelerini derleyen bir çalışma; işlem hızı ve bellek kullanımını gerçek ölçümlerle sunuyor
  • Benchmark’lar CPython 3.14.2, Mac Mini M4 Pro (ARM, 14 çekirdek, 24GB RAM) ortamında gerçekleştirildi
  • Sonuçlar göreli karşılaştırmaya odaklanıyor; kod ve veriler GitHub deposunda açık olarak paylaşılıyor

Bellek kullanımı (Memory Costs)

  • Boş bir Python süreci 15.73MB bellek kullanıyor
  • String’ler temel olarak 41 bayt, karakter başına ek 1 bayt kullanıyor
    • Örnek: boş string 41B, 100 karakterlik string 141B
  • Sayısal türler: küçük tamsayılar (0–256) 28B, büyük tamsayılar (1000) da 28B, çok büyük tamsayılar (10ⁱ⁰⁰) 72B, kayan noktalı sayı 24B
  • Koleksiyonların temel boyutu: liste 56B, sözlük 64B, küme 216B
    • 1.000 öğede liste 35.2KB, sözlük 63.4KB, küme 59.6KB
  • Sınıf örnekleri: normal sınıf (5 öznitelik) 694B, __slots__ kullanan sınıf 212B
    • 1.000 örnekte normal sınıf 165.2KB, __slots__ sınıfı 79.1KB

Temel işlemler (Basic Operations)

  • Aritmetik işlemler: tamsayı toplama 19ns, kayan noktalı toplama 18.4ns, tamsayı çarpma 19.4ns
  • String işlemleri: birleştirme 39.1ns, f-string 64.9ns, .format() 103ns, % biçimlendirme 89.8ns
  • Liste işlemleri: append() 28.7ns, liste üreteci/list comprehension (1.000 öğe) 9.45μs, aynı işlemin for döngüsü 11.9μs
    • List comprehension, for döngüsünden yaklaşık %26 daha hızlı

Koleksiyon erişimi ve yineleme (Collection Access and Iteration)

  • Anahtar/indeks erişimi: sözlük sorgulaması 21.9ns, kümede üyelik kontrolü 19ns, liste indeks erişimi 17.6ns
    • Liste üyelik kontrolü (1.000 öğe) 3.85μs ile set/sözlükten yaklaşık 200 kat daha yavaş
  • Uzunluk kontrolü: len() listede 18.8ns, sözlükte 17.6ns, kümede 18ns
  • Yineleme: liste (1.000 öğe) 7.87μs, sözlük 8.74μs, sum() 1.87μs

Sınıflar ve öznitelikler (Class and Object Attributes)

  • Öznitelik erişim hızı: hem normal sınıfta hem __slots__ sınıfında okuma 14.1ns, yazma yaklaşık 16ns
  • Diğer işlemler: @property okuma 19ns, getattr() 13.8ns, hasattr() 23.8ns
  • __slots__ kullanıldığında bellek tasarrufu etkisi 2 katın üzerinde, erişim hızı ise benzer seviyede

JSON ve serileştirme (JSON and Serialization)

  • Standart kütüphaneye kıyasla alternatif kütüphanelerin performansı
    • orjson, karmaşık nesnelerin serileştirilmesinde 310ns ile json’un 2.65μs değerinden 8 kattan fazla daha hızlı
    • msgspec 445ns, ujson ise 1.64μs
  • Deserileştirme tarafında da orjson 839ns ile en hızlısı
  • Pydantic: model_dump_json() 1.54μs, model_validate_json() 2.99μs

Web framework’leri (Web Frameworks)

  • Aynı JSON yanıtı için FastAPI 8.63μs, Starlette 8.01μs, Litestar 8.19μs, Flask 16.5μs, Django 18.1μs
  • FastAPI’nin yanıt süresi Django’dan yaklaşık 2 kat daha hızlı

Dosya girdi/çıktısı (File I/O)

  • Dosya açma-kapama 9.05μs, 1KB okuma 10μs, 1MB okuma 33.6μs
  • Yazma: 1KB 35.1μs, 1MB 207μs
  • Pickle, hem serileştirme hem deserileştirmede json’dan yaklaşık 2 kat hızlı (pickle.dumps() 1.3μs, json.dumps() 2.72μs)

Veritabanı ve kalıcılık (Database and Persistence)

  • SQLite: insert 192μs, select 3.57μs, update 5.22μs
  • diskcache: set 23.9μs, get 4.25μs
  • MongoDB: insert 119μs, find_one 121μs
  • Okuma hızında SQLite en hızlısı; yazma performansında ise diskcache öne çıkıyor

Fonksiyon çağrıları ve istisnalar (Function and Call Overhead)

  • Fonksiyon çağrısı: boş fonksiyon 22.4ns, metot 23.3ns, lambda 19.7ns
  • İstisna yönetimi: try/except (normal akış) 21.5ns, istisna oluştuğunda 139ns
  • Tür kontrolü: isinstance() 18.3ns, type() karşılaştırması 21.8ns

Asenkron ek yükü (Async Overhead)

  • Coroutine oluşturma 47ns, run_until_complete 27.6μs
  • asyncio.sleep(0) 39.4μs, gather(10 coroutines) 55μs
  • Senkron fonksiyon çağrısına (20ns) kıyasla asenkron çalıştırma (28μs) yaklaşık 1.000 kat daha yavaş

Temel çıkarımlar (Key Takeaways)

  • Python nesnelerinin bellek ek yükü büyüktür; boş bir liste bile 56 bayt kullanır
  • Sözlük/küme sorgulamaları, liste taramasından yüzlerce kat daha hızlıdır
  • orjson, msgspec gibi alternatif JSON kütüphaneleri standart çözümlerden 3–8 kat daha hızlıdır
  • Asenkron işleme yüksek ek yüke sahip olduğundan yalnızca paralellik gerektiğinde kullanılması önerilir
  • __slots__, performansta neredeyse kayıp olmadan belleği yarının altına indirebilir

1 yorum

 
GN⁺ 2026-01-02
Hacker News yorumları
  • Birçok kişi, “Python'da gecikme (latency) değerlerini dert etmeniz gerekiyorsa başka bir dil kullanmalısınız” diyor ama ben buna katılmıyorum
    Instagram, Dropbox, OpenAI gibi büyük ölçekli kod tabanları da Python ile büyüdü. Sonunda performans sorunlarıyla karşılaşıyorsunuz ve başka bir dile taşımadan bunları Python içinde çözebilme becerisi önemli.
    Performans sorunlarının çoğu dilin sınırlarından değil, verimsiz koddan kaynaklanıyor. Örneğin gereksiz yere fonksiyon çağrısını 10 bin kez tekrarlayan bir döngü gibi.
    Hazırladığım Python latency quiz de faydalı olabilir

    • Python ile yazılmış sistemlerin performans optimizasyonundan sorumluyum. Ama bu tür sayılar, gerçekten sorun olana kadar anlamlı değil. Sorun çıktığında doğrudan ölçerim. Metot çağrısından tasarruf etmeye çalışarak kod yazarsanız Python'ın avantajlarını kaybedersiniz
    • Python en temel işlemlerde bile yavaş. Fonksiyon çağrısı ya da sözlük erişimi gibi basit işlerde de yavaş. Aslında Python'ın ayakta kalmasının nedeni C/C++ tabanlı kütüphaneler (Numpy vb.)
    • Bu tür sayılar sadece Python'a özgü değil. Zig'de de CPU cycle ya da cache miss hesaba katılıyor. Her dilde belirli işlemlerin gecikmesi vardır. Python kullanmamak için nedenler olabilir ama bu onlardan biri değil
    • Bazı işlemler alternatif modüller kullanılarak iyileştirilebilir. Bu tür bilgileri bilmek önemli ama gerçekten ihtiyacı olanlar zaten biliyordur. Yine de Python prototipleme için harika bir dil
    • Bizim build sistemimiz de Python ile yazılmış durumda, bu yüzden performansı iyileştirirken Python'ı korumak istiyorum. Bu nedenle bu sayılar çok önemli
  • Paradoksal olarak, bu tür sayıların önemli hale geldiği anda Python o iş için uygun araç değildir

    • Python kodunu koruyup çekirdek performans kısımlarını yalnızca C veya Rust eklentilerine indirmek gerçekçi bir yaklaşım. numpy, pandas, PyTorch bunu yapıyor.
      Pratikte önemli olan, kodu enstrümante edip (pyspy gibi araçlarla) darboğazları bulmak. Listeye eleman ekleme hızını dert edecek seviyedeyseniz, o işlemi Python'da yapmamalısınız
    • 20 yıldır Python ile çalışıyorum ama bu sayıları bilmem hiç gerekmedi. Onun yerine profiling ve Cython, SWIG, JIT gibi araçlarla çözdüm
    • Bu tür sayıların önemli olacağı kadar hassas uygulamalarda Python bence fazla yüksek seviyeli bir dil, dolayısıyla optimize etmesi zor
    • Ama Python ile büyük ölçekli veri pipeline'ları kurdum. turbodbc + pandas kombinasyonuyla C++ seviyesinde hız elde ediyorum. Bellek daha fazla kullanılıyor ama personel maliyetini düşününce çok daha verimli.
      Python ile C arasındaki birlikte çalışabilirlik sayesinde bu yaklaşım mümkün. Zig de giderek daha iyi hale geliyor. Python ile uçak kontrol etmem ama kaynak farkındalığı yine de önemli
    • Bu tür sayılar son çaredir. Disk I/O, ağ, algoritmik karmaşıklık gibi genel darboğazları çözdükten sonra ancak düşünülmeli
  • Boş bir string'in kaç byte tuttuğunu bilmenin pek anlamı yok. Önemli olan zaman ve alan karmaşıklığını anlamak.
    int'in 28 byte olduğunu bilmektense, programın performans gereksinimlerini karşılayıp karşılamadığını değerlendirmek ve karşılamıyorsa daha iyi bir algoritma bulmak daha önemli

    • Ama performans her zaman sızdıran bir soyutlamadır. Farkında olsak da olmasak da kodun tamamını etkiler.
      Örneğin string birleştirmenin O(n²) olması, Python'daki f-string tasarımını da etkiler.
      Sözlüklerin hızlı olması nedeniyle Python genelinde yaygın biçimde kullanılmaları da aynı bağlamda değerlendirilebilir.
      Bu tür sayılar, o örtük bilgiyi sayısal olarak gerekçelendirme işlevi görüyor
    • int'in 28 byte olması, çok sayıda nesne üretmek gereken problemlerde gerçekten önemlidir.
      Eric Raymond'ın Reposurgeon ile GCC'yi migrate ederken yaşadığı sorunları anlattığı yazıyı hatırlatıyor
  • Başlık kafa karıştırıcı ama aslında Jeff Dean'in 2012 tarihli “Latency Numbers Every Programmer Should Know” makalesine bir gönderme.
    Bu tür başlık oyunları CS makalelerinde yaygındır

    • “latency numbers considered harmful is all you need” başlıklı bir makale yazılsa akademide patlama yapardı herhalde
    • Ama bu yazının yazarı bunu ciddi biçimde yazmış gibi görünüyor. Okurların başlığı yanlış anlaması söz konusu değil
    • Başlığın geçerli olabilmesi için sayıların gerçekten yararlı olması gerekir ama burada fazla çoklar ve pratik değiller
    • Bu arada Jeff Dean'in orijinal metni muhtemelen 2012'den çok daha önce yazılmıştı.
      Google'ın ilk dönem arama motorunda RAM vs Disk tasarımı için hazırlanmış dahili bir materyaldi.
      Sonrasında flash belleklerin ortaya çıkmasıyla sayılar değişti ve Jeff'in genom verisini doğrudan flash üzerinden servis edebilmek için sıkıştırma algoritmaları geliştirdiğine dair bir anekdot da var
  • Python geliştiricilerinin çoğu, bu tür düşük seviye performans ayrıntılarından daha önemli işlere odaklanmalı.
    Bu tür materyaller referans olarak iyi ama pratikte nadiren gerekli

    • Ama kullandığınız araçlarla ilgili genel bilgi her zaman değerlidir. Zihinsel birikimin parçasıdır ve bazı durumlarda çok işe yarar
    • Sınırlarla karşılaşıldığında C ile yazılmış modüller bulunabilir ya da doğrudan yazılabilir. Python zaten baştan beri böyle gelişti
    • Ben de çoğu durumda “yeterince hızlı” hissiyle çalıştım. Bu materyal, o hissi rakamlarla doğrulamamı sağladı
  • String boyutu açıklaması hatalı. Python'da karakter başına 1, 2 veya 4 byte kullanan üç tür string tipi var
    Ayrıntılar için bu bloga bakılabilir

  • Yazının başlığı ve örnekleri biraz isabetsiz.
    Örneğin “item in set, item in list'ten 200 kat daha hızlıdır” ifadesi membership test ile ilgili; iteration hızının karşılaştırılması değil.
    Buna rağmen genel olarak biçimi ve kurgusu çekici

  • Sınıf instance'ı oluşturma süresinin ölçümü eksik.
    Ben kod refactor ettikten sonra basit bir liste yapısını sınıfa çevirdim ve çalışma süresi birkaç mikrosaniyeden birkaç saniyeye çıktı.
    Böyle durumların da ölçülmesini isterdim

    • Doktora “Bunu yapınca canım yanıyor” deyince “O zaman yapmayın” demesiyle ilgili şakayı hatırlattı.
      Sorun sınıfların aşırı kullanımı olabilir. Bazı durumlarda basit liste yapıları daha iyi olabilir
    • Sınıf instance'ı oluşturmanın kendisi genelde performans sorunu değildir.
      Daha çok nesne yönelimli yaklaşımın yanlış kullanılmış olma ihtimali vardır.
      Kodu StackOverflow ya da CodeReview.SE'ye koyup geri bildirim almak iyi olabilir
  • Bu yazıyı, “modern Python'da temelde yanlış giden bir şey mi var” bakış açısından ilgi çekici buldum.
    Ama bu sayıların “herkes tarafından bilinmesi gerektiği” iddiasına katılmıyorum.
    Birkaç temel işlem için sezgisel bir fikir sahibi olmak yeterli

  • Python'daki small int cache aralığı 0~256 değil, -5~256'dır.
    Bu yüzden özdeşlik (is) ile eşitliği (==) karıştıran yeni başlayanlar sık sık kafası karışıyor

    • Java da benzer davranıyor. Yeni başlayanlar için kafa karıştırıcı olabilir