bazel mobil yükleme

Sorun bildirin 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. Burada, bu yaklaşımın avantajlarına kıyasla geleneksel uygulama yükleme yönteminin zorlukları açıklanmaktadı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. USB üzerinden ART (Dalvik değil) çalıştıran cihazınızı bağlayın ve USB hata ayıklama özelliğini etkinleştirin.
  6. bazel mobile-install :your_target çalıştır. 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 çalıştır.
  9. Çok fazla beklemek zorunda kalmayın.

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

  • --adb, Bazel'e hangi adb ikili programını kullanacağını bildirir
  • --adb_arg, adb komut satırına fazladan bağımsız değişkenler eklemek için kullanılabilir. Bu özelliğin kullanışlı bir uygulamalarından biri, iş istasyonunuza bağlı birden fazla cihazınız varsa yüklemek istediğiniz cihazı seçmektir: bazel mobile-install --adb_arg=-s --adb_arg=<SERIAL> :your_target
  • --start_app, uygulamayı otomatik olarak başlatır

Şüpheye düştüğünüzde ö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örmek ile değişikliklerin beklediğiniz gibi olup olmadığıyla ilgili geri bildirim almak için dakikalar, bazen saatler boyunca beklemek zorunda kalmak arasında çok büyük bir fark vardır.

Maalesef, .apk oluşturmaya yönelik geleneksel Android araç zinciri, birçok monolitik, sıralı adım gerektirir ve bunların hepsinin bir Android uygulaması geliştirmek için tamamlanması 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 durum değildi.

bazel mobile-install, değişiklikleri budama, iş parçalama ve Android dahili bileşenleri üzerinde zekice değiştirme gibi yöntemleri bir arada kullanarak Android için yinelemeli geliştirmeyi çok daha hızlı hale getirir. Üstelik tüm bunları uygulamanızın hiçbir kodunu değiştirmeden yapar.

Geleneksel uygulama yüklemeyle ilgili sorunlar

Android uygulaması oluştururken aşağıdakiler gibi bazı sorunlar var:

  • Dexing. Varsayılan olarak "dx", derlemede tam olarak bir kez çağrılır ve önceki derlemelere ait çalışmaların nasıl yeniden kullanılacağını bilmez. Yalnızca bir yöntem değiştirilmiş olsa bile her yöntem için yeniden deneme yapılır.

  • Veriler cihaza yükleniyor. Adb, USB 2.0 bağlantısının tam bant genişliğini kullanmaz ve daha büyük uygulamaların yüklenmesi uzun sürebilir. Bir kaynak veya tek bir yöntem gibi yalnızca küçük kısımları değişmiş olsa bile uygulamanın tamamı yüklenir. Bu nedenle bu büyük bir performans sorunu olabilir.

  • Yerel kod derlemesi. Android L, uygulamaları Dalvik gibi tam zamanında derlemek yerine önceden derleyen yeni Android çalışma zamanı ART'ı kullanıma sundu. Bu da daha uzun yükleme süreleri karşılığında uygulamaları çok daha hızlı hale getirir. Kullanıcılar bir uygulamayı genellikle bir kez yükleyip birçok kez kullandığı için bu durum iyi bir performanstır. Ancak uygulamanın birçok kez yüklendiği ve her sürümün en fazla birkaç kez çalıştırıldığı durumlarda geliştirme sürecinin yavaş olmasına yol açar.

bazel mobile-install yaklaşımı

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

  • Parçalı dexing. Bazel, uygulamanın Java kodunu oluşturduktan sonra sınıf dosyalarını yaklaşık olarak eşit büyüklükteki parçalara ayırır ve dx öğesini bu dosyalarda ayrı olarak çağırır. dx, son derlemeden bu yana değişmeyen kırıklarda ç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 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ı bölümleri .apk dışından yükleniyor. .apk'ye Android kaynaklarını, Java kodunu ve yerel kodu cihaz üzerinde mobil yükleme dizininden yükleyen ve ardından kontrolü gerçek uygulamaya aktaran küçük bir saplama uygulaması yerleştirilir. Aşağıda açıklanan bazı özel durumlar dışında bunların tamamı uygulamaya şeffaf bir şekilde aktarılır.

Parçalı Dex Oluşturma

Parçalama işlemi makul ölçüde basittir: .jar dosyaları oluşturulduktan sonra, bir araç bunları yaklaşık olarak aynı boyutta ayrı .jar dosyaları halinde parçalara ayırır ve ardından, önceki derlemeden bu yana değiştirilmiş olan dosyalarda dx yöntemini çağırır. Hangi parçaların ayrıştırılacağını belirleyen mantık Android'e özgü değildir: Yalnızca Bazel'in genel değişiklik budama algoritmasını kullanır.

Parçalama algoritmasının ilk sürümü sadece .class dosyalarını alfabetik olarak sıralar ve ardından listeyi eşit boyutlu parçalara ayırır. Ancak bunun optimum olmadığı kanıtlanmıştır: Bir sınıf eklenir veya kaldırılırsa (iç içe yerleştirilmiş veya anonim bir sınıf olsa bile), tüm sınıflar alfabetik olarak kayarak bu parçaların tekrar çıkarılmasına neden olur. Bu nedenle, tek tek sınıflar yerine Java paketlerini parçalamaya karar verildi. Elbette bu durum, yeni bir paket eklendiğinde veya kaldırıldığında çok sayıda parçanın dizinlenmesine neden olur. Ancak bu, tek bir sınıfın eklenmesi veya kaldırılmasından çok daha azdır.

Kırık sayısı, BUILD dosyası tarafından kontrol edilir (android_binary.dex_shards özelliği kullanılarak). İdeal bir dünyada Bazel, en iyi kaç parçanın uygun olduğunu otomatik olarak belirler. Fakat Bazel'in bunlardan herhangi birini çalıştırmadan önce işlem grubunu (örneğin, derleme sırasında yürütülecek komutlar) bilmesi gerekir. Bu nedenle uygulamada kaç Java sınıfı olacağını bilemediği için ideal kırık sayısını belirleyemez. Çünkü uygulamada kaç tane Java sınıfı olacağını bilemez, bağlantı da ne kadar hızlıysa derleme de o kadar yavaş olur. İş için ideal nokta genellikle 10 ila 50 parçadı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 (genellikle adb install kullanılarak)
  2. .dex dosyalarını, Android kaynaklarını ve yerel kitaplıkları mobil yükleme dizinine yükleme

İlk adımda çok fazla artımlılık yoktur: Uygulama yüklü veya yüklü değildir. Şu anda Bazel, her durumda gerekli olup olmadığını belirleyemediğinden, bu adımı --incremental komut satırı seçeneği üzerinden yapması gerekip gerekmediğini belirtmelidir.

İkinci adımda, derlemedeki uygulamanın dosyaları, cihazda hangi uygulama dosyalarının bulunduğunu ve bunların sağlamalarını 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 dosyası 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ı yanıltmanın mümkün olduğunu, ancak manifest dosyasındaki sağlama toplamını değiştirmemenin mümkün olduğunu unutmayın. Cihazdaki dosyaların sağlama toplamı bu riske karşı korunabilirdi, ancak yükleme süresindeki artışa değmeyeceğine karar verildi.

Stub uygulaması

Stub uygulaması, cihaz üzerindeki mobile-install dizininden dex'ler, yerel kod ve Android kaynaklarını yüklemenin en güzel yoludur.

Gerçek yükleme, BaseDexClassLoader alt sınıflandırması yapılarak uygulanır ve makul şekilde iyi belgelenmiş bir tekniktir. Bu işlem, uygulamanın herhangi bir sınıfı yüklenmeden önce gerçekleşir. Böylece, apk'de bulunan uygulama sınıfları, cihaz üzerindeki mobile-install dizinine eklenebilir. Böylece, adb install olmadan güncellenebilirler.

Bu işlemin, uygulamanın herhangi bir sınıfı yüklenmeden önce yapılması gerekir. Böylece, .apk'de uygulama sınıfı bulunmaz. Bu da bu sınıflarda yapılan değişiklikler için tamamen yeniden yükleme yapılması gerektiği anlamına gelir.

Bu işlem, AndroidManifest.xml politikasında belirtilen Application sınıfının stub uygulaması ile değiştirilmesiyle gerçekleştirilir. Bu, uygulamanın başlatılacağı zamanı kontrol altına alır ve Android çerçevesinin dahili öğeleri hakkındaki Java yansımalarını kullanarak sınıf yükleyicisi ile kaynak yöneticisini en kısa zamanda (oluşturucusu) uygun şekilde düzenler.

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 işlem gereklidir. Kök olmayan adb tarafından erişilebilen hiçbir konum için bu işlem yapılamaz.

Tüm bunlar yapıldıktan sonra, saplama uygulaması gerçek Application sınıfını örneklendirir ve tüm referansları Android çerçevesinde asıl uygulamayla değiştirir.

Sonuçlar

Performans

Genel olarak, bazel mobile-install, küçük bir değişiklikten sonra büyük uygulamaların geliştirilme ve yüklenme hızlarında 4 ila 10 kat artış sağlar.

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

Bu, elbette değişikliğin yapısına bağlıdır: Temel kitaplığın değiştirilmesinden sonra yeniden derleme işlemi daha fazla zaman alır.

Sınırlamalar

Saplama uygulamasında yapılan hileler her durumda işe yaramaz. Aşağıdaki durumlarda, işlevin beklendiği gibi çalışmadığı durumlar vurgulanır:

  • Context, ContentProvider#onCreate() içindeki Application sınıfına yayınlandığında. Bu yöntem, Application sınıfı örneğini değiştirme fırsatı bulmadan önce uygulama başlatılırken çağrılır. Bu nedenle, ContentProvider gerçek uygulama yerine saplama uygulamasına başvuruda bulunur. Context ürününü bu şekilde eski sürüme geçirmeniz gerekmediği için bu durumun bir hata olduğunu söyleyemeyiz ancak bu durum, Google'daki birkaç uygulamada yaşanmaktadır.

  • bazel mobile-install tarafından yüklenen kaynaklara yalnızca uygulama içinden erişilebilir. Kaynaklara diğer uygulamalar PackageManager#getApplicationResources() üzerinden erişiyorsa bu kaynaklar ek olmayan son yükleme işleminden elde edilir.

  • ART çalışmayan cihazlar. Saplama uygulaması Froyo ve sonraki sürümlerde iyi performans gösterse de Dalvik, belirli durumlarda (ör. Java ek açıklamaları belirli bir şekilde) kodun birden çok .dex dosyasına dağıtılması durumunda uygulamanın hatalı olduğunu düşünmesine neden olan bir hataya sahiptir. Uygulamanız bu hataları gidermediği sürece Dalvik ile çalışmalıdır (ancak eski Android sürümlerini desteklemenin tam olarak odak noktamız olmadığını unutmayın.)