Herkes bize Electron kullanmamızı söyledi. Bir kez yaz, her yerde çalıştır. Hızlı ilerle. Biz tersini yaptık — Apple'da SwiftUI, Android'de Jetpack Compose, Windows'ta C++/WinRT, pikselleri saate göre ihtiyaç duyduğumuz yerde ham Metal ve Vulkan. Tek bir ürün için dört yerel istemci geliştirirken öğrendiklerimiz şunlar.
Kolay yol ve doğru yol
İnsanlara 2024'te sıfırdan bir uzak masaüstü uygulaması geliştirdiğinizi söylediğinizde ilk soru hep şu olur: "Neden sadece Electron kullanmıyorsunuz?"
Haklı bir soru. Electron, gezegendeki en başarılı uygulamalardan bazılarına güç veriyor — VS Code, Slack, Discord, Figma'nın masaüstü sarmalayıcısı. Bir kez yazıp her yerde dağıtmanıza izin veriyor. Web geliştiricileriniz bir gecede masaüstü geliştiricisi oluyor. Pazara çıkış süresi avantajı gerçek.
Rakamlara baktık, ödünleri tarttık ve mümkün olan en zor yolu seçtik: her platformda tamamen yerel. iOS ve macOS'ta SwiftUI. Android'de Jetpack Compose. Windows'ta C++/WinRT. Apple'da görüntüleme için Metal. Diğer her yerde Vulkan. Çekirdekte özel bir Go sunucusu.
Acı çekmekten hoşlandığımız için değil, bazı günler öyle hissettirse de. Bu tür bir uygulama için yerel çözüm bir lüks değil, bir gereklilik olduğu için.
Electron vergisi gerçek
Electron'un gerçekte ne olduğuyla başlayalım: masaüstü uygulaması gibi davranan bir Chromium tarayıcı penceresi. Bu bir eleştiri değil — mimari. Birçok uygulama için de gayet iyi.
Ama bir uzak masaüstü için? Başka bir bilgisayardan pikselleri yayınlıyor, onları gerçek zamanlı çiziyor ve her girdi olayını yakalayıp geri gönderiyorsunuz. Gecikme olsa iyi olur bir şey değil. Ürünün tamamı o.
İki yaklaşımın prototipini yaptığımızda ölçtüklerimiz:
- Bellek — Yerel istemci kararlı durumda: ~45 MB. Electron prototipi: ~380 MB. Uygulamalardan biri tek bir kareyi çözmeye başlamadan, boşta 8,4 kat fark.
- Soğuk başlangıç — Yerel macOS uygulaması 200 ms'nin altında soğuk başlıyor. Electron prototipi 2 ila 3 saniye sürdü. Günde yirmi kez açtığınız bir araç için bu, gerçek bir sürtünmeye dönüşür.
- Pil — Pille çalışan bir Mac'te Electron derlemesi, boşta bir bağlantı sırasında kabaca 3 kat watt çekti. Chromium ucuz uyumaz.
380 MB, Electron'un şişkin olmasından değil. Chromium'un işini yapmasından — V8, bir GPU süreci, yardımcı süreçler, koca bir tarayıcı motoru. Etkileyici bir mühendislik. Sadece farklı bir problem için tasarlanmış bir mühendislik.
Kareler özelliklerden daha önemli
Uzak masaüstü, her bir karenin önemli olduğu az sayıdaki uygulama kategorisinden biri. Bir kare düşürürseniz kullanıcı hisseder. 16 ms girdi gecikmesi ekleyin, bir tasarımcı düzgün eğriler çizemez. 32 ms ekleyin, bir oyuncu oynayamaz.
Yerel görüntülemeyle doğrudan GPU ile konuşuruz. Apple platformlarında VideoToolbox bize donanım video çözmeye doğrudan erişim sağlar. Ağdan bir H.265 karesi alır, donanımda çözer ve gösteririz — kare hiç ana belleğe dokunmadan. Çözmeden görüntülemeye hat, modern bir Mac'te 4 ms'nin altında çalışır.
Electron'da aynı kare Chromium'un birleştiricisinden, IPC köprüsünden geçer, Skia tarafından boyanır, sonra işletim sistemi tarafından yeniden birleştirilir. Her sıçrama gecikme ekler. Her sıçrama titreşim ekler. Ve titreşim — tutarsız kare zamanlaması — ortalama FPS iyi görünse bile uzak masaüstünü tuhaf hissettiren şeydir.
Yerel çözümü püristler olmak için seçmedik. Problemimizin fiziği bunu gerektirdiği için seçtik — LAN'da yaklaşık 8 ms'lik işlem (geri kalanı ekranınızın kendi 60 Hz yenileme ritmidir), ortada bir tarayıcıya yer bırakmaz.
Yerel ve web yetenek defteri
Electron ve yerel çözüm tartışması çoğu zaman hislerde takılıp kalır. Bu yüzden Remio'nun her oturumun her saniyesinde bağlı olduğu yedi işletim sistemi yeteneğini yazdık ve açıkça sorduk: her biri her çalışma zamanında nasıl bir performans gösteriyor?
| Yetenek | Yerel | Web / Electron |
|---|---|---|
| 60 fps donanım çözme | ● Doğrudan VideoToolbox / D3D11VA | ○ WebCodecs üzerinden, titreşim |
| Düşük gecikmeli USB ses | ● CoreAudio / WASAPI | — Sanal alanda, 40 ms+ |
| Klavye girdisi izleme | ● CGEvent / SendInput | — Odak dışında engelli |
| Metal / D3D11 GPU erişimi | ● Sıfır kopyalı dokular | ○ WebGPU, kopya sıçramaları |
| Yerel dosya sistemi | ● Tam, işletim sistemince kapsamlı | ○ Yalnızca seçici, istemler |
| Çok pencere, çok ekran | ● İşletim sistemine özgü pencereleme | ○ BrowserWindow yamaları |
| Arka planda kalıcılık | ● LaunchAgent / hizmet | — Gizlenince askıya alınır |
Her satır bugün yayınladığımız bir özellik. Web sütunundaki her — icat etmemiz, belgelememiz ve özür dilememiz gereken bir geçici çözüm. Yerel çözüme gitmek, bu yetenekleri polyfill'ler olarak değil, temel yapı taşları olarak ele almamız demek.
Platform vatandaşlığı
Bir kez yaz, her yerde çalıştır kalabalığının nadiren söylediği bir şey: kullanıcılar bunu anlıyor.
Bir uygulama sistemin koyu mod geçişlerine saygı göstermediğinde anlarlar. Kaydırma fiziği hafifçe yanlış hissettirdiğinde. Uygulama Spotlight'ta görünmediğinde ya da macOS pencere yönetimini düzgün ele almadığında. Bağlam menüsü yerel bir menü yerine bir web sayfasına benzediğinde.
Bunlar olsa iyi olur şeyler değil. İnsanların katlandığı bir uygulama ile sevdiği bir uygulama arasındaki farktır. iOS'ta bu özellikle kritik — App Store incelemesi yerel hissettirmeyen uygulamaları reddeder ve haklı olarak.
SwiftUI ile bunların hepsi bedavaya geliyor. Dinamik Yazı Tipi, VoiceOver erişilebilirliği, sistem dokunsal geri bildirimleri, iPad'de çoklu görev, Mac'te klavye kısayolları. Platform özelliklerini yeniden uygulamıyoruz. Onları kullanıyoruz.
Maliyeti de gerçek
Olumsuz tarafı dürüstçe söyleyelim: yerel çözüme gitmek pahalı. Dolar olarak değil — zaman ve karmaşıklık olarak.
Dört arayüz kod tabanı sürdürüyoruz. Ağ ve codec katmanımız ortak (sinyalleşme için Go, yayın protokolü için C++), ama ekranda gördüğünüz her piksel platforma özel kod. Electron'da bir günde biten bir özellik bizde üç ila beş gün sürüyor, çünkü onu dört kez, her platform için ayarlayarak geliştiriyoruz.
Tek bir animasyonun iOS'ta güzel çalıştığı, Android'de bozuk olduğu ve Windows'ta takıldığı haftalarımız oldu. Hata ayıklama matrisi acımasız.
Ama öğrendiğimiz şu: en zor yol ve doğru yol çoğu zaman aynı yoldur. Kullanıcılarımız mimarimizi bilmez ya da umursamaz. Remio'nun hızlı hissettirdiğini, doğru hissettirdiğini ve pilini kahvaltıda yemediğini bilirler.
Yine yapar mıydık
Tereddütsüz.
Yerel yaklaşım bize, bu kullanım senaryosunda Electron'un temelde eşleşemeyeceği bir performans verdi. Her platforma ait hissettiren uygulamalar verdi. 380 MB yerine 45 MB'ın altında bir bellek ayak izi verdi. LAN'da yaklaşık 8 ms'lik işlem verdi (geri kalanı ekranınızın kendi 60 Hz yenileme ritmidir); tarayıcıya sarılı bir rakip ise 60 ms'nin üzerinde duruyor.
En önemlisi, bize teknik bir hendek verdi. Dört platformda yerel geliştirmek, çoğu rakibin yapmayacağı kadar zor. Bu zorluk bizim avantajımız.
Uzak masaüstü kategorisine Electron'a sarılı web uygulamaları ve yıllardır anlamlı şekilde güncellenmemiş eski yerel uygulamalar hâkim oldu. Hem modern hem yerel bir şeye — bugünün donanımı düşünülerek sıfırdan yapılmış bir şeye — yer var.
İşte Remio bu. Zor yoldan yapıldı, çünkü bazı şeyler doğru yapılmaya değer.