앱 기반 프로필을 캡처하든 트리거 기반 프로필을 캡처하든 ProfilingManager는 완료된 파일을 기기에 저장하고 ProfilingResult를 등록된 콜백에 전달합니다. ProfilingResult.getResultFilePath를 호출하여 저장된 프로필의 경로를 가져옵니다.
- 로컬 테스트 중:
adb를 사용하여 파일을 컴퓨터로 가져옵니다. - 프로덕션: 프로필을 압축하고 서버에 업로드하는
WorkManager작업의 경로를 전달합니다.
기기에서 프로필 가져오기
이 섹션에서는 ProfilingManager가 기기에서 프로필을 저장하는 위치, 자동 파일 삭제의 작동 방식, adb를 사용하여 로컬에서 파일을 가져오는 방법을 설명합니다.
파일 위치 및 이름 지정 형식
ProfilingManager는 수정된 프로필을 /data/user/0/<app>/files/profiling/의 앱별 저장소 디렉터리에 저장합니다. 파일 이름 형식은 프로필이 캡처된 방식에 따라 다릅니다.
앱 기반 프로필:
profile_<tag>_<datetime>_uid-<uid>.<profile-type-ext>프로필을 요청할 때 태그가 제공되지 않은 경우
<tag>_가 생략됩니다(profile_<datetime>_uid-<uid>.<profile-type-ext>).트리거 기반 프로필:
profile_trigger-type-<trigger_type>_<datetime>_uid-<uid>.<profile-type-ext>
각 항목의 의미는 다음과 같습니다.
<app>은 앱의 패키지 이름입니다.<tag>은setTag로 구성되거나requestProfiling에 전달된 호출자 제공 태그의 처음 20자(영문 기준)까지의 영숫자 문자(및 하이픈)이며,a-z,0-9,-이외의 문자는 삭제되고 소문자로 변환됩니다.<trigger_type>는ProfilingTrigger의 트리거에 대한 정수 상수 코드입니다. 파일 이름을 파싱하는 대신 코드에서 항상ProfilingResult.getTriggerType를 호출합니다.<datetime>는 프로필이 기록된 날짜 및 시간입니다(yyyy-MM-dd-HH-mm-ss-SSS).<uid>는 앱의 Linux 사용자 ID입니다(최근Profiling모듈 버전에 포함됨).<profile-type-ext>은 캡처된 프로필 유형의 파일 확장자입니다.- 시스템 트레이스의 경우
.perfetto-trace - Java 힙 덤프의 경우
.perfetto-java-heap-dump - 힙 프로필의 경우
.perfetto-heap-profile .perfetto-stack-sample: 스택 샘플링 프로필
- 시스템 트레이스의 경우
기기 내 저장 및 정리
기기 저장용량을 즉시 확보하려면 업로드가 완료된 직후 업로드 작업자의 각 프로필 파일을 삭제하세요. 자동 정리는 ProfilingManager가 앱에 결과를 전송할 때만 실행되므로 캠페인이 종료된 후 앱이 콜백 등록을 중지하면 업로드되지 않은 파일이 디스크에 남아 있을 수 있습니다. 최신 Profiling 모듈 버전의 대체 기능으로 ProfilingManager는 새 결과가 전송될 때 앱별 저장소 디렉터리에서 5일이 지난 전송된 파일을 자동으로 삭제합니다.
WorkManager를 사용하여 프로덕션에서 프로필 업로드
프로필 파일은 크기가 수 메가바이트일 수 있으므로 기기가 무제한 네트워크(Wi-Fi)에 연결되어 있고 충전 중이며 유휴 상태일 때 백그라운드에서 프로덕션 업로드를 예약합니다.
업로드하기 전에 프로필 파일을 압축합니다(예: GZIPOutputStream 또는 ZipOutputStream 사용). Perfetto protobuf 프로필과 Java 힙 덤프는 크게 압축되어 네트워크 대역폭과 백엔드 스토리지 비용을 줄입니다.
WorkManager 종속 항목 추가
ProfilingManager는 클라우드에 구애받지 않으므로 WorkManager를 사용하여 모든 백엔드에 프로필 업로드를 예약할 수 있습니다. WorkManager 라이브러리를 build.gradle.kts 파일에 추가합니다.
Kotlin
dependencies { implementation("androidx.work:work-runtime:2.12.0") }
Groovy
dependencies { implementation 'androidx.work:work-runtime:2.12.0' }
업로드 작업 예약
앱이 ProfilingResult를 수신하면 업로드 작업을 예약합니다. 다음 예시에서는 초기 프로파일링 요청을 생략합니다. 전체 요청 예시는 시스템 트레이스 기록을 참고하세요.
Kotlin
class TraceUploadWorker(context: Context, workerParams: WorkerParameters) : Worker(context, workerParams) { override fun doWork(): Result { // Perform your uploading work here Log.d("ProfileTest", "Uploading trace: " + inputData.getString("PROFILE_PATH")) return Result.success() } } fun setupProfileUploadWorker(profileFilepath: String?) { val workMgr = WorkManager.getInstance(applicationContext) val workRequestBuilder = OneTimeWorkRequest.Builder(TraceUploadWorker::class) val constraints = Constraints.Builder() .setRequiredNetworkType(NetworkType.UNMETERED) .setRequiresDeviceIdle(true) .setRequiresCharging(true) .build() workRequestBuilder.setConstraints(constraints) val inputDataBuilder = Data.Builder() inputDataBuilder.putString("PROFILE_PATH", profileFilepath) workRequestBuilder.setInputData(inputDataBuilder.build()) workMgr.enqueue(workRequestBuilder.build()) }
자바
public static class TraceUploadWorker extends Worker { public TraceUploadWorker( @androidx.annotation.NonNull Context context, @androidx.annotation.NonNull WorkerParameters workerParams) { super(context, workerParams); } @androidx.annotation.NonNull @Override public Result doWork() { // Perform your uploading work here Log.d("ProfileTest", "Uploading trace: " + getInputData().getString("PROFILE_PATH")); return Result.success(); } } public void setupProfileUploadWorker(String profileFilepath) { WorkManager workMgr = WorkManager.getInstance(getApplicationContext()); OneTimeWorkRequest.Builder workRequestBuilder = new OneTimeWorkRequest.Builder( TraceUploadWorker.class); Constraints constraints = new Constraints.Builder() .setRequiredNetworkType(NetworkType.UNMETERED) .setRequiresDeviceIdle(true) .setRequiresCharging(true) .build(); workRequestBuilder.setConstraints(constraints); Data.Builder inputDataBuilder = new Data.Builder(); inputDataBuilder.putString("PROFILE_PATH", profileFilepath); workRequestBuilder.setInputData(inputDataBuilder.build()); workMgr.enqueue(workRequestBuilder.build()); }
코드 둘러보기
위의 예시에서는 다음 단계를 수행합니다.
- 작업자 정의:
Worker를 확장하는TraceUploadWorker클래스를 만듭니다.doWork를 구현하여 프로필 파일이 여전히 존재하는지 확인하고, 백엔드 SDK 또는 HTTP 클라이언트를 사용하여 압축하고 업로드한 후 업로드가 완료되면 로컬 파일을 삭제합니다. - 작업 예약:
- 작업자의
OneTimeWorkRequest를 만듭니다. - 제약 조건 설정: 기기가 Wi-Fi에 연결되어 있고 충전 중이며 유휴 상태일 때만 업로드가 실행되도록
setRequiredNetworkType(NetworkType.UNMETERED),setRequiresDeviceIdle(true),setRequiresCharging(true)를 사용합니다. - 데이터 전달:
setInputData를 사용하여getResultFilePath에서 작업자로 프로필 경로를 전달합니다. - 큐에 추가:
WorkManager.enqueue를 호출하여WorkManager에 요청을 제출합니다.
- 작업자의
다음 단계
프로필을 가져오거나 업로드한 후 Perfetto UI에서 시각화하거나, PerfettoSQL로 개별 프로필을 쿼리하거나, 트레이스를 일괄 분석하거나, AI로 프로필을 분석합니다. 확장 가능한 서버 측 분석 파이프라인을 설정하는 방법에 대한 안내는 Kubernetes에 Bigtrace 배포를 참조하세요.