Mobil Programlama

Android

Verimli Ağ Erişimi için İndirmeleri Yönetmek

Lisans: Creative Commons 26.11.2020 tarihinde güncellendi
Bakabileceğiniz Etiketler: Eğitmen: Geleceği Yazanlar Ekibi

Veri indirmek için kablosuz ağ yayınını kullanmak, uygulamanızın en büyük pil harcama nedenlerinden biridir. Ağ işlemlerinizden kaynaklanan pil kullanımını en aza indirmek için, kullandığınız bağlantı modelinin arkaplandaki yayın donanımına nasıl etkileri olduğunu iyi anlamanız gerekir.

Bu eğitim, kablosuz ağ yayını durum makinelerini (state machine) tanıtır, uygulamanızın bağlantı modelinin ağ yayını durum makineleri ile etkileşimini anlatır ve veri bağlantınızı azaltıp, önceden indirmeyi kullanarak veri transferine bağlı pil kullanımı azaltmanın yollarını gösterir.

 

Ağ yayını durum makinesi (Radio state machine)

Tümüyle aktif durumdaki kablosuz ağ yayını çok yüksek derecede güç harcar. Ağ yayını kullanılmadığı durumlarda harcama yapmamak için değişik enerji durumlarına geçişler yapar; bu aynı zamanda ağ yayınını ihtiyaç olduğunda tekrar açmak için gereken gecikmeyi de en aza indirir.

Tipik bir 3G ağ yayını durum makinesi 3 çeşit enerji durumuna sahiptir:

  1. Tam Güç (Full Power): Bir bağlantının aktif olması durumudur, cihazın mümkün olan en yüksek oranla veri aktarmasına izin verir.
  2. Düşük Güç (Low Power): Tam durumda pil gücünün sadece yüzde 50'sini kullanan ara geçiştir.
  3. Bekleme (Standby): Hiçbir ağ bağlantısı olmaması durumunda kullanılan en düşük enerji durumudur.

Düşük güç ve bekleme durumları çok az pil harcasalar da ağ isteklerine çok fazla gecikme yansıtırlar. Düşük güç durumundan tam güç durumuna geçmek yaklaşık 1,5 saniye, bekleme durumundan tam güç durumuna geçmek ise 2 saniyeden fazla zaman alır.

Gecikmeyi en aza indirmek için, durum makinesi daha düşük enerji durumlarına geçişi ertelemek için ek bir geciktirme zamanı kullanır. Aşağıda AT&T'nin tipik bir 3G ağ yayını kullandığı zamanlamaları görebilirsiniz:

Her cihazdaki ağ yayını durum makinesi dolayısıyla da bağlantılı değişim gecikme süresi (tail-time) ve başlangıç gecikme süresi kablosuz ağ yayını teknolojisine (2G, 3G, LTE, vs.) bağlı olarak değişir ve cihazın yönettiği taşıyıcı ağ ile tanımlanır, ayarlanır.

Bu eğitim, AT&T'nin sağladığı verilere göre çalışan temsili bir 3G kablosuz ağ yayını durum makinesini anlatacak. Her ne kadar tek bir durum makinesine göre anlatılıyor gibi görünse de, genel prensipler ve alınan sonuçlar tüm kablosuz ağ yayını çeşitlerine uyumludur.

Bu geciktirme yaklaşımı öncelikli olarak tipik İnternet gezintilerinde verimlidir çünkü kullanıcılar İnternet'te gezerken yaşanan gecikmelerden hiç hoşlanmazlar. Düşük değişim gecikme süresi (tail-time) gezinme bittiği zaman ağ yayınının bir düşük enerji seviyesine geçeceğini garanti eder.

Maalesef bu yaklaşım, Android gibi uygulamaların hem önplan (gecikmenin önemli bir sorun olduğu) hem de arkaplanda (pil ömrüne dikkat edilmesi gereken) çalıştığı modern akıllı telefon işletim sistemlerinde verimsiz sonuçlara neden olabilir.

 

Uygulamalar ağ yayını durum makinesine nasıl etki eder?

Her yeni bağlantı kurduğunuzda, ağ yayını da tam güç durumuna geçer. Yukarıda bahsedilen tipik 3G bağlantısı, aktarımınızın süresi boyunca tam güçte kalır ve 5 saniye geçiş için eklenen süreye ek olarak 12 saniye düşük enerji seviyesinde bekler. Bu durum, tipik bir 3G bağlantısı için her aktarımda yaklaşık 20 saniyelik güç kullanımı anlamına gelir.

Pratikte uygulama, bağımsız veriyi 1 saniyede indirirken 18 saniye kablosuz ağ yayınını sürekli aktif tutup beklemeye geçtiği gibi tam güç durumuna geçirecektir. Bunun sonucunda da ağ yayını her bir dakikanın 18 saniyesinde tam güç durumunda, 42 saniyesinde ise düşük güç durumunda pil harcayacaktır.

Aynı uygulama, bağımlı veri transferi yaptığında ise her dakikanın 3 saniyesinde transfer yapıp, ağ yayınını 8 saniye tam güç durumunda, ek 12 saniye de düşük güç durumunda tutacaktır.

İkinci örnekte ağ yayının her dakika ek 40 saniye boşta beklediğini bunun da pil harcamasında ciddi bir düşüş sağladığını görebiliriz.

 

Önceden veri indirme

Veriyi önceden indirme (prefetching), başına buyruk veri transferlerinin sayısını azaltmak için çok verimli bir yöntemdir. Önceden indirmek istediğiniz verinin tamamını, verilen zaman aralığında tek seferde ya da tek bağlantı üzerinden tam kapasiteli olarak indirmenizi sağlar.

Transferlerinizi önceden yükleyerek, gerekli verinin indirilmesi için gereken ağ yayını aktivitelerinin sayısını azaltmış olursunuz. Bunun sonucunda sadece pil ömrünü korumakla kalmaz aynı zamanda gecikmeyi azaltır, gereken bant genişliğini azaltır, indirme sayılarınızı düşürürsünüz.

Önceden indirme kullanıcının bir işlemi yapmadan önce ya da veri indirirken beklediği süreyi azaltarak aynı zamanda kullanıcı deneyemini de geliştirmiş olur.

Bu yöntem çok fazla kullanıldığı zaman, gereksiz verinin de indirilmesine, dolaylı olarak da bant genişliği ve pil harcamasının artmasına, indirme kotasının dolmasına sebebiyet verebilir. Aynı zamanda önceden indirmenin, uygulamanın açılma süresine etki etmediğine de dikkat etmek gerekir. Pratik olarak konuşacak olursak, işlenecek verinin ve arka arkaya yapılan indirmelerin artmasına sebep olabiliceğinden, indirilmesi gereken verinin öncelik sırasına dikkat etmek gerekir.

Önceden indirmenin ne kadar çok kullanıldığı indirilen verinin büyüklüğü ve nerede kullanıldığı ilişkisine göre değişir. Kabaca yukarıdaki ağ yayını durum makinesinin tanımına baktığımızda, mevcut oturumda yüzde 50 oranla kullanılma olasılığı olan bir veriyi yaklaşık 6 saniye (yaklaşık 1-2 MB) önceden indirme yaparsanız maliyeti, hiç indirilmemiş olmasının vereceği kârı geçmez.

Genelde bir sonraki indirmeyi 2 ila 5 dakika sonra yapacağınız, 1 ila 5 MB arasındaki veriyi önceden indirmeniz sizin için faydalı olacaktır. Bu durum video gibi büyük indirmelerin parçalar halinde 2 ila 5 dakika aralıklarla yapılıp, videonun sonraki birkaç dakikasının önceden yüklenerek verim sağlanması anlamına gelecektir.

Gelecekte yapacağınız indirmeler bir sonraki kısımda anlatılacağı gibi paketler halinde olmalıdır. Anlatılacak kısımdaki sayılar bağlantı tipi ve hızına göre değişecektir, bu durum da İndirme Kalıplarının Bağlantı Tipine Göre Düzenlenmesi eğitiminde anlatılmıştır.

Birkaç pratik örneğe bakacak olursak:

Müzik Çalar: Bir albümün tamamını önceden indirmek isteyebilirsiniz ancak eğer kullanıcı ilk şarkıdan sonra dinlemeyi bırakırsa epey büyük miktarda bir bant genişliğini ve pil ömrünü boşa harcamış olursunuz.

Çalanın yanında fazladan bir şarkıyı yedeğe almak, daha akılcı bir yöntem olabilir. Müzik akışı (streaming) oluşturmak için tüm akışı kesintisiz olarak kullanmak ağ yayınını sürekli aktif tutacaktır. Bunun yerine HTTP'den canlı akış sağlamak ve sesi sadece parçalar halinde almak, yukarıda anlatılan önceden yükleme yaklaşımına benzer olacaktır.

Haber Okuyucu: Pek çok haber uygulaması bant genişliği kullanımını bir kategori seçildikten sonra sadece başlıkları indirerek, tam sayfaları sadece kullanıcı okumak istediğinde, küçük resimleri de sadece üstüne geldiğinde indirerek azaltır. Bu yaklaşım ile ağ yayını, pek çok kullanıcı için başlıkları gezindikçe, kategori değiştirdikçe ya da haber okudukça aktif halde kalacaktır ve aynı zamanda sürekli güç değişimi olacaktır.

Açılışta haberlerin başlıkları ve küçük resimlerini içeren makul miktarda veriyi önceden yükleyerek gecikme vaktinizi azaltmayı garanti ettikten sonra geriye kalan başlık, küçük resim ve popüler olandan başlayarak haber içeriklerini yüklemek, daha iyi bir çözümdür.

Başka bir alternatif ise arkaplanda planlanmış şekilde tüm başlık, küçük resim ve hatta haberlerin tüm fotoğraflarını önceden yüklemek olabilir. Bu yöntem kullanılmayacak olan veriler için de ciddi miktarda bant genişliği ve pil ömrü harcanılması anlamına geldiğinden çok dikkatli biçimde kullanılmalıdır.

Tüm indirmeleri planlamak için bir başka çözüm ise indirmeleri sadece Wi-Fi bağlantısı varsa ve telefon şarja takıldığı zaman yapmak. Bu yöntem İndirme Kalıplarının Bağlantı Tipine Göre Düzenlenmesi içeriğinde detaylı olarak anlatılmıştır.

 

Aktarmaları ve bağlantıları gruplamak

Tipik bir 3G kablosuz ağ yayını kullanarak her bağlantı oluşturduğunuzda veri aktarımının büyüklüğüyle alakasız olarak yaklaşık 20 saniye güç harcarsınız.

Kullanıcının gördüğünü veya uygulamanın çalıştığını kontrol etmek için sunucuyu her 20 saniyede bir yoklayan uygulama, ağ yayınının sürekli güç kullanmasına sebep olarak hiçbir veri aktarımı olmamasına rağmen epey fazla pil harcayacaktır.

Bunu akılda tutarak veri aktarımlarınızı paketlemek ve bir aktarma sırası oluşturmak oldukça önemlidir. Doğru yapıldığında, aktarmaları verimli bir şekilde kaydırabilir hepsinin eş zamanlı olarak gerçekleşmesini sağlayabilirsiniz. Bu sayede de ağ yayınının mümkün olan en kısa süre için güç harcamasını sağlayabilirsiniz. Bu yaklaşım ile her aktarım seansında mümkün olan en fazla veriyi transfer ederek ihtiyacınız olacak seansların sayısını azaltabilirsiniz.

Bu, aktarmalarınızı sıralı ve gecikme toleransı olanlara göre paketlemeniz gerektiğini, planlanmış güncellemeler ve önceden indirmelere öncelik vermeniz gerektiğini gösterir. Bu sayede hepsinin zamanlamalı aktarma gerektiğinde gerçekleşmesini sağlarsınız. Benzer şekilde, planlanmış güncellemeleriniz ve düzenli önceden indirmeleriniz bekleyen aktarma sıranızı başlatmalıdır.

Örneklere bakmak için yukarıda bahsettiğimiz Önceden Veri İndirme kısmına bakabilirsiniz.

Daha önce bahsettiğimiz önceden indirme düzenini kullanan haber uygulamasını ele alalım. Haber okuyucular kullanıcılarının okuma kalıplarını çıkarmak ve en popüler öyküleri sıralamak için bilgi analizi yaparak veri toplarlar. Haberleri taze tutmak için güncellemeleri her saat kontrol ederler. Bant genişliğini korumak için her makalenin tam fotoğrafını indirmek yerine sadece küçük resimleri önceden indirip, tam fotoğrafları sadece seçildiğinde indirmek gerekir.

Bu örnekte uygulamanın topladığı tüm analiz bilgilerini hemen indirmek yerine birarada tutmak ve indirmek için sıraya sokmak gerekir. Sonuçta ortaya çıkacak olan paket, tam boyutlu fotoğraf indirilirken ya da saatlik güncelleme yapılırken indirilebilir.

Her zamanlamalı (time-sensitive) veya anlık (on-demand) aktarım - tam boyutlu fotoğraf indirmek gibi- tüm zamanlamış güncellemelerden öne alınmalıdır. Planlanmış güncelleme anlık indirme ile aynı zamanda işleme alınır ve belirlenen aralıktan sonrasına sıradaki güncellemenin ayarlanması gerekir.

Bu yaklaşım, gerekli ve zamanlamalı fotoğraf indirmesi için sıradan bir yüklenici güncellemenin yapacağı harcamayı azaltır.

 

Bağlantıları azaltmak

Genelde yeniden bağlantı oluşturmaktansa mevcut bağlantıları kullanmak daha verimlidir. Bağlantıları yenidek kullanmak aynı zamanda oluşacak sıkışıklıklara ve benzer ağ sorunlarına daha akıllıca yaklaşmayı sağlar.

Veri indirmek için birden çok bağlantıyı eşzamanlı olarak yaratmak ya da birden çok GET metodunu arka arkaya çağırmak yerine bütün istekleri tek bir GET metoduna koymanız gerekir.

Örneğin, tek bir cevapta gelebilecek haber metinlerini birden çok sorgu yerine tek bir sorguya koymak daha verimlidir. Kablosuz ağ yayınları, bağlantıları kapatmak için sunucu ve vericide kullandıkları zaman aşımı süresine kadar aktif kalırlar, onun yerine bağlantıları kullanılmadığı zaman kapatmak, zaman aşımı süresi için beklemekten daha iyidir.

Buna rağmen bazen bir bağlantıyı yeniden kullanılabilecekken erken kapatıp yenisini açmak, fazladan bir yükleme olmasına neden olur. Bu sebeple bağlantıyı anında kapatmak yerine doğal oluşan zaman aşımı süresini beklemek daha mantıklıdır.

 

DDMS ağ trafiği aracını endişe edilecek alanları tespit için kullanın

Uygulamanızın ne zaman yeni ağ istekleri yaptığını, Android DDMS (Dalvik Debug Monitor Server)'ın içindeki Detaylı Ağ Kullanımı (Detailed Network Usage) sekmesinden takip edebilirsiniz. Bu aracı kullanarak uygulamanızın ne zaman ve nasıl veri aktarımı yaptığını gözlemleyip, kodunuzu buna göre düzenleyebilirsiniz.

Alttaki şekilde küçük parçalı verinin kabaca 15 saniyelik aralıklarla aktarılması kalıbını görebilirsiniz. Bu sayede her isteği önceden indirme ile ya da yüklemeleri paketleyerek verimliliği ciddi biçimde artırmanın mümkün olduğunu görebiliriz.

Veri transferlerinizin sıklığını ve her bağlantıda aktarılan veri miktarını gözlemleyerek uygulamanızın iyileştirilmesi ve daha az pil harcaması için gerekli olan alanları saptayabilirsiniz. Çıkan grafikte göreceğiniz çıkıntılı şekillerdeki paketleri ertelemeye ya da daha sonra aktarılmasına öncelik vermeye çalışmalısınız.

Aktarım çıkıntılarını daha iyi belirleyebilmek için Traffic Stats API size TrafficStats.setThreadStatsTag() metodunu sunar. Bu metod sayesinde veri aktarmalarınızı etiketleyebilirsiniz. Bir başka yöntem ise soket kullanarak elle etiketleme veya etiketi kaldırmaktır. tagSocket() ve untagSocket() metodları bu işe yarar. Örneğin,

 

TrafficStats.setThreadStatsTag(0xF00D);
TrafficStats.tagSocket(outputSocket);
// Transfer data using socket
TrafficStats.untagSocket(outputSocket);

 

Apache HttpClient ve URLConnection kütüphaneleri soketleri currentgetThreadStatsTag() metodundan gelen değere göre otomatik olarak etiketler. Bu kütüphaneler aynı zamanda geridönüş havuzunu canlı tutmak adına soketleri etiketleyebilir ya da etiketlerini kaldırabilir.

 

TrafficStats.setThreadStatsTag(0xF00D);
try {
  // Make network request using HttpClient.execute()
} finally {
  TrafficStats.clearThreadStatsTag();
}

 

Soket etiketleme Android 4.0 sürümünde desteklenmektedir ancak gerçek zamanlı istatistikler sadece Android 4.0.3 ve üstü sürümleri içeren cihazlarda gösterilebilir.

 

Bu sayfadaki metinler Android Open Source Project kapsamında oluşturulmuş ve paylaşılmış içeriğin küçük değişiklikler yapılmış hâlidir ve Creative Commons 2.5 Attribution License'ta belirlenen koşullara göre kullanılmıştır.

Bu eğitim içeriğinin orijinal hâline buradan ulaşabilirsiniz: Optimizing Downloads for Efficient Network Access