İş parçacıkları ve bellek

Uygulamanız her yeni iş parçacığı oluşturduğunda işletim sisteminin bu iş parçacığını desteklemek için bellek ayırması gerekir. İş parçacıkları genellikle tam süreçlere kıyasla "hafif" olarak kabul edilse de bellek maliyetleri sıfır değildir. İş parçacığı sızıntısı, Android'de bellek sızıntısına neden olan çok yaygın bir durumdur.

Mesaj dizisinin maliyeti

Android'de bir iş parçacığı oluşturulduğunda iki ana bileşen bellek tüketir:

  1. Yerel yığın: pthread kitaplığı, yerel değişkenleri ve çağrı çerçevelerini depolamak için iş parçacığına bir yığın ayırır. Android'de bu değer genellikle varsayılan olarak 1 MB'tır.
  2. Dahili JVM/Çekirdek Yapıları: ART ve Linux çekirdeği, iş parçacığını izlemek ve yönetmek için veri yapıları (ör. pthread_internal_t ve java.lang.Thread nesneleri) ayırmalıdır.

Yığın bellek ve mmap

Android'in 1 MB'lık yerel yığını mmap ile MAP_ANONYMOUS | MAP_NORESERVE işaretlerini kullanarak ayırdığını anlamak önemlidir.

Bu, işletim sisteminin 1 MB sanal bellek adres alanı ayırdığı ancak hemen 1 MB fiziksel RAM ayırmadığı anlamına gelir. Fiziksel bellek yalnızca iş parçacığı kodu yürütüp verileri yığına aktardığında tahsis edilir (sayfalanır). Hiçbir şey yapmayan bir iş parçacığı, yığını için çok az fiziksel RAM tüketir.

Uygulamalı alıştırma: sızdıran mesaj dizileri

Bir uygulama yüzlerce boş iş parçacığı oluşturduğunda ne olduğunu gözlemlemek için MemoryLab örnek uygulamasını kullanacağız.

1. Lansman ve referans değer

Uygulamayı başlatın ve temel bellek okuması yapın:

adb shell am start -W -n com.android.memorylab/.MainActivity
adb shell dumpsys meminfo -s com.android.memorylab

Çıkıştaki Stack ve Native Heap satırlarına bakın. Bunlar muhtemelen küçük olacaktır.

2. 100 mesaj dizisi oluşturun

Create 100 Threads (100 ileti dizisi oluştur) düğmesine dokunun. Uygulama 100 yeni iş parçacığı oluşturur. Yığın belleğinin fiziksel RAM'e gerçekten sayfa olarak yüklendiğinden (böylece araçlarımızda görebiliriz) emin olmak için her iş parçacığı, beklemeden önce yığınında küçük bir 10 KB'lık dizi ayırır ve bu diziye yazar.

İş parçacıkları etkin durumdayken meminfo komutunu tekrar çalıştırın:

adb shell dumpsys meminfo -s com.android.memorylab

Sonuçlar:

Yeni çıkışı referansınızla karşılaştırın. İş parçacıkları etkin durumdayken önemli artışlar göreceksiniz:

  • Stack: Bir megabayt veya daha fazla artırıldı. Bu, 100 iş parçacığı yığını için ayrılan fiziksel sayfaları temsil eder (her biri en az 10 KB'a dokunur).
  • Native Heap / Private Other: Sistem tarafından her ileti dizisi için ayrılan dahili pthread yapıları nedeniyle artırıldı.

Temizlemek için Tüm Mesaj Dizilerini Yok Et düğmesine dokunun.

3. Perfetto'da ileti dizilerini görüntüleme

Perfetto, iş parçacığı yaşam döngülerini ve sayılarını zaman içinde izlemek için idealdir.

Perfetto kullanıcı arayüzünün ekran görüntüsü. Etkin iş parçacıklarının sayısını ve memorylab uygulamasında başlayan ve çıkan iş parçacıklarını gösteren bir sayaç kanalı gösteriliyor.

İş parçacığı analizi için PerfettoSQL

Uygulama tarafından tam olarak kaç iş parçacığı oluşturulduğunu saymak için izi sorgulayabilirsiniz:

SELECT p.name AS process_name, COUNT(t.id) as thread_count
FROM thread t JOIN process p USING (upid)
WHERE p.name = 'com.android.memorylab' AND t.name LIKE 'LeakedThread-%';

Bunun gibi bir sorgu, ekran görüntüsünde gösterildiği gibi sayaç içeren bir hata ayıklama kanalı oluşturmak için kullanılabilir.


← Uygulama kodu | ↑ Yukarı | Yerellik →