Apple’dan TrueType Devrimi: Swift ile Fontlar Artık Daha Güvenli ve Hızlı
TrueType, web sayfalarında, PDF’lerde, işletim sistemlerinde ve uygulamalarda metin oluşturmak için yaygın olarak kullanılan bir vektör font standardıdır. Helvetica, Garamond ve Monaco gibi bilinen fontlar TrueType ana hatları üzerine kuruludur. Bu format, düşük çözünürlüklü ekranlarda ana hatların doğru şekilde rasterize edilmesine yardımcı olmak için bir hintleme yorumlayıcısı içerir. Modern yüksek çözünürlüklü ekranlar yalnızca ana hatlardan güzel tipografi sağlasa da, okunabilir bir şekilde işlenmek için hintlemeye ihtiyaç duyan TrueType fontları hala kullanılmaktadır.
Font ayrıştırıcıları, güvenilmeyen kaynaklardan gelen verileri işlediği için TrueType hintleme yorumlayıcısı, güvenlik açısından kritik bir saldırı yüzeyidir. Apple platformlarında formatı daha dayanıklı hale getirmek amacıyla, yorumlayıcıyı C’den bellek güvenli Swift’e yeniden yazdık ve bu, Güz 2025 sürümleriyle birlikte sunuldu. Bellek güvenliğine ek olarak, performansı da iyileştirdik: Swift yorumlayıcımız, yerine geçtiği C yorumlayıcısından ortalama %13 daha hızlı çalışmaktadır.
Bu yazıyla birlikte, Swift TrueType hintleme yorumlayıcısının kaynak kodunu da GitHub üzerinde yayımladık. Deneyimlerimizi paylaşarak benzer çalışmalar yapan diğer geliştiricilere yardımcı olmayı umuyoruz.
TrueType ve Hintleme Motorunun Gelişimi
Apple, TrueType’ı 1980’lerin sonlarında geliştirdi ve 1991’de System 7’nin piyasaya sürülmesiyle birlikte yayımladı. TrueType, zamanına göre büyük bir atılımdı: font geliştiricilerine, gelişmiş bir ızgara oturtma algoritması ve özel amaçlı bir bayt kodu yorumlayıcısı üzerine kurulu sofistike bir hintleme motoruyla gliflerin nasıl görüntülendiği üzerinde büyük kontrol sağladı. TrueType tüm bunları, günümüzdeki bilgisayarlardan çok daha az güçlü olan makinelerde başarıyla gerçekleştirdi, bu nedenle performans için son derece iyi optimize edilmiş olması gerekiyordu.
İnternet, fontların kullanım şeklini kökten değiştirdi. TrueType, 1994’te PDF dosyalarına ve 2008’de web sayfalarına gömülebilir hale geldi ve hala güncelliğini koruyor. Ancak bu yeni kullanım senaryoları ek riskler getirdi: TrueType artık internetin herhangi bir yerinden gelen güvenilmeyen fontlara maruz kalabiliyordu. Hintleme motoru, bayt kodu yorumlayıcısı aracılığıyla programlar çalıştırabilir. Bu yorumlayıcı, girdi odaklı kontrol akışı, karmaşık veri yapıları ve dikkatli bellek yönetimi içerir – yani mükemmel hale getirilmesi zor ve bellek hatalarının istismar edilmesinin kolay olduğu türden bir kod. Bu yüksek doğuştan gelen karmaşıklık, doğruluğu özellikle önemli kılmaktadır.
Bir yeniden yazım için, mevcut kod tabanına entegre olabilen ve değiştirdiği uygulamaya eşdeğer düzeyde performans sağlayabilen, bellek güvenli bir dil gerekiyordu. Swift, bu görev için bariz bir seçimdi.
İkili Uyumluluk ve Kapsamlı Test Süreçleri
Bu projenin başarısı için ikili uyumluluk hayati önem taşıyordu: mevcut programlar, yeni bir uygulamanın devrede olduğundan habersizmiş gibi, daha önce çalıştığı gibi işlev görmeye devam etmeliydi. Bu sadece arayüz uyumluluğu değil, aynı zamanda C uygulamasına göre piksel-özdeş glif oluşturmayı da içeriyordu. Hintleme, gliflerin ekran görünümünü radikal bir şekilde değiştirebilir, bu nedenle yorumlayıcının davranışındaki küçük bir değişiklik bile kullanıcı tarafından fark edilebilir önemli değişikliklere yol açabilirdi. Bu proje için doğruluk, C uygulamasının çıktılarıyla tam uyumluluk olarak tanımlandı.
Doğruluğu sağlamak için iki test paketi geliştirdik. İlki, her iki uygulamayı da hedefleyebilen ve her ikisi için de kapsamlı (%99,7) kod kapsamı sağlayan bir birim test paketiydi. Bu paket, Swift yorumlayıcısının açık kaynak sürümüyle birlikte yayımlandı.
Daha sonra, gerçek dünya iş yüklerini temsil etmek için, 10 milyon PDF dosyasından oluşan bir külliyatı, kod kapsamı kaybı olmadan 4.200’e indirmek için bir fuzzer kullandık. Minimize edilmiş külliyattaki belgeler, her biri dört farklı dönüşümle oluşturduğumuz toplam 27 milyon glife sahip 25.572 fontu içeriyordu ve ortaya çıkan bit eşlemleri referans yorumlayıcıyla karşılaştırdık. Bu bize yeni yorumlayıcının uyumluluğu konusunda güven verdi. Projenin sonunda, Swift yorumlayıcısı için yazdığımız kodun neredeyse dört katı kadar test kodu yazdık.
Swift ile Performans İyileştirmelerinin Anahtar Alanları
Yeni uygulamamız tüm testleri geçtikten sonra dikkatimizi performansa çevirdik. Performansı üst düzeyde PDF oluşturma süresiyle değerlendirdik ve ardından üç farklı fonttan tüm glifleri oluşturan kıyaslamalarla rehberlik edilen iyileştirmeler üzerinde çalıştık. Bu iyileştirmeler dört ana kategoriye ayrıldı:
- `~Copyable` ve `Span` ile Hafıza Yönetimi: Swift, paylaşılan referans türlerinin ömrünü yönetmek için otomatik referans sayımı (ARC) ve veri yapılarına çakışan erişimi engellemek için çalışma zamanı ayrıcalık denetimi kullanır. Bu ek yükler, yorumlayıcının tasarım gereği var olan indirgenemez miktarının olduğu aliasing tarafından kötüleştirilebilir. Bu ek yük kaynakları, kopyalanabilirlik kolaylığından vazgeçerek, mimari genelinde
~Copyabledeğer türlerini (structyerineclass) benimseyerek ve referans türlerini üst düzey soyutlamalara ayırarak ortadan kaldırılabilir. Swift 6.2’de tanıtılan ve macOS 10.14.4 ve iOS 12.2’ye kadar geri uyumluluk desteği olanSpan, bu tür diziler üzerinde verimli bir şekilde işlem yapmamızı sağladı. - Dil Sınırları Arasında Verimli Veri Yapıları: Bazen yapılandırılmış verilerin ‘şeklini’, dil sınırlarını geçerken diğer taraftaki deyimlere daha iyi uyması için değiştirmek isteriz. Başlangıçta, C’den Swift’e kopyalama, yeni yorumlayıcının çalışma zamanının yaklaşık %20’sini oluşturuyordu. Sonunda, temel C yapısına güvenli erişim sağlayan projeksiyon türleri kullandık. Bu sayede Swift, temel veri yapısını kopyalamadan veya başka bir şekilde dönüştürmeden okunabilirlik sunar.
- Bellek Tahsisini Azaltma: `filter` ve `map` gibi işlemler bellek tahsis eder, ancak bu tahsis yalnızca değer kaçarsa gereklidir. Swift standart kütüphanesi `.lazy.map` ve `.lazy.filter` sağlar, ancak bunlar her durumda çalışmaz. Yalnızca filtre veya harita üzerinde iterasyon yapan mantık için, `continue` ile döngü yapmak (veya `for … in … where` kullanmak) ve öğeleri gerektiğinde yerel değişkenlere dönüştürmek çok daha verimlidir. Bir fonksiyonun çağırana sonuçları geçirmek için özel olarak var olan tahsisler de ortadan kaldırılabilir. Örneğin, yorumlayıcının yığınından son `n` öğeyi `pop` etme işlemini, yığın öğelerinin bir dilimi üzerinde işlem yapabilen bir bloğu çağırana geçiren bir devamlılık-geçiş yaklaşımıyla optimize ettik.
- Dinamik Çağrıları Azaltma: Protokoller, jenerikler ve kalıtım gibi soyutlama mekanizmaları çok güçlüdür, ancak çalışma zamanında dinamik gönderim olarak ortaya çıkabilecek yöntem çağrısı dolaylılığını getirirler. Bu ek yük genellikle optimize edici tarafından ortadan kaldırılabilir, ancak her koşulda bu mümkün değildir. Soyutlamaları gereğinden daha genel yapmamak ve araç zincirini satır içi yapmaya teşvik etmek, optimize edicinin sınır kontrollerini yükseltmesi ve tüm jenerik bağlamlarımızı özelleştirmesi için yeterli oldu.
Sıfır Maliyetli Soyutlamalar ve Artırılmış Okunabilirlik
Performans iyileştirmelerinin genellikle okunabilirlik pahasına geldiği düşünülse de, Swift’in tip sistemi ve optimize edicisi, yüksek derecede okunaklı kodla sonuçlanan soyutlamalar kullanmamızı sağladı. Örneğin, FixedPoint türleri, karmaşık yuvarlama ve kaydırma aritmetiğini kapsayarak tam sayı türleriyle aynı ergonomiyi sağladı. StackElement, desteklenen sekiz sayısal türün tümü için yerleşik dönüşümlerle 32 bit değerlere erişim sağladı. Projeksiyon türlerimiz, bu faktörler göz önünde bulundurularak yapılandırılmamış verilere güvenli ve doğal erişim sağladı. Swift’in tip sistemi, güçlü ve ifade edici soyutlamalar tanımlamayı mümkün kılar. Optimizasyonlarla birlikte inşa edildiğinde, tüm soyutlamalarımız sıfır maliyet eklerken okunabilirliği önemli ölçüde iyileştirdi.
Bellek Güvenli ve C’den Daha Hızlı Bir Gelecek
Bu projedeki hedefimiz, TrueType hintleme yorumlayıcısını tamamen bellek güvenli hale getirmek, C uygulamasıyla aynı gözlemlenebilir oluşturma davranışına sahip olmak ve kullanıcı tarafından fark edilebilir hiçbir kıyaslamayı geriletmeyen bir performans seviyesine ulaşmaktı. Bu hedeflere ulaştık. Swift yorumlayıcısı, dil birlikte çalışabilirlik sınırında az sayıda, kapsamlı bir şekilde doğrulanmış unsafe ifadesi içerir; etkinleştirildiğinden beri herhangi bir hata bildirilmemiştir ve daha hızlıdır. Ortalama olarak, Swift yorumlayıcısı, yerine geçtiği C yorumlayıcısından %13 daha hızlı çalışmaktadır. Swift dili bu projeyi mümkün kıldı. Swift, bellek güvenli, harika ergonomiye sahip ve dikkatlice yazılmış C kadar hızlı olabilir. Bu da onu hem uygulama hem de sistem geliştirme için mükemmel bir dil haline getiriyor.
noncopyable türler, değer türleri ve Span kullanan kod, varsayılan olarak hem güvenli hem de hızlıdır ve modül-özel türler, hiçbir ek maliyet olmaksızın toplu olarak bir mimari tanımlamak için kullanılabilir. Kapsamlı test kapsamıyla birlikte, bu iyi tanımlanmış dahili arayüz sınırları, yeniden düzenlemeyi önemli ölçüde kolaylaştırır, bu da ölçme ve düzeltme optimizasyon döngüsünü hızlandırırken hata riskini en aza indirir.
Bu geçiş çabası, Swift uzmanlığımızı derinleştirdi ve üzerine inşa edebileceğimiz bir temel sağladı. Geçişi tamamladıktan sonra, öğrendiklerimizi LLM kodlama asistanları için talimatlara dönüştürdük ve o zamandan beri bunları diğer projelerde başarıyla kullandık. LLM’ler, ekibimizin C/C++’ı Swift’e dönüştürme çalışmalarının verimliliğini artırdı ve bu çabada kullanılan türden kod dönüşümlerini gerçekleştirmede değerli olduğunu kanıtladı.
Bu yazının ekinde, Swift TrueType hintleme yorumlayıcısının kaynak kodunu GitHub’da yayımladık. Bu, sürekli bir açık kaynak projesi yerine bir referans uygulama olarak tasarlanmış üretim kodudur. Bu tekniklerin pratikte nasıl çalıştığını görmenin başkalarının da benzer sonuçlar elde etmesine yardımcı olmasını umuyoruz.

