- Python paket yöneticisi uv, pip’e kıyasla 10 kattan daha hızlı kurulum hızı sunuyor; bunun nedeni yalnızca Rust ile yazılmış olması değil, tasarım tercihleri
- Bu hızı mümkün kılan temel unsur, statik metadata standartları (PEP 518, 517, 621, 658); bunlar kod çalıştırmadan bağımlılıkların anlaşılmasını sağlıyor
- uv, pip’in sürdürdüğü legacy özellikleri (.egg, pip.conf, sistem Python kurulumu vb.) cesurca kaldırarak gereksiz kod yollarını ortadan kaldırıyor
- Rust’ın katkı sağladığı alanlar zero-copy deserialization, locksuz eşzamanlılık, tek binary yapısı gibi noktalar; bunlar toplam hız artışının yalnızca bir kısmını oluşturuyor
- Genel olarak uv örneği, standartlaştırılmış metadata ile gereksiz uyumluluğun kaldırılmasının performans yeniliğinin anahtarı olduğunu gösteriyor
uv’nin hızını mümkün kılan standartlar
- pip’in yavaşlığı bir implementasyon sorunu değil; geçmişteki setup.py tabanlı yapı nedeniyle bağımlılıkları öğrenmek için kod çalıştırılması gereken mimariden kaynaklanıyor
setup.py çalıştırmak, build bağımlılıklarının kurulmasını gerektiriyordu; bu da “tavuk-yumurta problemi” yaratıyordu
- Kurulum sürecinde rastgele kod çalıştırma ve tekrarlanan hatalar yaşanıyor, bu da kurulum hızını düşürüyordu
- PEP 518 (2016),
pyproject.toml dosyasını tanıtarak kod çalıştırmadan build bağımlılıklarının bildirilebilmesini sağladı
- PEP 517 (2017), build frontend ile backend’i ayırdı; böylece pip’in setuptools iç yapısını anlaması gerekliliğini kaldırdı
- PEP 621 (2020),
[project] tablosunu standartlaştırdı; böylece yalnızca TOML parse ederek bağımlılıkları kontrol etmek mümkün oldu
- PEP 658 (2022), paket metadata’sını doğrudan Simple Repository API içine ekleyerek wheel indirmeden bağımlılık bilgisinin alınmasını sağladı
- PyPI, Mayıs 2023’te PEP 658’i uyguladı; uv ise Şubat 2024’te yayımlandı ve yeni standart altyapıyı tamamen kullanan ilk araç olarak ortaya çıktı
- Rust’ın Cargo’su veya npm gibi, Python ekosistemi de artık statik metadata tabanlı paketleme modeline geçiyor
uv’nin kaldırdığı özellikler
- uv’nin hızı, gereksiz özelliklerin kaldırılmasından geliyor
- .egg desteği yok: pip hâlâ bunu işlerken uv tamamen dışarıda bırakıyor
- pip.conf yok sayılıyor: yapılandırma dosyaları, environment variable’lar ve kalıtım mantığının tamamı atlanıyor
- Bytecode derleme kapalı:
.py dosyaları .pyc dosyalarına dönüştürülmeyerek kurulum süresi kısalıyor
- Sanal ortam zorunlu: sistem Python’una doğrudan kurulum yapılmadığı için izin kontrolleri ve güvenlik kodu kaldırılıyor
- Katı spec uyumu: hatalı paketler reddedilerek istisna işleme mantığı azaltılıyor
requires-python üst sınırı yok sayılıyor: python<4.0 gibi savunmacı kısıtlar yok sayılarak bağımlılık çözümleme (backtracking) azalıyor
- İlk index önceliği: birden fazla index içinde paket ilkinde bulunursa hemen duruluyor; bu da dependency confusion saldırılarını önlüyor ve ağ isteklerini azaltıyor
- Tüm bu maddeler, pip’in çalıştırmak zorunda olduğu kod yollarını uv’nin ortadan kaldırdığı örnekler
Rust olmadan da mümkün olan optimizasyonlar
- uv’nin hızının önemli bir bölümü, dilden bağımsız tasarım optimizasyonlarından geliyor
- HTTP Range istekleri ile wheel dosyasının yalnızca merkezi dizini kısmen indiriliyor, tüm dosyanın indirilmesi engelleniyor
- Paralel indirme ile birden fazla paket aynı anda çekiliyor
- Global cache ve hard link kullanılarak aynı paket birden fazla sanal ortama kurulduğunda bile ek disk alanı tüketilmiyor
- Python’dan bağımsız çözümleme: TOML ve wheel metadata doğrudan parse ediliyor, yalnızca
setup.py bulunan durumlarda Python çalıştırılıyor
- PubGrub bağımlılık çözümleme algoritması kullanılarak pip’in backtracking yaklaşımına göre daha hızlı ve daha anlaşılır hata açıklamaları sağlanıyor
Rust’ın gerçekten katkı sağladığı yerler
- Rust, belirli düşük seviye optimizasyonlarda önemli rol oynuyor
- rkyv tabanlı zero-copy deserialization ile cache verisi kopyalanmadan doğrudan kullanılıyor
- Locksuz eşzamanlılık veri yapıları ile güvenli paralel erişim sağlanıyor
- Interpreter başlatma maliyeti yok: uv tek ve statik bir binary olduğu için pip’teki Python process oluşturma maliyeti ortadan kalkıyor
- Sürüm bilgisinin u64 tamsayısı olarak sıkıştırılmış temsili, karşılaştırma ve hash işlemlerini hızlandırıyor
- Ancak bu unsurlar performansı artırsa da, toplam hız artışının temel nedeni bunlar değil
Temel ders
- uv’nin hızı Rust’tan değil, yapmadığı şeylerden geliyor
- PEP 518·517·621·658 ile gelen standartlaşma, hızlı paket yönetiminin temelini attı; uv de bunu legacy’yi kaldırıp modern varsayımlar benimseyerek hayata geçirdi
- pip de paralel indirme, global cache ve metadata tabanlı çözümleme uygulayabilir; ancak 15 yıllık geriye dönük uyumluluğu koruma zorunluluğu önemli bir engel
- Sonuç olarak pip’in her zaman yavaş kalması kaçınılmaz ve yalnızca yeni varsayımlarla başlayan araçlar köklü hız artışı sağlayabilir
- Diğer paket yöneticileri için çıkarılacak ders, statik metadata, kod çalıştırmadan bağımlılık keşfi ve önceden çözümlenebilir yapıların zorunlu olduğudur
- Cargo ve npm bu yaklaşımı zaten benimsiyor; bağımlılıkları doğrulamak için kod çalıştırmak zorunda olan ekosistemler temelden yavaştır
1 yorum
Hacker News görüşleri
Bu yazının uv'nin performansını birçok açıdan iyi anlattığını düşünüyorum
Rust ile yazılmış olması da yardımcı oluyor, ama son 10 yılda Python ekosistemini
setup.pybağımlılığından uzaklaştıran standartlaşma çabaları çok daha büyük rol oynadıRust da benzer şekilde topluluğun yetkinliğini yukarı çeken bir tercih olabilir
Geçmişteki deneme-yanılmaları yeniden gözden geçirip daha iyi tasarım yapabiliyorlar; buna Rust'ın kendi avantajları da eklenince adeta bir "çifte darbe" oluyor
"uv Rust olduğu için değil, yapmadığı işler yüzünden hızlı" iddiasına katılıyorum
Yine de benchmark olmadan hızın nedenlerini kesinleştirmek için erken olduğunu düşünüyorum
PEP 518, 517, 621, 658'in etkisi büyük, ama uyumluluğun kaldırılmasının ne kadar katkı yaptığı belirsiz
Ayrıca dil seçiminin optimizasyona nasıl etki ettiği de ele alınmamış
Cargo'nun TOML ayrıştırıcısının Python'dakinden çok daha hızlı olması da ilginç
Aslında TOML sadece build sırasında okunduğu için büyük payı yok, ama wheel yaygınlaşması hız artışına katkı sağladı
İlgili yazılar: setup.py deprecated, wheels are faster
rkyvile yapılan zero-copy deserialization sadece Rust'a özgü bir teknik değilC/C++ gibi düşük seviyeli dillerde de mümkün
"Interpreter başlangıcı yok" ifadesi de aynı bağlamda
Yazının içeriği iyi ama LLM'in cilaladığı üslup fazla yapay hissettiriyor
Belki bir gün LLM yüzünden bozulan yazıları yeniden insani hale getirme dönemi gelir
Tedarik zinciri güvenliği uzmanı gibi görünüyor, ama o yazı da LLM'e özgü muğlak üslup yüzünden bozulmuş gibiydi
Sabit prompt'ların her şeyi birbirine benzetmesi yüzünden internetin tek bir sesle konuşuyormuş gibi gelmesi üzücü
uv'nin hızına yönelik coşkuyu pek anlayamıyorum
Python kullanıcılarının çoğu paket kurulum hızını muhtemelen ilk 10 derdi arasına koymaz
Ben de her gün Python kullanıyorum ama etkisini çok hissetmiyorum
poetryile bağımlılık güncellemesi 5 ila 30 dakika sürüyorduBaşarısız olursa yeniden 30 dakika beklemek gerekiyordu; uv ise gerçekten çok konforlu bir deneyimdi
pip installdağıtım süresinin büyük bölümünü kaplıyorduHızlandırmak için cache'lerle uğraşmaya çok zaman harcadım
poetry install2 dakika sürerkenuv syncbirkaç saniyede bitiyorHer CI çalışmasında 2 dakika tasarrufun birikimli etkisi büyük
uvx sometoolçalıştırırken de sanal ortam oluşturma ve bağımlılık kurulumu birkaç saniye sürdüğü için iş akışı tamamen değişiyorArtık uv olmayan projelere dönmek zor geliyor
uv'deki bazı hız optimizasyon teknikleri pip'e de taşınabilir görünüyor
Örneğin paralel indirme,
.pycdosyalarının gecikmeli oluşturulması, egg'lerin yok sayılması, sürüm kontrolü gibiAma uv sanal ortamları o kadar iyi yönetiyor ki pip'i ayrıca kurcalamaya pek gerek olmayabilir
Sonuçta mesele sadece "Rust sayesinde" değil; bu açıdan pip'in de hızlanma payı var
Hızlı bir dil seçen programcılar çoğu zaman zaten performans optimizasyonu zihniyetine sahip oluyor
Performansı belirleyen şey dilden çok bu yaklaşım
uv'nin
python<4.0üst sınırını yok sayması ilginçPaketlerin çoğu Python 4'te bozulur korkusuyla bunu savunmacı biçimde koymuştu, oysa pratikte çoğu sorun çıkarmayacaktır
Üst sınır kısıtları, gerçek bir problemden çok varsayımsal bir problemi çözmeye çalışıyordu
python<3.0gibi kısıtlar hâlâ önemli, dolayısıyla bunlar engellenmeliPEP 658'in 2023'te devreye girmesi ve uv'nin 2024'te ortaya çıkması tesadüf değil
Ekosistem hazır hale geldiği için uv gibi araçlar mümkün oldu
Ama paket bakımcılarının bu değişimi neden benimsediğini merak ediyorum
setup.pyile sorunsuz çalışanlar da vardı; peki pyproject.toml'a geçmelerinin motivasyonu neydisetup.pybirçok kişi için rahatsız ediciydiÖrneğin Requests bile hâlâ tam PEP 517/518/621 uyumlu değil
1,5 yıl geçmesine rağmen minor sürüm gecikti ve bu arada build sorunları da yaşandı
Ama pip'in bunu neden yeterince kullanmadığı hâlâ soru işareti
"Çalıştırılmayan kod yolunu beklemeniz gerekmez" ifadesi çok doğru değil
Zaman kazandıran şey, gerçekten yürütülmeyen koddur
Mesela
.eggdesteğinin olmaması, eğer bu zaten terk edilmiş bir format ise hıza etki etmezHangi kalemin ne kadar zaman kazandırdığına dair nicel veri olsaydı daha iyi olurdu
Yine de genel olarak iyi derlenmiş bir yazı