DOTS là viết tắt của Data-Oriented Technology Stack, bao gồm các thư viện trong Unity giúp tạo trò chơi bằng lập trình hướng dữ liệu.

1. DOTS tối ưu truy cập bộ nhớ và CPU cache

Trước hết, cùng nói một chút về CPU cache. Khi CPU thực thi một lệnh truy xuất dữ liệu, dữ liệu này có thể nằm ở:

  • L1 Cache: tốc độ rất nhanh, dung lượng rất nhỏ
  • L2/L3 Cache: tốc độ nhanh, dung lượng lớn hơn một chút
  • RAM: dung lượng rất lớn, nhưng tốc độ chậm hơn hàng chục lần so với cache

Nếu CPU tìm thấy dữ liệu trong cache (hay còn gọi là "cache hit"), tốc độ sẽ cực nhanh. Ngược lại, nếu CPU phải truy cập RAM (hay còn gọi là "cache miss"), tốc độ sẽ rất chậm có thể lên đến vài trăm chu kỳ CPU.

Với GameObject, mỗi thành phần (ví dụ như Transform, RigidBody, CustomComponent) là một object C# tách biệt, với địa chỉ nằm ngẫu nhiên trong bộ nhớ. Ví dụ khi muốn lặp qua 1000 GameObject, CPU phải nhảy tới các địa chỉ trong bộ nhớ mà không theo quy luật nào. Việc này sẽ dẫn đến cache miss liên tục, nên tốc độ truy cập chậm.

Với DOTS, Entity Component System (ECS) được sử dụng để tổ chức và lưu trữ các thành phần giống nhau của nhiều entity một cách liên tục. Ví dụ có 128 quái vật, mỗi quái có PositionVelocity. Tất cả dữ liệu này nằm liền kề trong bộ nhớ như sau:

Position[0..127] (liên tục)
Velocity[0..127] (liên tục)
Với cách lưu trữ này, CPU chỉ cần duyệt qua địa chỉ của từng phần tử trong mảng một cách tuần tự trong bộ nhớ, nên CPU có thể dự đoán trước nạp sẵn dữ liệu sắp duyệt vào trong cache (tính năng Cache prefetching), từ đó tốc độ duyệt tăng lên đáng kể.

2. DOTS tận dụng CPU đa lõi

GameObject chủ yếu chạy trên luồng chính (main thread), trong khi DOTS tận dụng C# Job System để chạy song song các tác vụ trên các lõi khác nhau của CPU. Việc này giúp tận dụng sức mạnh của các CPU ngày này vì chúng thường có nhiều lõi.

3. DOTS cho phép quản lý bộ nhớ thủ công

Trong C#, Garbage Collection (GC) có thể làm game bị dừng trong vài mili-giây để dọn lượng lớn đối tượng không còn được sử dụng. Vài mili-giây nghe có vẻ nhanh nhưng vẫn đủ để người chơi nhận ra trong game và gây khó chịu.

Với DOTS, chúng ta có thể sử dụng các Native Collections không bị quản lý bởi GC. Việc này buộc chúng ta phải quản lý bộ nhớ thủ công và phải nhớ giải phóng bộ nhớ sau khi dùng xong, nhưng bù lại tránh được việc dừng game không mong muốn gây ra bởi GC.

4. DOTS sử dụng trình biên dịch mới Burst

Burst là trình biên dịch mới của Unity giúp chuyển mã C# thành mã máy. Nó được thiết kế với mục tiêu tối ưu cho hiệu năng nên nhanh hơn nhiều lần so với trình dịch cũ Unity sử dụng như Mono hoặc IL2CPP.

5. Kết luận

Mặc dù lập trình Unity với DOTS khá mới mẻ và khó tiếp cận hơn so với cách lập trình truyền thống bằng GameObject, nhưng nhờ hiệu năng vượt trội mà nó mang lại, chúng ta nên cân nhắc sử dụng DOTS cho các dự án game có nhiều đối tượng và yêu cầu hiệu năng cao, đặc biệt là các game MMO. Unity cũng đã phát triển Netcode for Entities nhằm hỗ trợ lập trình game online sử dụng DOTS.