Tài liệu này giúp bạn xác định và khắc phục các vấn đề chính về hiệu suất của ứng dụng.
Các vấn đề chính về hiệu suất
Có nhiều vấn đề có thể góp phần gây ra hiệu suất kém trong một ứng dụng. Tuy nhiên, bạn nên lưu ý một số vấn đề thường gặp sau đây:
- Độ trễ khi khởi động
Độ trễ khi khởi động là khoảng thời gian cần thiết kể từ khi người dùng nhấn vào biểu tượng ứng dụng, thông báo hoặc điểm vào khác đến khi dữ liệu của người dùng hiện trên màn hình.
Hãy cố gắng đạt được các mục tiêu khởi động sau trong ứng dụng của bạn:
- Khởi động nguội trong vòng chưa đầy 500 mili giây. Quá trình khởi động nguội xảy ra khi ứng dụng đang khởi chạy không có trong bộ nhớ của hệ thống. Hiện tượng này xảy ra khi đây là lần đầu tiên ứng dụng chạy kể từ khi khởi động lại hoặc kể từ khi người dùng/hệ thống buộc dừng quy trình của ứng dụng. Quá trình khởi động nguội yêu cầu hệ thống phải xử lý nhiều việc nhất, vì hệ thống phải tải mọi thứ từ bộ nhớ và khởi động ứng dụng. Hãy cố gắng làm cho thời gian khởi động nguội chỉ mất tối đa 500 mili giây.
- Khởi động ấm trong vòng chưa đầy 200 mili giây và khởi động nóng trong vòng chưa đầy 150 mili giây. Quá trình khởi động ấm xảy ra khi quy trình của ứng dụng đã chạy ở chế độ nền, nhưng hệ thống cần khởi động lại giao diện người dùng hoặc đưa hoạt động trở lại nền trước, chẳng hạn như khi người dùng thoát ứng dụng và mở lại ngay sau đó. Khởi động nóng còn nhanh hơn nữa vì hoạt động của ứng dụng đã được lưu vào bộ nhớ đệm và chỉ cần đưa lên nền trước mà không cần tạo lại hệ phân cấp view. Hãy cố gắng giữ thời gian khởi động ấm dưới 200 mili giây và thời gian khởi động nóng dưới 150 mili giây.
- Các độ trễ P95 và P99 rất gần với độ trễ trung bình. P95 và P99 biểu thị phân vị thứ 95 và 99 của thời gian khởi động, trong khi trung vị là phân vị thứ 50. Khi mất quá nhiều thời gian để khởi động, ứng dụng sẽ mang lại trải nghiệm khó chịu cho người dùng. Hoạt động giao tiếp liên quy trình (IPC) và I/O không cần thiết trong quá trình quan trọng khi khởi động ứng dụng có thể gặp phải tình trạng cạnh tranh khoá và dẫn đến sự không nhất quán.
- Giật trong khi cuộn
Giật là thuật ngữ mô tả tình trạng hình ảnh bị giật khi hệ thống không thể xây dựng và cung cấp các khung hình kịp thời để vẽ chúng lên màn hình ở tần số 60 Hz trở lên. Hiện tượng giật thể hiện rõ nhất lúc cuộn, khi luồng ảnh động không chạy trơn tru mà lại có tình trạng giật. Hiện tượng giật xuất hiện khi chuyển động tạm dừng trong một hoặc nhiều khung hình, vì ứng dụng mất nhiều thời gian hơn để hiển thị nội dung so với thời lượng của một khung hình trên hệ thống.
Nhắm đến tốc độ làm mới 90 Hz trong ứng dụng của bạn. Tốc độ kết xuất thông thường là 60 Hz, nhưng nhiều thiết bị mới hoạt động ở chế độ 90 Hz trong các hoạt động tương tác của người dùng, chẳng hạn như cuộn. Một số thiết bị hỗ trợ tốc độ thậm chí còn cao hơn, lên tới 120 Hz.
Để xem tốc độ làm mới mà một thiết bị đang sử dụng tại một thời điểm nhất định, hãy bật lớp phủ bằng cách sử dụng Tuỳ chọn cho nhà phát triển > Hiện tốc độ làm mới trong phần Gỡ lỗi.
- Quá trình chuyển đổi không suôn sẻ
Vấn đề này rất dễ thấy trong các hoạt động tương tác như chuyển đổi giữa các thẻ hoặc tải một hoạt động mới. Các loại chuyển đổi này phải đảm bảo ảnh động mượt mà và không có độ trễ hoặc nhấp nháy hình ảnh.
- Sử dụng pin không hiệu quả
Tất nhiên làm việc sẽ tốn pin, nhưng thực hiện những tác vụ không cần thiết lại cũng làm giảm thời lượng pin.
Việc phân bổ bộ nhớ từ việc tạo các đối tượng mới trong mã sẽ khiến hệ thống phải thực hiện khối lượng công việc lớn. Bởi vì không chỉ có việc phân bổ yêu cầu chạy Android Runtime (ART), mà việc giải phóng các đối tượng đó sau này (gom rác) cũng đòi hỏi thời gian và công sức.
Cả quá trình phân bổ bộ nhớ và thu gom rác đều nhanh và hiệu quả hơn nhiều, đặc biệt là với các đối tượng tạm thời. Mặc dù trước đây phương pháp hay nhất là tránh phân bổ các đối tượng bất cứ khi nào có thể, nhưng bạn nên làm điều phù hợp nhất với ứng dụng và kiến trúc của mình. Dựa trên khả năng của ART, phương pháp hay nhất là tiết kiệm được các mức phân bổ trước nguy cơ mã không thể duy trì.
Tuy nhiên, việc phân bổ đòi hỏi nhiều công sức, vì vậy, hãy lưu ý rằng việc này có thể ảnh hưởng đến hiệu suất nếu bạn đang phân bổ nhiều đối tượng trong vòng lặp nội bộ.
Xác định vấn đề
Để khắc phục các vấn đề về hiệu suất, hãy xác định và kiểm tra các hành trình quan trọng sau đây của người dùng:
- Các quy trình khởi động phổ biến, bao gồm cả từ trình chạy và thông báo.
- Màn hình mà người dùng cuộn xem dữ liệu.
- Chuyển đổi giữa các màn hình.
- Các quy trình chạy lâu dài, chẳng hạn như điều hướng hoặc phát nhạc.
Đối với mỗi quy trình này, hãy kiểm tra xem điều gì đang xảy ra bằng các công cụ gỡ lỗi sau:
- Perfetto: cho phép bạn xem điều gì đang diễn ra trên toàn bộ thiết bị nhờ dữ liệu thời gian chính xác.
- Trình phân tích bộ nhớ: cho phép bạn xem quá trình phân bổ bộ nhớ đang diễn ra trên vùng nhớ khối xếp.
- Simpleperf: cho thấy biểu đồ về các lệnh gọi hàm đang sử dụng nhiều CPU nhất trong một khoảng thời gian nhất định. Khi bạn xác định được tác vụ nào đang chạy nhiều thời gian trong Systrace, nhưng không biết lý do tại sao, Simpleperf có thể cung cấp thêm thông tin.
Để hiểu và gỡ lỗi các vấn đề về hiệu suất này, bạn cần phải tự mình gỡ lỗi từng lần chạy kiểm thử. Bạn không thể thay thế các bước trước đó bằng cách phân tích dữ liệu tổng hợp. Tuy nhiên, để hiểu rõ những gì người dùng thực sự nhìn thấy và xác định thời điểm sự hồi quy có thể xảy ra, điều quan trọng là bạn phải thiết lập tính năng thu thập chỉ số trong quy trình kiểm thử tự động và trong trường:
- Quy trình khởi động
- Chỉ số trường: Thời gian khởi động Play Console
- Kiểm thử trong phòng thí nghiệm: kiểm thử việc khởi động bằng Macrobenchmark
- Giật
- Chỉ số trường
- Các chỉ số khung của Play Console: trong Play Console, bạn không thể thu hẹp các chỉ số cho một hành trình cụ thể của người dùng. Loại chỉ số này chỉ báo cáo tình trạng giật tổng thể trong toàn bộ ứng dụng.
- Đo lường tuỳ chỉnh bằng
FrameMetricsAggregator: bạn có thể sử dụngFrameMetricsAggregatorđể ghi lại các chỉ số độ giật trong một quy trình công việc cụ thể.
- Kiểm thử trong phòng thí nghiệm
- Cuộn bằng Macrobenchmark.
- Macrobenchmark thu thập thời gian kết xuất khung hình bằng cách sử dụng các lệnh
dumpsys gfxinfođóng một hành trình người dùng. Đây là một cách để tìm hiểu về sự thay đổi độ giật trong một hành trình cụ thể của người dùng. Chỉ sốRenderTime(nêu rõ khoảng thời gian cần thiết để vẽ các khung hình) có ý nghĩa quan trọng hơn số lượng khung hình bị giật trong việc xác định sự hồi quy hay cải thiện.
- Chỉ số trường
Vấn đề về quy trình xác minh Đường liên kết đến ứng dụng
Đường liên kết đến ứng dụng là đường liên kết sâu dựa trên URL của trang web đã được xác minh là thuộc về trang web của bạn. Quy trình xác minh Đường liên kết đến ứng dụng có thể không thành công vì những lý do sau:
- Phạm vi bộ lọc ý định không chính xác: chỉ thêm
autoVerifyvào bộ lọc ý định cho những URL mà ứng dụng của bạn có thể phản hồi. - Chuyển đổi giao thức chưa được xác minh: các lệnh chuyển hướng phía máy chủ và miền con chưa được xác minh được coi là rủi ro bảo mật và không xác minh được. Chúng khiến tất cả các đường liên kết
autoVerifyđều không hoạt động. Ví dụ: việc chuyển hướng các đường liên kết từ HTTP sang HTTPS, chẳng hạn như example.com sang www.example.com, mà không xác minh các đường liên kết HTTPS có thể khiến quá trình xác minh không thành công. Hãy nhớ xác minh Đường liên kết đến ứng dụng bằng cách thêm bộ lọc ý định. - Đường liên kết không xác minh được: việc thêm đường liên kết không xác minh được cho mục đích kiểm thử có thể khiến hệ thống không xác minh được Đường liên kết trong ứng dụng cho ứng dụng của bạn.
- Máy chủ không đáng tin cậy: đảm bảo máy chủ của bạn có thể kết nối với các ứng dụng khách.
Thiết lập ứng dụng để phân tích hiệu suất
Bạn cần phải thiết lập đúng cách để có được các điểm chuẩn chính xác, có thể lặp lại và hữu ích từ một ứng dụng. Hãy kiểm thử trên một hệ thống gần với bản phát hành công khai nhất có thể, đồng thời loại bỏ các nguồn gây nhiễu. Trong các phần sau, bạn có thể thực hiện một số bước cụ thể tuỳ theo APK và hệ thống để chuẩn bị thiết lập việc kiểm thử, trong đó một số bước có thể thay đổi tuỳ từng trường hợp sử dụng.
Các điểm theo dõi
Các ứng dụng có thể đo lường mã của chúng bằng các sự kiện theo dõi tuỳ chỉnh.
Mặc dù đang thu thập dấu vết, nhưng tính năng theo dõi có mức hao tổn nhỏ (khoảng 5μ mỗi phần), vì vậy, đừng sử dụng tính năng này cho mọi phương thức. Việc theo dõi các phần công việc lớn hơn 0,1 mili giây có thể cung cấp thông tin chi tiết đáng kể về các điểm tắc nghẽn.
Những điểm cần lưu ý về APK
Các biến thể gỡ lỗi có thể hữu ích cho việc khắc phục sự cố và thay thế các biểu tượng mẫu ngăn xếp. Tuy nhiên, các biến thể đó có ảnh hưởng nghiêm trọng đến hiệu suất. Các thiết bị chạy Android 10 (API cấp 29) trở lên có thể sử dụng profileable android:shell="true" trong tệp kê khai để cho phép lập hồ sơ trong các bản phát hành.
Sử dụng cấu hình rút gọn mã ở cấp phát hành công khai. Tuỳ theo tài nguyên mà ứng dụng của bạn sử dụng, việc này có thể ảnh hưởng đáng kể đến hiệu suất. Một số cấu hình ProGuard xoá các dấu vết, vì vậy, hãy cân nhắc xoá các quy tắc đó cho cấu hình mà bạn đang chạy chương trình kiểm thử.
Biên dịch
Biên dịch ứng dụng của bạn trên thiết bị sang một trạng thái đã biết, thường là speed để đơn giản hoá hoặc speed-profile để phù hợp hơn với hiệu suất trong quá trình phát hành chính thức (mặc dù việc này yêu cầu khởi động ứng dụng và kết xuất hồ sơ hoặc biên dịch hồ sơ cơ sở của ứng dụng).
Cả speed và speed-profile đều giảm lượng mã đang chạy được diễn giải từ dex, và do đó giảm lượng biên dịch nền tức thì (JIT) có thể gây ra sự can thiệp đáng kể. Chỉ speed-profile giảm tác động của việc tải lớp thời gian chạy từ dex.
Lệnh sau đây sẽ biên dịch ứng dụng bằng chế độ speed:
adb shell cmd package compile -m speed -f com.example.packagename
Chế độ biên dịch speed sẽ biên dịch hoàn toàn các phương thức của ứng dụng. Chế độ speed-profile biên dịch các phương thức và lớp của ứng dụng theo hồ sơ của các đường dẫn mã đã sử dụng được thu thập trong quá trình sử dụng ứng dụng. Có thể bạn sẽ khó thu thập được hồ sơ một cách chính xác và nhất quán. Vì vậy, nếu quyết định sử dụng hồ sơ, hãy xác nhận rằng các hồ sơ đó đang thu thập những dữ liệu bạn muốn. Các hồ sơ này nằm ở vị trí sau:
/data/misc/profiles/ref/[package-name]/primary.prof
Những điểm cần lưu ý về hệ thống
Để đo lường độ chân thực cao và thấp, hãy điều chỉnh thiết bị của bạn. Chạy quy trình so sánh A/B trên cùng một thiết bị và cùng một phiên bản hệ điều hành. Hiệu suất có thể thay đổi đáng kể, thậm chí ngay trên cùng một loại thiết bị.
Trên các thiết bị bị can thiệp hệ thống, hãy cân nhắc sử dụng tập lệnh lockClocks cho Microbenchmark. Ngoài ra, các tập lệnh này thực hiện những việc sau:
- Đặt CPU ở tần suất cố định.
- Vô hiệu hoá các lõi nhỏ và định cấu hình GPU.
- Tắt chế độ điều tiết nhiệt.
Bạn không nên sử dụng tập lệnh lockClocks cho các hoạt động kiểm thử tập trung vào trải nghiệm người dùng, chẳng hạn như khởi chạy ứng dụng, kiểm thử DoU và kiểm thử độ giật. Tuy nhiên, tập lệnh này có thể cần thiết để giảm độ nhiễu trong các hoạt động kiểm thử Microbenchmark.
Nếu có thể, hãy cân nhắc sử dụng một khung kiểm thử như Macrobenchmark để có thể giảm độ nhiễu trong kết quả đo lường và ngăn tình trạng đo lường không chính xác.
Khởi động ứng dụng chậm: hoạt động đàn hồi không cần thiết
Một hoạt động đàn hồi có thể kéo dài thời gian khởi động ứng dụng theo cách không cần thiết. Điều quan trọng là bạn phải biết ứng dụng của mình có đang chạy như vậy hay không. Như minh hoạ trong dấu vết mẫu sau, một activityStart đứng ngay trước một activityStart khác mà không có bất kỳ khung nào do hoạt động đầu tiên vẽ.
Hình 1. Dấu vết cho thấy hoạt động đàn hồi.
Điều này có thể xảy ra cả ở điểm truy cập thông báo và điểm truy cập khởi động ứng dụng thông thường. Bạn thường có thể giải quyết vấn đề này bằng cách tái cấu trúc. Ví dụ: nếu bạn đang sử dụng hoạt động này để thực hiện việc thiết lập trước khi chạy một hoạt động khác, hãy đưa mã này vào một thành phần hoặc thư viện có thể tái sử dụng.
Các trường hợp phân bổ không cần thiết sẽ kích hoạt GC thường xuyên
Bạn có thể thấy hoạt động thu gom rác (GC) diễn ra thường xuyên hơn dự kiến trong Systrace.
Trong ví dụ sau, việc thu gom rác cứ 10 giây trong một hoạt động kéo dài là một chỉ báo cho biết ứng dụng có thể đang phân bổ một cách không cần thiết nhưng nhất quán theo thời gian:
Hình 2. Dấu vết cho thấy có khoảng cách giữa các sự kiện GC.
Bạn cũng có thể nhận thấy trong Trình phân tích bộ nhớ rằng một ngăn xếp lệnh gọi cụ thể đang thực hiện phần lớn quá trình phân bổ. Bạn không cần phải buộc loại bỏ tất cả tuỳ chọn phân bổ, vì điều này có thể khiến mã khó duy trì hơn. Thay vào đó, hãy bắt đầu bằng cách xử lý các điểm phân bổ.
Khung hình bị giật
Quy trình đồ hoạ tương đối phức tạp và có thể xảy ra một số vấn đề trong việc xác định xem liệu người dùng có thấy khung hình bị bỏ qua hay không. Trong một số trường hợp, nền tảng có thể "giải cứu" khung hình bằng cách sử dụng bộ đệm. Tuy nhiên, bạn có thể bỏ qua hầu hết các vấn đề đó để dễ dàng xác định khung hình có vấn đề từ chính ứng dụng của bạn.
Khi khung hình đang được vẽ và khối lượng công việc đòi hỏi từ ứng dụng không nhiều, điểm truy vết Choreographer.doFrame() xảy ra theo tần suất 16,7 mili giây trên thiết bị 60 khung hình/giây:
Hình 3. Một dấu vết cho thấy các khung hình nhanh thường xuyên xuất hiện.
Nếu bạn thu nhỏ và điều hướng xem qua dấu vết, đôi khi bạn sẽ thấy một số khung hình mất nhiều thời gian hơn để hoàn thành, nhưng không quá thời gian 16,7 mili giây đã được phân bổ. Những khung hình này đều ổn:
Hình 4. Dấu vết cho thấy các khung hình nhanh, thường xuyên xảy ra cụm công việc định kỳ.
Khi bạn thấy có sự gián đoạn ở tần suất thông thường này, thì đó là hiện tượng khung hình bị giật như minh hoạ trong Hình 5 và 6:
Hình 5. Dấu vết cho thấy một khung hình bị giật.
Hình 6. Một dấu vết cho thấy nhiều khung hình bị giật hơn.
Trong một số trường hợp, bạn cần phóng to một điểm theo dõi để biết thêm thông tin về thành phần giao diện người dùng nào đang được Compose cập nhật hoặc, như trong Hình 6, LazyColumn đang làm gì. Khi chẩn đoán các điểm tắc nghẽn này trên giao diện người dùng, tính năng theo dõi hệ thống tiêu chuẩn có thể không cho biết thành phần kết hợp nào là nguyên nhân gốc rễ. Trong những trường hợp này, hãy sử dụng hoạt động theo dõi thành phần Jetpack Compose. Hoạt động này sẽ hiển thị chính xác các hàm có khả năng kết hợp ngay trong dấu vết, giúp bạn dễ dàng xác định các thành phần kết hợp lại không mong muốn. Hình 5 và 6 cho thấy kết quả của tính năng theo dõi thành phần.
Để biết thêm thông tin về cách tối ưu hoá hiệu suất của Compose, hãy xem bài viết Hiệu suất của Jetpack Compose. Để biết thêm thông tin về cách xác định khung hình bị giật và cách gỡ lỗi, hãy xem phần Kết xuất chậm.
Các lỗi thường gặp về bố cục tải từng phần
Việc vô hiệu hoá toàn bộ trạng thái hỗ trợ của một bố cục lười một cách không cần thiết có thể dẫn đến quá nhiều lần kết hợp lại, thời gian kết xuất khung hình dài và hiện tượng giật. Để giảm thiểu số lượng mục trong danh sách cần cập nhật, hãy sử dụng khoá mục cho các mục và chỉ thay đổi các phần tử trạng thái cụ thể thay đổi.
Hãy xem phần Sử dụng các khoá bố cục tải từng phần để biết các cách tránh việc phân bổ lại toàn bộ danh sách tốn kém. Việc này khiến nội dung cập nhật thay vì thay thế hoàn toàn nội dung.
Việc triển khai không đúng cách các danh sách cuộn lồng nhau có thể khiến hiệu suất giảm. Tránh lồng một bố cục lười cuộn bên trong một vùng chứa cuộn khác mà không có các ràng buộc rõ ràng. Để biết thêm thông tin, hãy xem phần Tránh lồng các thành phần có thể cuộn theo cùng một hướng.
Việc không tìm nạp trước đủ dữ liệu hoặc không tìm nạp trước kịp thời có thể gây khó chịu trong quá trình người dùng truy cập đến cuối danh sách cuộn, vì người dùng phải đợi thêm dữ liệu từ máy chủ. Mặc dù về mặt kỹ thuật thì đây không phải là hiện tượng giật vì không quá thời hạn kết xuất khung hình, nhưng bạn có thể cải thiện đáng kể trải nghiệm người dùng bằng cách sửa đổi thời gian và số lượng tìm nạp trước để người dùng không phải chờ dữ liệu của chúng tôi.
Gỡ lỗi ứng dụng
Sau đây là các phương thức để gỡ lỗi hiệu suất của ứng dụng.
Gỡ lỗi khi khởi động ứng dụng bằng Systrace
Hãy xem bài viết Thời gian khởi động ứng dụng để biết thông tin tổng quan về quy trình khởi động ứng dụng, đồng thời xem video sau đây để biết thông tin tổng quan về hoạt động theo dõi hệ thống và cách sử dụng trình phân tích tài nguyên Android Studio.
Bạn có thể phân biệt các loại khởi động ở những giai đoạn sau:
- Khởi động nguội: bắt đầu bằng cách tạo một quy trình mới chưa được lưu trạng thái.
- Khởi động ấm: tạo lại hoạt động trong khi sử dụng lại quy trình hoặc tạo lại quy trình với trạng thái đã lưu.
- Khởi động nóng: khởi động lại hoạt động và bắt đầu ở giai đoạn tăng kích thước.
Bạn nên thu thập Systrace bằng ứng dụng Theo dõi hệ thống trên thiết bị. Đối với Android 10 trở lên, hãy sử dụng Perfetto. Đối với Android 9 trở xuống, hãy sử dụng Systrace. Bạn cũng nên xem các tệp dấu vết bằng trình xem dấu vết Perfetto dựa trên web. Để biết thêm thông tin, hãy xem bài viết Tổng quan về tính năng theo dõi hệ thống.
Bạn cần lưu ý một số điều sau:
- Tranh chấp màn hình: việc cạnh tranh các tài nguyên được bảo vệ bằng màn hình có thể làm trì hoãn đáng kể khi khởi động ứng dụng.
Giao dịch nhị phân đồng bộ: tìm các giao dịch không cần thiết trong đường dẫn quan trọng của ứng dụng. Nếu một giao dịch cần thiết có chi phí cao, hãy cân nhắc làm việc với nhóm nền tảng liên kết để cải thiện.
GC đồng thời: đây là một hiện tượng thường thấy và có tác động tương đối thấp, nhưng nếu bạn thường xuyên gặp phải hiện tượng này, hãy cân nhắc tìm hiểu bằng trình phân tích bộ nhớ trong Android Studio.
I/O: kiểm tra I/O được thực hiện trong quá trình khởi động và tìm các stall dài.
Hoạt động quan trọng trên các luồng khác: những hoạt động này có thể ảnh hưởng đến luồng giao diện người dùng, vì vậy hãy chú ý đến thao tác trong nền khi khởi động.
Bạn nên gọi reportFullyDrawn khi hoàn tất quá trình khởi động từ góc độ của ứng dụng để cải thiện báo cáo chỉ số khởi động ứng dụng. Hãy xem phần Thời gian hiển thị đầy đủ để biết thêm thông tin về cách sử dụng reportFullyDrawn.
Bạn có thể trích xuất thời gian bắt đầu do RFD xác định thông qua trình xử lý dấu vết Perfetto và một sự kiện dấu vết mà người dùng có thể thấy sẽ được phát ra.
Sử dụng tính năng Theo dõi hệ thống trên thiết bị
Bạn có thể sử dụng ứng dụng cấp hệ thống có tên là Theo dõi hệ thống để ghi lại dấu vết hệ thống trên một thiết bị. Ứng dụng này cho phép bạn ghi lại dấu vết từ thiết bị mà không cần cắm hoặc kết nối thiết bị với adb.
Sử dụng Trình phân tích bộ nhớ trong Android Studio
Bạn có thể sử dụng Trình phân tích bộ nhớ của Android Studio để kiểm tra áp lực bộ nhớ có thể do rò rỉ bộ nhớ hoặc do thói quen sử dụng không tốt. Công cụ này cung cấp chế độ xem trực tiếp về việc phân bổ đối tượng.
Bạn có thể khắc phục các vấn đề về bộ nhớ trong ứng dụng bằng cách sử dụng Trình phân tích bộ nhớ để theo dõi lý do và tần suất xảy ra các hoạt động thu gom rác.
Để phân tích bộ nhớ ứng dụng, hãy thực hiện các bước sau:
Phát hiện vấn đề về bộ nhớ.
Ghi lại một phiên lập hồ sơ bộ nhớ của hành trình người dùng mà bạn muốn tập trung vào. Tìm số lượng đối tượng tăng lên, như trong hình 7, cuối cùng dẫn đến GC, như trong hình 8.
Hình 7. Tăng số lượng đối tượng.
Hình 8. Thu gom rác.Sau khi bạn xác định được hành trình của người dùng gây ra áp lực bộ nhớ, hãy phân tích nguyên nhân cốt lõi của áp lực bộ nhớ.
Chẩn đoán các điểm nóng về áp lực bộ nhớ.
Chọn một dải ô trong tiến trình để hình dung cả Phân bổ và Kích thước nông, như minh hoạ trong hình 9.
Hình 9. Giá trị cho Allocations và Shallow Size (Kích thước nông).Có nhiều cách để sắp xếp dữ liệu này. Sau đây là một số ví dụ về cách mỗi chế độ xem có thể giúp bạn phân tích vấn đề.
Sắp xếp theo lớp: hữu ích khi bạn muốn tìm các lớp đang tạo các đối tượng được lưu vào bộ nhớ đệm hoặc sử dụng lại từ một nhóm bộ nhớ.
Ví dụ: nếu một ứng dụng đang tạo 2.000 đối tượng của một lớp cụ thể mỗi giây, thì ứng dụng đó sẽ tăng số lượt Phân bổ thêm 2.000 mỗi giây và bạn sẽ thấy số liệu này khi sắp xếp theo lớp. Nếu bạn muốn sử dụng lại các đối tượng này để tránh tạo ra rác, hãy triển khai một nhóm bộ nhớ.
Sắp xếp theo ngăn xếp lệnh gọi: hữu ích khi bạn muốn tìm đường dẫn nóng mà bộ nhớ đang được phân bổ, chẳng hạn như bên trong một vòng lặp hoặc bên trong một hàm cụ thể thực hiện rất nhiều công việc phân bổ.
Shallow Size (Kích thước của đối tượng): chỉ theo dõi bộ nhớ của chính đối tượng. Quá trình này rất hữu ích trong việc theo dõi các lớp đơn giản chủ yếu bao gồm các giá trị gốc.
Retained Size (Kích thước được giải phóng): cho biết tổng bộ nhớ do chính đối tượng cộng với mọi tham chiếu chỉ được đối tượng đó tham chiếu. Quá trình này rất hữu ích trong việc theo dõi áp lực bộ nhớ do các đối tượng phức tạp gây ra. Để lấy giá trị này, hãy thực hiện kết xuất bộ nhớ đầy đủ, như minh hoạ trong hình 10. Retained Size (Kích thước giữ lại) được thêm dưới dạng một cột, như minh hoạ trong hình 11.
Hình 10. Vùng nhớ khối xếp bộ nhớ đầy.
Hình 11. Cột Kích thước được giữ lại.
Đo lường tác động của một hoạt động tối ưu hoá.
GC rõ ràng hơn và dễ đo lường tác động của việc tối ưu hoá trong bộ nhớ. Khi quá trình tối ưu hoá làm giảm áp lực bộ nhớ, bạn sẽ thấy ít GC hơn.
Để đo lường tác động của việc tối ưu hoá, trong tiến trình của trình phân tích tài nguyên, hãy đo thời gian giữa các GC. Tác động tích cực sẽ giúp kéo dài thời gian giữa các lần thu gom rác.
Những tác động cuối cùng của việc cải thiện bộ nhớ là:
- Các trường hợp tắt do hết bộ nhớ có thể sẽ giảm nếu ứng dụng không liên tục bị áp lực bộ nhớ.
- Việc có ít GC cải thiện chỉ số giật, đặc biệt là trong P99. Nguyên nhân là do GC gây ra tranh chấp về CPU, có thể dẫn đến việc hiển thị các nhiệm vụ bị trì hoãn trong khi GC đang diễn ra.
Đề xuất cho bạn
- Lưu ý: văn bản có đường liên kết sẽ hiện khi JavaScript tắt
- Phân tích và tối ưu hoá quá trình khởi động ứng dụng {:#app-startup-analysis-optimization}
- Khung hình bị treo
- Viết một Macrobenchmark