Cải thiện việc sử dụng bộ nhớ phía trước lên gấp 30 lần khi tải Carousel

Trong quý 2 năm 2020, chúng tôi đã tiến hành tái cấu trúc kỹ thuật trên trang trải nghiệm, viết lại bằng React và sử dụng REST API. Nhưng trong quá trình triển khai, chúng tôi đã phát hiện ra một vấn đề thú vị.
Có khoảng 20 carousel trên trang trải nghiệm, mỗi carousel có ít nhất 60 ô. Vì vậy, trang sẽ hiển thị hơn 1.200 trải nghiệm, bao gồm các thông tin liên quan như tiêu đề, xếp hạng của người dùng, số người dùng đồng thời và hình thu nhỏ. Trong mỗi carousel, khi nhấp vào thanh cuộn bên phải, một yêu cầu sẽ được gửi để tải đợt trải nghiệm tiếp theo nếu còn. Sau đó, dữ liệu mới từ yêu cầu này sẽ được thêm vào carousel, có nghĩa là sẽ có thêm các nút được thêm vào DOM và thêm các hình thu nhỏ được hiển thị trong trình duyệt. Dung lượng bộ nhớ trong trình duyệt sẽ tăng lên khi người dùng cuộn để yêu cầu thêm dữ liệu, và sau đó trải nghiệm người dùng sẽ chậm lại và bắt đầu bị giật.

Phân tích bộ nhớ
Chúng ta có thể sử dụng Công cụ phát triển Chrome để phân tích vấn đề này. Ảnh chụp đầu tiên được thực hiện khi trang tải lần đầu tiên, và ảnh chụp thứ hai được thực hiện sau khi người dùng nhấp vào cuộn tiếp theo trong một carousel 12 lần. Chúng ta thấy mức sử dụng bộ nhớ tăng gần 9,7MB do hơn 100 nút chuỗi và việc hiển thị hình thu nhỏ tăng lên.

Giải pháp
Khi carousel cuộn, người dùng chỉ xem các mục từ cửa sổ carousel. Ví dụ, trên laptop có độ phân giải 1920×1080, trong chế độ toàn màn hình của trình duyệt, mỗi lần chỉ hiển thị khoảng 9 mục. Do đó, không cần thiết phải hiển thị tất cả các nút và hình thu nhỏ không hiển thị cùng lúc hoặc đưa thêm dữ liệu trả về từ yêu cầu vào DOM.
Vậy, đây là ý tưởng: sau khi lấy dữ liệu thô từ yêu cầu API lần đầu tiên, chúng ta tạo một mảng có độ dài tương ứng để chuẩn bị hiển thị vào DOM. Trong mảng hiển thị này, chúng ta chỉ điền đủ dữ liệu để lấp đầy màn hình và cuộn sang mục tiếp theo. Phần còn lại của mảng sẽ chỉ được điền khi cửa sổ hiển thị cuộn gần đến vị trí đó. Hãy định nghĩa hai chỉ số để ghi lại phạm vi dữ liệu hiển thị: renderingStartIndex và renderingEndIndex. Chúng ta thiết lập một con trỏ để xác định vị trí bắt đầu nào trong danh sách là hiển thị. Khi cuộn, chúng ta cần liên tục cập nhật con trỏ đến chỉ số của mục hiển thị đầu tiên. Trước khi hiệu ứng cuộn kết thúc, chúng ta cần kiểm tra xem con trỏ tiếp theo có nằm trong mảng dữ liệu hiển thị hay không. Dựa trên kích thước cửa sổ carousel và kích thước thẻ, chúng ta có thể dễ dàng xác định số lượng mục hiển thị sẽ vừa với cửa sổ hiển thị. Sau đó, chúng ta cần đảm bảo các mục từ cửa sổ hiện tại và cửa sổ tiếp theo nằm trong phạm vi của mảng dữ liệu hiển thị. Nếu không, chúng ta sẽ lấy các mục từ dữ liệu thô để điền vào danh sách trống đồng thời xóa dữ liệu trước vị trí con trỏ. Điều này áp dụng khi người dùng cuộn sang phải hoặc trái. Khi người dùng cuộn sang phải, bằng cách lấy thêm dữ liệu ở chế độ nền, chúng ta sẽ điền dữ liệu thô vào mỗi lần sau khi nhận được dữ liệu mới. Tuy nhiên, dữ liệu thô sẽ không được sử dụng trong việc hiển thị trang.


Hồ sơ bộ nhớ
Hãy xem lại Công cụ phát triển Chrome. Như trước đó, ảnh chụp đầu tiên được thực hiện tại thời điểm khởi tạo và ảnh chụp thứ hai được thực hiện sau khi cuộn sang phải 12 lần. Hiện tại, việc tải hơn 100 mục chỉ tiêu tốn thêm 0,3MB bộ nhớ, so với 9,7MB trước đó.

Tiếp theo là gì?
Ngoài việc cải thiện thành phần carousel để xử lý các cửa sổ dữ liệu lớn, khi chúng tôi tái cấu trúc một tính năng/trang, chúng tôi cần thêm nhiều điểm chuẩn hơn để thu thập thông tin về hiệu suất.
Mặc dù nền tảng ứng dụng web hiện đại đang chuyển dịch sang phía front-end, việc thu thập và cải thiện dữ liệu theo dõi phía front-end cũng quan trọng không kém so với dữ liệu theo dõi phía back-end truyền thống.
Ying Jiang là Kỹ sư Phần mềm Frontend Chính tại Roblox. Là Kỹ sư Frontend đầu tiên của Roblox, cô làm việc để giới thiệu công nghệ frontend hiện đại vào Roblox và cải thiện quy trình phát triển và triển khai. Cô cũng đã làm việc trên các tính năng thời gian thực như trò chuyện, luồng thông báo và giọng nói.
Cả Roblox Corporation lẫn blog này đều không ủng hộ hay hỗ trợ bất kỳ công ty hay dịch vụ nào. Ngoài ra, không có bất kỳ đảm bảo hay cam kết nào được đưa ra về tính chính xác, độ tin cậy hoặc tính đầy đủ của thông tin được trình bày trong blog này.


