Việc tối ưu hoá bộ nhớ là yếu tố quan trọng để mang lại trải nghiệm chơi trò chơi ổn định, hiệu suất cao trên Android. Hướng dẫn này cung cấp thông tin tổng quan về lý do hiệu suất sử dụng bộ nhớ lại quan trọng, cách hệ điều hành Android quản lý và thực thi các giới hạn bộ nhớ xử lý, cũng như các ngưỡng mới được hiển thị trong Google Play Console để giúp bạn theo dõi và cải thiện chất lượng kỹ thuật của trò chơi.
Tầm quan trọng của việc tối ưu hoá bộ nhớ
Việc tối ưu hoá bộ nhớ của trò chơi là điều cần thiết để duy trì tỷ lệ giữ chân người chơi, mở rộng khả năng tương thích với thiết bị và tuân thủ các tiêu chuẩn chất lượng của nền tảng:
- Ngăn chặn khởi động nguội (trải nghiệm người dùng và tỷ lệ giữ chân): Khi người chơi tạm thời chuyển khỏi trò chơi của bạn (ví dụ: để trả lời thông báo hoặc kiểm tra tin nhắn), hệ điều hành sẽ đặt quy trình trò chơi vào chế độ nền. Nếu mức sử dụng bộ nhớ nền của trò chơi quá cao, Low Memory Killer (LMK) của hệ thống sẽ ưu tiên chấm dứt quy trình trò chơi để thu hồi RAM cho các tác vụ ở nền trước. Lần tiếp theo người dùng tiếp tục, thay vì tiếp tục nhanh chóng và liền mạch, trò chơi phải trải qua quá trình khởi động nguội kéo dài – tải lại hoàn toàn các thành phần đồ hoạ, âm thanh và tệp nhị phân của công cụ phát triển trò chơi từ bộ nhớ. Việc duy trì mức sử dụng bộ nhớ nền thấp sẽ ngăn chặn những trường hợp chấm dứt nền thầm lặng này, duy trì trạng thái người dùng và đảm bảo người chơi có thể tiếp tục phiên ngay lập tức. Để biết thêm thông tin chi tiết về hành vi LMK của hệ thống, hãy xem hướng dẫn Android Vitals – Low memory killers (Android Vitals – Trình diệt bộ nhớ thấp).
- Tính ổn định của hệ sinh thái và thiết bị: Mức sử dụng bộ nhớ không hiệu quả và lỗi rò rỉ bộ nhớ làm giảm tình trạng chung của hệ thống. Khi bộ nhớ hệ thống không đủ, hệ thống sẽ chịu áp lực lớn, dẫn đến tình trạng giảm tốc độ khung hình, giao diện người dùng bị giật và âm thanh bị trục trặc. Nếu áp lực bộ nhớ quá lớn, Low Memory Killer (LMK) của hệ thống sẽ chủ động chấm dứt các quy trình ở chế độ nền, buộc các ứng dụng khác phải trải qua quá trình khởi động nguội chậm và mất trạng thái người dùng khi người chơi chuyển đổi giữa các tác vụ.
- Các trường hợp chấm dứt ở cấp nền tảng: Kể từ Android 17 (cấp độ API 37), hệ thống sẽ chủ động hơn trong việc chấm dứt các quy trình sử dụng quá nhiều bộ nhớ. Nếu mức sử dụng bộ nhớ của trò chơi quá cao, hệ điều hành có thể đột ngột chấm dứt quy trình của trò chơi mà không tạo ra một dấu vết ngăn xếp tiêu chuẩn.
- Khả năng tương thích của thiết bị: Mặc dù các thiết bị hàng đầu có RAM từ 12 GB đến 16 GB, nhưng phần lớn người chơi game trên toàn cầu sử dụng các thiết bị có RAM 4 GB hoặc 6 GB. Việc quản lý bộ nhớ đúng cách đảm bảo trò chơi của bạn vẫn có thể truy cập và phản hồi trên tất cả các cấp phần cứng mà không yêu cầu các gói tài sản phức tạp, riêng biệt.
Tìm hiểu về bộ nhớ trong Android
Để thiết kế các chiến lược phân bổ bộ nhớ hiệu quả, nhà phát triển phải hiểu cách nền tảng Android quản lý bộ nhớ vật lý và cách nền tảng này đo lường dấu vết hoạt động của trò chơi.
Các khái niệm cốt lõi về bộ nhớ Android
Để biết các khái niệm cơ bản về hoạt động quản lý bộ nhớ ở cấp nền tảng, hãy xem tài liệu chính thức Tổng quan về hoạt động quản lý bộ nhớ. Tài nguyên này đề cập đến 4 lĩnh vực kiến trúc:
- Tổng quan về bộ nhớ: Android sử dụng tính năng phân trang và ánh xạ bộ nhớ (mmap) để quản lý RAM. Hệ thống này không hỗ trợ tệp hoán đổi truyền thống trên ổ đĩa; thay vào đó, hệ thống dựa vào tính năng nén trang (sử dụng zRAM) và thu hồi trang để giải phóng bộ nhớ thực.
- Phân bổ bộ nhớ giữa các quy trình: Android chia sẻ RAM trên toàn bộ hệ thống. Thư viện này chỉ định các vùng nhớ cụ thể để thực thi máy ảo Dalvik hoặc ART, đồng thời cho phép các môi trường phát triển gốc (chẳng hạn như các công cụ trò chơi C++) yêu cầu bộ nhớ từ vùng nhớ hệ thống gốc.
- Quản lý bộ nhớ ứng dụng: Hoạt động theo mô hình đa quy trình, Android yêu cầu các ứng dụng theo dõi trạng thái vòng đời của chúng một cách linh động và tự nguyện giải phóng các tài nguyên không cần thiết (chẳng hạn như đồ hoạ và bitmap không được lưu vào bộ nhớ đệm) để hỗ trợ tình trạng hệ thống.
- Tổng quan về các quy trình và luồng: Hệ thống phân loại các quy trình thành một hệ phân cấp dựa trên mức độ hiển thị và tầm quan trọng hiện tại mà người dùng cảm nhận được, xác định quy trình nào được duy trì và quy trình nào bị chấm dứt trước tiên trong điều kiện bộ nhớ thấp.
Tổng chỉ số mức sử dụng bộ nhớ
Trình giới hạn bộ nhớ Android 17 ở cấp nền tảng đánh giá mức tiêu thụ quy trình bằng cách sử dụng Tổng dung lượng bộ nhớ thay vì tổng kích thước thường trú (RSS) hoặc kích thước bộ nhớ ảo.
Tổng dung lượng bộ nhớ = RSS ẩn danh (RssAnon) + Không gian trao đổi chưa nén (VmSwap)
Để ngăn trò chơi vượt quá giới hạn do nền tảng áp đặt, nhà phát triển phải hiểu chính xác những chỉ số này đại diện cho điều gì ở cấp hệ thống. Để biết thêm thông tin về các chỉ số này, việc phân bổ RAM thực và cách xử lý các trang được sao lưu bằng tệp, hãy xem bài viết Tìm hiểu về chỉ số RSS và Swap trong hướng dẫn Theo dõi mức sử dụng bộ nhớ.
Hạn chế về bộ nhớ
Để duy trì sự ổn định của hệ thống và đảm bảo rằng các ứng dụng không tiêu tốn quá nhiều tài nguyên, nền tảng Android sẽ áp dụng giới hạn bộ nhớ đối với các quy trình đang chạy.
Trình giới hạn bộ nhớ trong Android 17 trở lên
Android 17 trở lên áp dụng các giới hạn nghiêm ngặt về bộ nhớ cho từng ứng dụng bằng cách sử dụng cgroup v2 của Linux để ngăn chặn tình trạng các ứng dụng riêng lẻ gây ra sự bất ổn trên toàn hệ thống. Để biết thêm thông tin chi tiết về việc triển khai kỹ thuật, hãy xem Hướng dẫn về bộ giới hạn bộ nhớ AOSP và Ưu tiên hiệu suất bộ nhớ: Các bước cần thiết cho Blog Android 17.
- Cơ chế: Trình giới hạn bộ nhớ giám sát tất cả các quy trình của ứng dụng và chỉ định giới hạn một cách linh động dựa trên trạng thái vòng đời của quy trình:
- Các quy trình hiển thị (nền trước): Các quy trình của ứng dụng hiện đang hiển thị một giao diện người dùng dự kiến sẽ chạy một nhóm làm việc tài nguyên lớn hơn và được cấp một hạn mức rộng rãi hơn.
- Các quy trình không hiển thị (nền hoặc dịch vụ): Các quy trình của ứng dụng đang thực hiện công việc chủ động mà không hiển thị giao diện người dùng sẽ bị giới hạn ở mức ngân sách chặt chẽ và hạn chế hơn.
- Thuộc tính của nhân: Dịch vụ này dựa vào 2 thuộc tính chính:
memory.high: Giới hạn mềm. Khi vượt quá, kernel sẽ điều tiết quy trình và cố gắng thu hồi bộ nhớ một cách tích cực. Việc thu hồi này có thể khiến hiệu suất của trò chơi bị giảm.memory.swap.max: Áp dụng giới hạn tối đa đối với không gian hoán đổi hoặc zRAM mà quy trình có thể sử dụng.
- Hành vi chấm dứt: Nếu một quy trình tiếp tục phân bổ bộ nhớ ẩn danh vượt quá
memory.highvà cạn kiệt dung lượng trao đổi, thì các hoạt động phân bổ sẽ không thành công và hệ điều hành sẽ âm thầm huỷ quy trình. Việc chấm dứt này được ghi lại bằngApplicationExitInfotheo lý do thoát Memory Limiter (có từ Android 17, 26Q4).
Giám sát mức sử dụng bộ nhớ
Để tối ưu hoá bộ nhớ của trò chơi một cách hiệu quả, trước tiên, bạn phải hiểu cách nền tảng Android đo lường mức sử dụng bộ nhớ. Android 17 cập nhật chỉ số thực thi bộ nhớ để theo dõi tổng của RSS ẩn danh (RssAnon) và Swap chưa nén (VmSwap), không bao gồm bộ nhớ riêng của GPU hoặc bộ nhớ được sao lưu bằng tệp. Hướng dẫn này trình bày chi tiết cách tận dụng các công cụ ở cấp hệ thống như Perfetto và meminfo, triển khai các API chẩn đoán như ProfilingManager và onTrimMemory, đồng thời trích xuất các hoạt động phân bổ bộ nhớ chính xác trong Unity và Unreal Engine. Tìm hiểu cách lập hồ sơ chính xác cho trò chơi và tránh tình trạng giật hình liên quan đến hoạt động thăm dò bộ nhớ thời gian chạy truyền thống.
Để biết thêm thông tin, hãy xem bài viết Theo dõi mức sử dụng bộ nhớ.
Chiến lược giảm bộ nhớ
Mặc dù các công cụ trò chơi giúp đơn giản hoá quá trình phát triển trên nhiều nền tảng, nhưng việc xử lý bộ nhớ mặc định của các công cụ này có thể kích hoạt giới hạn bộ nhớ ở cấp hệ điều hành. Trang này trình bày chi tiết các bước tối ưu hoá thực tế được điều chỉnh riêng cho Unity và Unreal Engine. Tìm hiểu lý do việc dựa vào onTrimMemory dựa trên Java có thể gây ra tình trạng bế tắc trong Unity và cách sử dụng các lệnh gọi lại vòng đời gốc thay thế. Bạn cũng sẽ khám phá các điểm tối ưu hoá chính ở cấp tài sản, chẳng hạn như sử dụng chế độ nén hoạ tiết ASTC 8x8 và định cấu hình việc huỷ tải tài sản để trò chơi của bạn chạy mượt mà trên mọi cấp phần cứng.