Cho dù bạn thu thập hồ sơ do ứng dụng điều khiển hay hồ sơ dựa trên điều kiện kích hoạt, thì ProfilingManager đều lưu tệp đã hoàn tất trên thiết bị và gửi ProfilingResult đến lệnh gọi lại đã đăng ký của bạn. Gọi
ProfilingResult.getResultFilePath để lấy đường dẫn của hồ sơ đã lưu:
- Trong quá trình kiểm thử cục bộ: Kéo tệp vào máy tính bằng
adb. - Trong môi trường thực tế: Truyền đường dẫn đến một công việc
WorkManagerđể nén và tải hồ sơ lên máy chủ của bạn.
Truy xuất hồ sơ từ một thiết bị
Phần này mô tả nơi ProfilingManager lưu trữ hồ sơ trên thiết bị, cách hoạt động của tính năng tự động dọn dẹp tệp và cách lấy tệp trên thiết bị bằng adb.
Vị trí tệp và định dạng đặt tên
ProfilingManager lưu hồ sơ đã loại bỏ thông tin nhạy cảm vào thư mục bộ nhớ dành riêng cho ứng dụng tại /data/user/0/<app>/files/profiling/. Định dạng tên tệp phụ thuộc vào cách thu thập hồ sơ:
Hồ sơ do ứng dụng điều khiển:
profile_<tag>_<datetime>_uid-<uid>.<profile-type-ext>Nếu không có thẻ nào được cung cấp khi yêu cầu hồ sơ, thì
<tag>_sẽ bị bỏ qua:profile_<datetime>_uid-<uid>.<profile-type-ext>.Hồ sơ dựa trên trình kích hoạt:
profile_trigger-type-<trigger_type>_<datetime>_uid-<uid>.<profile-type-ext>
Trong trường hợp:
<app>là tên gói của ứng dụng.<tag>là tối đa 20 ký tự chữ-số đầu tiên (và dấu gạch nối) của thẻ do phương thức gọi cung cấp được định cấu hình bằngsetTaghoặc được truyền đếnrequestProfiling, được chuyển đổi thành chữ thường và xoá mọi ký tự nằm ngoàia-z,0-9và-.<trigger_type>là mã hằng số nguyên cho điều kiện kích hoạt từProfilingTrigger. Luôn gọiProfilingResult.getTriggerTypetrong mã thay vì phân tích cú pháp tên tệp.<datetime>là ngày và giờ hồ sơ được ghi lại (yyyy-MM-dd-HH-mm-ss-SSS).<uid>là mã nhận dạng người dùng Linux của ứng dụng (có trong các phiên bản mô-đunProfilinggần đây).<profile-type-ext>là đuôi tệp cho loại hồ sơ đã thu thập:.perfetto-tracecho dấu vết hệ thống.perfetto-java-heap-dumpcho tệp báo lỗi vùng nhớ Java.perfetto-heap-profilecho hồ sơ ảnh chụp nhanh của vùng nhớ khối xếp.perfetto-stack-samplecho hồ sơ lấy mẫu ngăn xếp
Bộ nhớ trên thiết bị và dọn dẹp
Để giải phóng bộ nhớ trên thiết bị ngay lập tức, hãy xoá từng tệp hồ sơ trong trình thực thi tải lên ngay sau khi tải lên thành công (vì quá trình dọn dẹp tự động chỉ chạy khi ProfilingManager phân phối kết quả cho ứng dụng của bạn, nếu không, các tệp chưa tải lên có thể vẫn còn trên ổ đĩa nếu ứng dụng của bạn ngừng đăng ký lệnh gọi lại sau khi kết thúc chiến dịch). Để dự phòng cho các phiên bản mô-đun Profiling gần đây, ProfilingManager cũng tự động xoá các tệp đã phân phối trong thư mục lưu trữ dành riêng cho ứng dụng của bạn (các tệp đã tồn tại hơn 5 ngày) khi kết quả mới được phân phối.
Tải hồ sơ lên trong phiên bản phát hành chính thức bằng WorkManager
Vì các tệp hồ sơ có thể có kích thước vài megabyte, nên hãy lên lịch tải bản phát hành chính thức lên trong nền khi thiết bị đang kết nối với mạng không đo lượng dữ liệu (Wi-Fi), đang sạc và ở trạng thái rảnh.
Trước khi tải lên, hãy nén tệp hồ sơ (ví dụ: sử dụng GZIPOutputStream hoặc ZipOutputStream). Hồ sơ protobuf Perfetto và tệp báo lỗi vùng nhớ khối xếp Java nén đáng kể, giúp giảm băng thông mạng và chi phí lưu trữ phụ trợ.
Thêm phần phụ thuộc WorkManager
ProfilingManager không phụ thuộc vào đám mây, vì vậy, bạn có thể lên lịch tải hồ sơ lên bất kỳ phần phụ trợ nào bằng WorkManager. Thêm thư viện WorkManager vào tệp build.gradle.kts:
Kotlin
dependencies { implementation("androidx.work:work-runtime:2.12.0") }
Groovy
dependencies { implementation 'androidx.work:work-runtime:2.12.0' }
Lên lịch cho một công việc tải lên
Khi ứng dụng của bạn nhận được ProfilingResult, hãy lên lịch cho công việc tải lên. Ví dụ sau đây bỏ qua yêu cầu lập hồ sơ ban đầu; để xem ví dụ về yêu cầu hoàn chỉnh, hãy xem phần Ghi lại dấu vết hệ thống.
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()) }
Java
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()); }
Hướng dẫn từng bước về mã
Ví dụ trước thực hiện các bước sau:
- Xác định worker: Tạo một lớp
TraceUploadWorkermở rộngWorker. Triển khaidoWorkđể xác minh rằng tệp hồ sơ vẫn tồn tại, nén và tải tệp đó lên bằng SDK phụ trợ hoặc máy khách HTTP, sau đó xoá tệp cục bộ sau khi tải lên thành công. - Lên lịch cho công việc:
- Tạo
OneTimeWorkRequestcho worker. - Đặt quy tắc ràng buộc: Sử dụng
setRequiredNetworkType(NetworkType.UNMETERED),setRequiresDeviceIdle(true)vàsetRequiresCharging(true)để quá trình tải lên chỉ chạy khi thiết bị đang kết nối Wi-Fi, đang sạc và ở trạng thái rảnh. - Truyền dữ liệu: Sử dụng
setInputDatađể truyền đường dẫn hồ sơ từgetResultFilePathđến worker. - Enqueue: Gửi yêu cầu đến
WorkManagerbằng cách gọiWorkManager.enqueue.
- Tạo
Các bước tiếp theo
Sau khi truy xuất hoặc tải hồ sơ lên, hãy trực quan hoá hồ sơ trong giao diện người dùng Perfetto, truy vấn từng hồ sơ bằng PerfettoSQL, phân tích hàng loạt dấu vết hoặc phân tích hồ sơ bằng AI. Để được hướng dẫn về cách thiết lập quy trình phân tích phía máy chủ có thể mở rộng, hãy xem bài viết Triển khai Bigtrace trên Kubernetes.