Bu sayfada, ProfilingManager API kullanılarak sistem izinin nasıl kaydedileceği gösterilmektedir.
ProfilingManager, diğer profil türlerini de kaydedebilir. Bu işlem, sistem izi kaydetmeye benzer ancak her tür farklı bir oluşturucu kullanır. Desteklenen profiller ve oluşturucuları şunlardır:
Sistem İzleri: Gecikme analizi ve genel performans hata ayıklama için yararlı olan
SystemTraceRequestBuilderkullanılarak kaydedilir.Yığın dökümleri:
JavaHeapDumpRequestBuilderkullanılarak kaydedilir. Bellek sızıntısı algılama ve optimizasyon için faydalıdır.Yığın profilleri:
HeapProfileRequestBuilderkullanılarak kaydedilir. Bu profiller, bellek optimizasyonu için yararlıdır.Çağrı yığını profilleri:
StackSamplingRequestBuilderkullanılarak kaydedilir. Bu profiller, kod yürütme ve gecikme analizini anlamak için yararlıdır.
Bağımlılık ekleme
ProfilingManager API ile en iyi deneyimi elde etmek için aşağıdaki Jetpack kitaplıklarını build.gradle.kts dosyanıza ekleyin.
Kotlin
dependencies { implementation("androidx.tracing:tracing-ktx:2.0.1") implementation("androidx.core:core:1.19.0") }
Modern
dependencies { implementation 'androidx.tracing:tracing:2.0.1' implementation 'androidx.core:core:1.19.0' }
Sistem izi kaydetme
Gerekli bağımlılıkları ekledikten sonra sistem izi kaydetmek için aşağıdaki kodu kullanın. Bu örnekte, ana iş parçacığı dışındaki ağır işlemleri güvenli bir şekilde yönetirken bir composable'dan profil oluşturma oturumunun nasıl başlatılacağı gösterilmektedir.
Kotlin
@RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
@Composable
fun ProfiledScreen(modifier: Modifier = Modifier) {
// Use the application context: requestProfiling resolves the ProfilingManager
// system service from it, so there's no reason to hand it a short-lived Activity.
val appContext = LocalContext.current.applicationContext
val scope = rememberCoroutineScope()
Button(
onClick = {
// Run the orchestration off the main thread. Profiling a heavy operation
// on the UI thread would freeze the UI (ANR) and distort the very metrics
// you're trying to capture.
//
// Note: this scope is tied to composition. If the user leaves this screen
// mid-session, the coroutine is cancelled and stopSignal.cancel() might not
// run, but setDurationMs() acts as a safety net and ends the trace.
scope.launch(Dispatchers.Default) {
val callbackExecutor = Dispatchers.IO.asExecutor()
val resultCallback = Consumer<ProfilingResult> { profilingResult ->
if (profilingResult.errorCode == ProfilingResult.ERROR_NONE) {
Log.d("ProfileTest", "Result file: ${profilingResult.resultFilePath}")
} else {
// errorMessage explains the failure (e.g., rate limiting); keep it.
Log.e(
"ProfileTest",
"Profiling failed errorCode=${profilingResult.errorCode} " +
"errorMessage=${profilingResult.errorMessage}"
)
}
}
val stopSignal = CancellationSignal()
val requestBuilder = SystemTraceRequestBuilder().apply {
setCancellationSignal(stopSignal)
setTag("FOO") // Caller-supplied tag for identification.
setDurationMs(60000) // Hard cap: ends the session if cancel() never fires.
setBufferFillPolicy(BufferFillPolicy.RING_BUFFER)
setBufferSizeKb(32768)
}
// 1. Start the session. This is asynchronous system IPC. The tracing
// engine takes a moment to start and allocate buffers.
requestProfiling(appContext, requestBuilder.build(), callbackExecutor, resultCallback)
// 2. The API exposes no "profiling started" signal, so pad with a short,
// best-effort delay before running the code you care about. This is
// approximate. Increase it on slower or heavily loaded devices.
delay(STARTUP_PADDING_MS)
// 3. The session is already recording every thread in your app. This slice
// doesn't scope what's captured. It just labels this region of the
// timeline so heavyOperation() is easier to find. trace { } closes the
// section even if the block throws.
trace("MyApp:HeavyOperation") {
heavyOperation()
}
// 4. Stop recording. Until this fires or the setDurationMs() cap is
// reached (whichever comes first), the session keeps capturing app-wide
// activity.
stopSignal.cancel()
}
}
) {
Text("Run & Profile Heavy Operation")
}
}
// Best-effort wait for the system trace engine to initialize before profiling.
// There is no deterministic start callback; tune this for your target devices.
private const val STARTUP_PADDING_MS = 100L
fun heavyOperation() {
// Background computations to profile.
}
Java
void heavyOperation() {
// Computations you want to profile
}
void sampleRecordSystemTrace() {
Executor mainExecutor = Executors.newSingleThreadExecutor();
Consumer<ProfilingResult> resultCallback =
new Consumer<ProfilingResult>() {
@Override
public void accept(ProfilingResult profilingResult) {
if (profilingResult.getErrorCode() == ProfilingResult.ERROR_NONE) {
Log.d(
"ProfileTest",
"Received profiling result file=" + profilingResult.getResultFilePath());
setupProfileUploadWorker(profilingResult.getResultFilePath());
} else {
Log.e(
"ProfileTest",
"Profiling failed errorcode="
+ profilingResult.getErrorCode()
+ " errormsg="
+ profilingResult.getErrorMessage());
}
}
};
CancellationSignal stopSignal = new CancellationSignal();
SystemTraceRequestBuilder requestBuilder = new SystemTraceRequestBuilder();
requestBuilder.setCancellationSignal(stopSignal);
requestBuilder.setTag("FOO");
requestBuilder.setDurationMs(60000);
requestBuilder.setBufferFillPolicy(BufferFillPolicy.RING_BUFFER);
requestBuilder.setBufferSizeKb(32768);
Profiling.requestProfiling(getApplicationContext(), requestBuilder.build(), mainExecutor,
resultCallback);
// Wait some time for profiling to start.
Trace.beginSection("MyApp:HeavyOperation");
heavyOperation();
Trace.endSection();
// Once the interesting code section is profiled, stop profile
stopSignal.cancel();
}
Örnek kod, aşağıdaki adımları uygulayarak profilleme oturumunu oluşturur ve yönetir:
Yürütücüyü ayarlayın. Profil oluşturma sonuçlarını alacak ileti dizisini tanımlamak için
Executoroluşturun. Profil oluşturma işlemi arka planda gerçekleşir. Kullanıcı arayüzü iş parçacığı dışındaki bir iş parçacığı yürütücü kullanmak, geri çağırmaya daha sonra daha fazla işlem eklerseniz Uygulama Yanıt Vermiyor (ANR) hatalarını önlemeye yardımcı olur.Profil oluşturma sonuçlarını işleme
Consumer<ProfilingResult>nesnesi oluşturun. Sistem, bu nesneyi kullanarakProfilingManagerprofil oluşturma sonuçlarını uygulamanıza geri gönderir.Profillendirme isteğini oluşturun. Profil oluşturma oturumunuzu ayarlamak için
SystemTraceRequestBuilderoluşturun. Bu oluşturucu, iz ayarlarınıProfilingManagerözelleştirmenize olanak tanır. Oluşturucuyu özelleştirmek isteğe bağlıdır. Özelleştirmezseniz sistem varsayılan ayarları kullanır.- Bir etiket tanımlayın. İz adına etiket eklemek için
setTag()simgesini kullanın. Bu etiket, izlemeyi tanımlamanıza yardımcı olur. - İsteğe bağlı: Süreyi ayarlayın. Milisaniye cinsinden ne kadar süreyle profil oluşturulacağını belirtmek için
setDurationMs()kullanın. Örneğin,6000060 saniyelik bir izleme ayarlar. Belirtilen süre içindeCancellationSignaltetiklenmezse izleme otomatik olarak sona erer. - Bir arabellek politikası seçin. İzleme verilerinin nasıl depolandığını tanımlamak için
setBufferFillPolicy()kullanın.BufferFillPolicy.RING_BUFFER, arabellek dolduğunda yeni verilerin en eski verilerin üzerine yazılacağı ve son etkinliklerin sürekli olarak kaydedileceği anlamına gelir. - Arabellek boyutu ayarlayın. Çıkış izleme dosyasının boyutunu kontrol etmek için kullanabileceğiniz izleme arabellek boyutunu belirtmek üzere
setBufferSizeKb()seçeneğini kullanın.
- Bir etiket tanımlayın. İz adına etiket eklemek için
İsteğe bağlı: Oturum yaşam döngüsünü yönetin.
CancellationSignaloluşturun. Bu nesne, profil oluşturma oturumunu istediğiniz zaman durdurmanıza olanak tanıyarak süresi üzerinde hassas kontrol sağlar.Başlatın ve sonuçları alın.
requestProfiling()'ı aradığınızda,ProfilingManagerarka planda bir profil oluşturma oturumu başlatır. Profil oluşturma işlemi tamamlandıktan sonraProfilingResult,resultCallback#acceptyönteminize gönderilir. Profillendirme işlemi başarıyla tamamlanırsaProfilingResult,ProfilingResult#getResultFilePatharacılığıyla izlemenin cihazınıza kaydedildiği yolu sağlar. Bu dosyayı programatik olarak veya yerel profilleme için bilgisayarınızdanadb pull <trace_path>komutunu çalıştırarak alabilirsiniz.Özel izleme noktaları ekleyin. Uygulamanızın koduna özel izleme noktaları ekleyebilirsiniz. Önceki kod örneğinde,
trace("MyApp:HeavyOperation") { ... }bloğu oluşturulan profilde özel bir dilim oluşturur.