bazel mobil yükleme

Sorun bildir Kaynağı göster

Android için hızlı yinelemeli geliştirme

Bu sayfada bazel mobile-install ürününün Android için yinelemeli geliştirmeyi nasıl çok daha hızlı hale getirdiği açıklanmaktadır. Makalede bu yaklaşımın avantajları, geleneksel uygulama yükleme yönteminin zorluklarına kıyasla açıklanmıştır.

Özet

Bir Android uygulamasındaki küçük değişiklikleri çok hızlı bir şekilde yüklemek için aşağıdakileri yapın:

  1. Yüklemek istediğiniz uygulamanın android_binary kuralını bulun.
  2. proguard_specs özelliğini kaldırarak ProGuard'ı devre dışı bırakın.
  3. multidex özelliğini native olarak ayarlayın.
  4. dex_shards özelliğini 10 olarak ayarlayın.
  5. ART (Dalvik değil) çalıştıran cihazınızı USB üzerinden bağlayın ve cihazda USB hata ayıklama özelliğini etkinleştirin.
  6. bazel mobile-install :your_target komutunu çalıştırın. Uygulama normalden biraz daha daha yavaş başlatılır.
  7. Kodu veya Android kaynaklarını düzenleyin.
  8. bazel mobile-install --incremental :your_target komutunu çalıştırın.
  9. Çok fazla beklemek zorunda kalmamanın keyfini çıkarın.

Bazel için yararlı olabilecek bazı komut satırı seçenekleri:

  • --adb, Bazel'a hangi adb ikili programının kullanılacağını söyler
  • --adb_arg, adb öğesinin komut satırına fazladan bağımsız değişkenler eklemek için kullanılabilir. Bunun yararlı bir uygulaması, iş istasyonunuza bağlı birden çok cihazınız varsa hangi cihaza yüklemek istediğinizi seçmektir: bazel mobile-install --adb_arg=-s --adb_arg=<SERIAL> :your_target
  • --start_app uygulaması otomatik olarak başlatır

Emin olamadığınız durumlarda örneği inceleyin veya bizimle iletişime geçin.

Giriş

Bir geliştiricinin araç zincirinin en önemli özelliklerinden biri hızdır. Kodu değiştirmek ile kodun bir saniye içinde çalıştığını görmek ve değişikliklerinizin beklediğiniz gibi yapıp yapmadığıyla ilgili geri bildirim almadan önce dakikalar, bazen saatlerce beklemek zorunda kalmak arasında çok büyük bir fark vardır.

Ne yazık ki .apk oluşturmak için kullanılan geleneksel Android araç zinciri, pek çok monolitik, ardışık adım gerektirir ve bunların bir Android uygulaması geliştirmek için bunların hepsi yapılması gerekir. Google'da, tek satırlı bir değişiklik oluşturmak için beş dakika beklemek Google Haritalar gibi daha büyük projelerde olağan dışı bir durumdu.

bazel mobile-install; değişiklik ayıklama, iş parçalama ve Android dahili bileşenlerinin zekice değiştirilmesini bir arada kullanarak, uygulamanızın kodunda hiçbir değişiklik yapmadan Android için yinelemeli geliştirmeyi çok daha hızlı hale getirir.

Geleneksel uygulama yüklemeyle ilgili sorunlar

Android uygulaması oluştururken aşağıdakiler de dahil olmak üzere bazı sorunlar vardır:

  • Dexing. Varsayılan olarak, "dx" derlemede tam olarak bir kez çağrılır ve önceki derlemelere ait çalışmanın nasıl yeniden kullanılacağını bilmez: Yalnızca bir yöntem değiştirilse bile her yöntemi tekrar dxştirir.

  • Cihaza veri yükleme. adb, USB 2.0 bağlantısının tam bant genişliğini kullanmaz ve daha büyük uygulamaların yüklenmesi çok zaman alabilir. Bir kaynak veya tek bir yöntem gibi yalnızca küçük parçalar değişmiş olsa bile uygulamanın tamamı yüklenir. Dolayısıyla bu, büyük bir performans sorunu olabilir.

  • Yerel koda derleme. Android L, uygulamaları Dalvik gibi tam zamanında derlemek yerine önceden derleyen yeni Android çalışma zamanı olan ART'ı kullanıma sundu. Bu da uygulamaları, daha uzun yükleme sürelerine mal olacak şekilde çok daha hızlı hale getirir. Bu, bir uygulamayı genellikle bir kez yükleyip birçok kez kullandıkları, ancak uygulamanın birçok kez yüklendiği ve her sürümün en az birkaç kez çalıştırıldığı daha yavaş bir gelişime neden olduğundan kullanıcılar için iyi bir dengedir.

bazel mobile-install yaklaşımı

bazel mobile-installaşağıdaki iyileştirmeleri yapar:

  • Parçalı dexing. Uygulamanın Java kodunu oluşturduktan sonra Bazel, sınıf dosyalarını yaklaşık olarak eşit boyutta parçalara ayırır ve bunlarda ayrı olarak dx yöntemini çağırır. dx, son derlemeden bu yana değişmemiş parçalarda çağrılmaz.

  • Artımlı dosya aktarımı. Android kaynakları, .dex dosyaları ve yerel kitaplıklar ana .apk'den kaldırılır ve ayrı bir mobil yükleme dizininde depolanır. Bu, uygulamanın tamamını yeniden yüklemeden kodu ve Android kaynaklarını bağımsız olarak güncellemeyi mümkün kılar. Böylece, dosyaların aktarılması daha kısa sürer ve yalnızca değiştirilen .dex dosyaları cihaz üzerinde yeniden derlenir.

  • Uygulamanın bazı kısımları .apk dışından yükleniyor. Cihaz üzerindeki mobil yükleme dizininden Android kaynaklarını, Java kodunu ve yerel kodu yükleyen, ardından kontrolü gerçek uygulamaya aktaran .apk'ye küçük bir saplama uygulaması yerleştirilir. Aşağıda açıklanan birkaç köşe durumu haricinde tüm bunlar uygulama tarafından şeffaf bir şekilde işlenir.

Parçalı Dexing

Parçalı dexing işlemi makul ölçüde basittir: .jar dosyaları derlendikten sonra, bir araç bu dosyaları yaklaşık olarak eşit boyutta ayrı .jar dosyaları halinde parçalara ayırır, ardından önceki derlemeden bu yana değiştirilen dosyalarda dx çağırır. Hangi kırıkların ayıklanacağını belirleyen mantık Android'e özel değildir. Yalnızca Bazel'ın genel değişiklik ayıklama algoritması kullanılır.

Parçalama algoritmasının ilk sürümü, .class dosyalarını alfabetik olarak sıralıyor ve ardından listeyi eşit boyutlu parçalara ayırıyordu. Ancak bunun yetersiz olduğunu kanıtladı: Bir sınıf eklenir veya kaldırılırsa (iç içe veya anonim bir sınıf olsa bile) tüm sınıfların bir birim kaydırılmasından sonra alfabetik olarak bir değişim olur ve bu da söz konusu parçalara tekrar dağılmasıyla sonuçlanır. Bu nedenle, bağımsız sınıflar yerine Java paketlerini parçalamaya karar verildi. Elbette, yeni bir paket eklenirse veya kaldırılırsa bu yine de çok sayıda parçanın dizine eklenmesine neden olur, ancak bu, tek bir sınıf eklemek veya çıkarmaktan çok daha az sıklıkta gerçekleşir.

Parça sayısı, BUILD dosyası (android_binary.dex_shards özelliği kullanılarak) tarafından kontrol edilir. İdeal bir dünyada Bazel kaç tane parçanın en iyi olduğunu otomatik olarak belirler. Ancak Bazel şu anda herhangi bir işlemi yürütmeden önce işlem kümesini (örneğin, derleme sırasında yürütülecek komutlar) bilmelidir. Bu nedenle, uygulamada kaç Java sınıfı olacağını bilemez, çünkü uygulamanın daha hızlı yüklenmesi ve daha yavaş uygulama parçaları olur. En iyi konum genellikle 10 ila 50 kırıktır.

Artımlı dosya aktarımı

Uygulamayı oluşturduktan sonraki adım, tercihen mümkün olan en az çabayla uygulamayı yüklemektir. Yükleme işlemi aşağıdaki adımlardan oluşur:

  1. .apk yükleniyor (genelde adb install kullanılıyor)
  2. .dex dosyalarını, Android kaynaklarını ve yerel kitaplıkları mobile-install dizinine yükleyerek

İlk adımda fazla bir artımlılık yoktur: Uygulama ya yüklüdür ya da yüklenmemiştir. Bazel, gerekli olup olmadığını her durumda belirleyemeyeceğinden şu anda bu adımı --incremental komut satırı seçeneği üzerinden yapıp yapmayacağını belirtmek için kullanıcıdan güveniyor.

İkinci adımda, uygulamanın derlemedeki dosyaları, cihazda hangi uygulama dosyalarının bulunduğunu ve sağlamalarının listelendiği cihaz üzerindeki bir manifest dosyasıyla karşılaştırılır. Yeni dosyalar cihaza yüklenir, değiştirilen dosyalar güncellenir ve kaldırılan dosyalar cihazdan silinir. Manifest mevcut değilse her dosyanın yüklenmesi gerektiği varsayılır.

Cihazdaki bir dosyayı değiştirerek artımlı yükleme algoritmasını kandırabilirsiniz, ancak manifest dosyasında dosyanın sağlama toplamını değiştirmek mümkün değildir. Bu durum, cihazdaki dosyaların sağlaması hesaplanarak korunabilirdi, ancak yükleme süresindeki artışa değmeyeceğine karar verildi.

Saplama uygulaması

Saplama uygulamasında dex'leri, yerel kodu ve Android kaynaklarını cihaz üzerindeki mobile-install dizininden yükleme işlemi gerçekleşir.

Gerçek yükleme, BaseDexClassLoader alt sınıflandırması tarafından uygulanır ve yeterince iyi belgelenmiş bir tekniktir. Bu işlem, uygulamanın sınıflarından biri yüklenmeden önce gerçekleşir. Böylece apk'deki uygulama sınıfları, cihaz üzerindeki mobile-install dizinine yerleştirilebilir ve böylece adb install olmadan güncellenebilir.

Bu işlemin, uygulamanın sınıflarından herhangi biri yüklenmeden yapılması gerekir. Böylece .apk'de uygulama sınıfı bulunmasına gerek yoktur. Bu da söz konusu sınıflarda yapılan değişikliklerin tam yeniden yükleme gerektirdiği anlamına gelir.

Bu işlem, AndroidManifest.xml politikasında belirtilen Application sınıfının saplama uygulamasıyla değiştirilmesiyle gerçekleştirilir. Bu, uygulamanın başlatılmasını kontrol etme imkanı tanır ve Android çerçevesinin dahili bileşenlerinde Java yansımasını kullanarak en kısa sürede sınıf yükleyici ile kaynak yöneticisini (kurucusu) uygun şekilde düzenler.

Saplama uygulamasının yaptığı bir başka işlem de, mobil yükleme ile yüklenen yerel kitaplıkları başka bir konuma kopyalamaktır. Bu işlem, dinamik bağlayıcı için dosyalarda X bitinin ayarlanması gerektiğinden gereklidir. Kök olmayan bir adb tarafından erişilebilen hiçbir konumda bunu yapmak mümkün değildir.

Tüm bu işlemler tamamlandıktan sonra, saplama uygulaması gerçek Application sınıfını somutlaştırarak Android çerçevesi içinde gerçek uygulamaya yapılan tüm referansları değiştirir.

Sonuçlar

Performans

bazel mobile-install, genellikle küçük bir değişiklikten sonra büyük uygulamalar oluşturma ve yükleme hızını 4 ila 10 kat artırır.

Aşağıdaki sayılar birkaç Google ürünü için hesaplanmıştır:

Bu elbette değişikliğin yapısına bağlıdır: Bir temel kitaplığı değiştirdikten sonra yeniden derleme daha uzun sürer.

Sınırlamalar

Saplama uygulamasının yaptığı hileler her durumda işe yaramaz. Aşağıdaki örneklerde, beklendiği gibi çalışmadığı yerler vurgulanmaktadır:

  • Context, ContentProvider#onCreate() ile ilgili Application sınıfına yayınlandığında. Bu yöntem, Application sınıfı örneğini değiştirme fırsatımız olmadan uygulama başlatma sırasında çağrılır. Bu nedenle ContentProvider, gerçek uygulama yerine saplama uygulamasına referans vermeye devam eder. Muhtemelen Context öğesini bu şekilde aşağı düşürmeniz gerekmediği için bu bir hata değildir, ancak bu durum Google'daki birkaç uygulamada yaşanmaktadır.

  • bazel mobile-install tarafından yüklenen kaynaklar yalnızca uygulama içinden kullanılabilir. Diğer uygulamalar PackageManager#getApplicationResources() üzerinden kaynaklara erişiyorsa bu kaynaklar son ek olmayan yükleme işleminden alınır.

  • ART kullanmayan cihazlar. Saplama uygulaması, Froyo ve sonraki sürümlerde sorunsuz bir şekilde çalışsa da Dalvik, bazı durumlarda (örneğin, Java ek açıklamaları belirli bir şekilde kullanıldığında) kodu birden fazla .dex dosyasına dağıtılmışsa uygulamanın hatalı olduğunu düşünür. Uygulamanız bu hataları gıdıklanmadığı sürece Dalvik ile de çalışmalıdır (ancak, eski Android sürümlerini desteklemenin tam olarak odak noktamız olmadığını unutmayın.)