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. Geleneksel uygulama yükleme yönteminin zorlukları ile karşılaştırıldığında bu yaklaşımın avantajlarını açıklamaktadır.

Özet

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

  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ıklamayı etkinleştirin.
  6. bazel mobile-install :your_target komutunu çalıştırın. Uygulama başlatma işlemi normalden biraz daha yavaş olacaktır.
  7. Kodu veya Android kaynaklarını düzenleyin.
  8. bazel mobile-install --incremental :your_target komutunu çalıştırın.
  9. Çok beklemek zorunda kalmamanın keyfini çıkarın.

Bazel'a yönelik yararlı olabilecek bazı komut satırı seçenekleri:

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

Emin değilseniz ö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ştirmekle kodun bir saniye içinde çalıştığını görmekle, yaptığınız değişikliklerin istediğiniz şeyi yapıp yapmadığına dair bir geri bildirim almadan önce dakikalar, bazen saatlerce beklemek zorunda kalmak arasında büyük fark vardır.

Ne yazık ki .apk dosyası oluşturmak için kullanılan geleneksel Android araç zinciri, pek çok monolitik, ardışık adım gerektirir ve bunların hepsinin bir Android uygulaması geliştirmek için uygulanması gerekir. Google'da, tek satırlık 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, uygulamanızın kodunda hiçbir değişiklik yapmadan değişiklik ayıklama, iş parçalama ve Android dahili öğelerini zekice değiştirme özelliklerini bir arada kullanarak Android için yinelemeli geliştirmeyi çok daha hızlı hale getirir.

Geleneksel uygulama yüklemeyle ilgili sorunlar

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

  • Dexing'i açın. Varsayılan olarak "dx" derlemede tam olarak bir kez çağrılır ve önceki derlemelerdeki çalışmaların nasıl yeniden kullanılacağını bilmez: Tek bir yöntem değiştirilmiş olsa bile tüm yöntemleri tekrar diske alır.

  • Veriler cihaza yüklenir. 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. Yalnızca küçük parçalar (ör. bir kaynak veya tek bir yöntem) değişmiş olsa bile uygulamanın tamamı yüklenir. Bu nedenle bu durum büyük bir performans sorununa yol açabilir.

  • Yerel koda derleme. Android L, yeni Android çalışma zamanı ART'ı tanıttı. Bu çalışma zamanı, uygulamaları Dalvik gibi tam zamanında derlemek yerine önceden derledi. Bu da uygulamaları, daha uzun yükleme süreleriyle çok daha hızlı hale getirir. Bu, kullanıcıların uygulamayı genellikle bir kez yükleyip birçok kez kullanmaları nedeniyle daha yavaş geliştirmelerine yol açar. Bununla birlikte, uygulamanın birçok kez yüklendiği ve her sürümün en fazla birkaç kez çalıştırıldığı durumlarda daha yavaş geliştirme sonuçları elde edilir.

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 büyüklükte 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ıp ayrı bir mobile-install dizininde depolanır. Bu işlem, uygulamanın tamamını yeniden yüklemeden kod 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.

Parçalı Dexing

Parçalı dexing işlemi makul ölçüde basittir: .jar dosyaları derlendikten sonra, bir araç bunları yaklaşık olarak eşit boyutta ayrı .jar dosyaları halinde parçalara ayırır ve ardından önceki derlemeden bu yana değiştirilen dosyalarda dx yöntemini çağırır. Hangi kırıkların silineceğini belirleyen mantık Android'e özgü değildir: Yalnızca Bazel'in genel değişiklik ayıklama algoritmasını kullanı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ğu kanıtlandı: Bir sınıf eklenir veya kaldırılırsa (iç içe veya anonim bir sınıf olsa bile), bu durum, tüm sınıfların bir birer liste kaydırıldıktan sonra alfabetik olarak değişmesine neden oluyordu. Bu da söz konusu parçaların tekrar kırılmasına neden oluyordu. Bu nedenle, tek tek sınıflar yerine Java paketlerini parçalara ayırmaya karar verildi. Elbette bu işlem, yeni bir paket eklenmesi veya kaldırılması durumunda çok sayıda parçanın dizine eklenmesine neden olur. Ancak bu işlem, tek bir sınıf eklemek veya kaldırmaktan çok daha az gerçekleşir.

Kırık sayısı, BUILD dosyası tarafından kontrol edilir (android_binary.dex_shards özelliği kullanılarak). İdeal bir dünyada Bazel, kaç 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) bilmesi gerekir. Bu nedenle, en uygun parça sayısını belirleyemez, çünkü uygulamada kaç Java sınıfı olacağını bilemez. Derlemenin en iyi yolu, daha hızlı derleme ve daha yavaş uygulama bağlantısıdır. Sorunsuz nokta genellikle 10 ila 50 parçadır.

Artımlı dosya aktarımı

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

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

İlk adımda pek fazla artımlılık yoktur: Uygulama ya yüklüdür ya da yüklü değildir. Bazel, her durumda gerekli olup olmadığını belirleyemeyeceğinden şu anda --incremental komut satırı seçeneğinde bu adımı uygulayıp uygulamayacağını belirtmek için kullanıcıdan yararlanıyor.

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

Cihazdaki bir dosyayı değiştirerek artımlı yükleme algoritmasını kandırmanın mümkün olduğunu, ancak manifest dosyasındaki sağlama toplamını değiştiremeyeceğinizi unutmayın. Bu durum, cihazdaki dosyaların sağlama toplamı hesaplanarak korunabilirdi, ancak yükleme süresinde olacak artışa değmediğine karar verildi.

Saplama uygulaması

Saplama uygulaması, cihazdaki mobile-install dizininden dex'leri, yerel kodu ve Android kaynaklarını yükleme işleminin gerçekleştirildiği yerdir.

Gerçek yükleme, BaseDexClassLoader alt sınıflandırması ile uygulanır ve makul ölçüde iyi belgelenmiş bir tekniktir. Bu işlem, uygulamanın sınıflarından herhangi 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üncellenebilirler.

Bu işlem, uygulamanın sınıflarından herhangi biri yüklenmeden önce gerçekleştirilmelidir. Böylece hiçbir uygulama sınıfının .apk'de yer alması gerekmez. Bu, söz konusu sınıflarda yapılan değişikliklerin tamamen yeniden yükleme gerektirdiği anlamına gelir.

Bu işlem, AndroidManifest.xml içinde belirtilen Application sınıfının sap uygulaması ile değiştirilmesiyle gerçekleştirilir. Bu işlem, uygulama başlatıldığında kontrolü ele alı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 (yapıcısı) uygun şekilde ayarlar.

Saplama uygulamasının yaptığı bir başka şey de mobil yükleme tarafından yüklenen yerel kitaplıkları başka bir konuma kopyalamaktır. Dinamik bağlayıcının dosyalarda X bitinin ayarlanması gerektiğinden bu gereklidir. Ancak bunun kök olmayan bir adb tarafından erişilebilen herhangi bir konum için yapılması mümkün değildir.

Tüm bu işlemler tamamlandıktan sonra, saplama uygulaması gerçek Application sınıfını örnekleyerek Android çerçevesi içindeki 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 tabii ki değişikliğin yapısına bağlıdır: Bir temel kitaplığı değiştirdikten sonra yeniden derleme işlemi daha fazla zaman alır.

Sınırlamalar

Kaba kod uygulamasının gösterdiği püf noktaları her durumda işe yaramaz. Aşağıdaki durumlarda, beklendiği gibi çalışmadığı yerler vurgulanır:

  • Context, ContentProvider#onCreate() içindeki Application sınıfına yayınlandığında. Bu yöntem, uygulama başlatılırken Application sınıfı örneğini değiştirme fırsatımız olmadan çağrılır. Bu nedenle ContentProvider, gerçek uygulama yerine saplama uygulamasına başvurmaya devam eder. Muhtemelen, Context öğelerini bu şekilde düşürmeniz beklenmediği için bu bir hata değildir, ancak Google'daki birkaç uygulamada bu durum 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şirse bu kaynaklar ek olmayan son yüklemeden alınır.

  • ART'yi çalıştırmayan cihazlar. Artık saplama uygulaması Froyo ve sonrasında sorunsuz ş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 yanlış olduğunu düşündüren bir hata içeriyor. Uygulamanız bu hataları gıdıklamadığı 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).