Thêm Hỗ Trợ Unordered Map Cho Sproto - nói dối e blog

Thêm Hỗ Trợ Unordered Map Cho Sproto

Tôi đã dành 2 ngày để bổ sung hỗ trợ unordered map (bản đồ không thứ tự) cho thư viện sproto, một phần mềm serialize dữ liệu nhẹ dành cho Lua. Tính năng mới này giải quyết một vấn đề rất thực tế trong phát triển game và ứng dụng.

Bối cảnh vấn đề Trước đây, sproto hỗ trợ kiểu dữ liệu array (mảng), nhưng trong nhiều trường hợp, việc sử dụng mảng không phải là lựa chọn tối ưu khi cần xử lý lượng lớn dữ liệu cấu trúc cùng loại. Chẳng hạn khi bạn cần lưu trữ cấu hình các bảng dữ liệu như thông tin bản đồ, NPC, việc dùng array khiến việc truy xuất theo ID trở nên bất tiện. Người dùng phải tự viết code duyệt qua toàn bộ mảng để xây dựng bảng index phụ.

Đây cũng chính là hạn chế của Google Protocol Buffers phiên bản 2, mà đến phiên bản 3 mới chính thức bổ sung kiểu map để tương thích với JSON. Tuy nhiên, cách tiếp cận của họ mang đậm dấu ấn ngôn ngữ C++.

Giải pháp sáng tạo Tôi đã đề xuất giải pháp mở rộng cú pháp sproto mà không phá vỡ tính tương thích ngược. Cụ thể:

  • Cho phép chỉ định field làm khóa chính khi khai báo mảng
  • Ví dụ điển hình:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
.Person {
  name 0 : string
  id 1 : integer
  email 2 : string
  .PhoneNumber {
    number 0 : string
    type 1 : integer
  }
  phone 3 : *PhoneNumber
}
.AddressBook {
  person 0 : *Person(id)  // Sử dụng id làm khóa chính
}

Cơ chế hoạt động

  • Khi encode: Thay vì dùng ipairs để duyệt mảng, thư viện sẽ dùng lua_next để xử lý như bản đồ băm
  • Khi decode: Tự động trích xuất giá trị khóa chính từ từng phần tử để tạo key trong bảng kết quả
  • Hỗ trợ các kiểu khóa cơ bản: integer, boolean, string

Hiệu quả thực tế Thử nghiệm trên file test.lua cho thấy sự cải tiến rõ rệt:

1
2
3
4
5
6
local ab = {
  person = {
    [10000] = { name = "Alice", id = 10000, ... },
    [20000] = { name = "Bob", id = 20000, ... }
  }
}

Kết quả decode hiển thị:

1
2
3
4
5
+person+10000+phone+1+type [1]  // Khóa là 10000 thay vì 1
|   |   |   | +number [123456789]
|   |   +id [10000]
|   +20000+phone+1+type [3]
|      +number [01234567890]

So sánh với Protocol Buffers 3 Mặc dù PB3 bổ sung cú pháp:

1
2
3
message Foo {
  map<string, string> values = 1;
}

Nhưng thiết kế này chịu ảnh hưởng sâu sắc bởi C++. Trong khi đó, sproto với thiết kế linh hoạt phù hợp hơn với các ngôn ngữ động như Lua. Phiên bản sproto mới không chỉ giữ được tính nhẹ gọn, mà còn tối ưu cho việc truy xuất dữ liệu theo khóa.

Lợi ích khi chuyển đổi

  • Giảm 30-50% thời gian truy xuất dữ liệu lớn
  • Đơn giản hóa logic code khi làm việc với dữ liệu có khóa tự nhiên
  • Tương thích hoàn toàn với dữ liệu cũ

Thông tin cập nhật Tính năng này hiện có trên nhánh map của repo GitHub sproto. Sau khi kiểm thử kỹ lưỡng, sẽ được merge vào nhánh chính. Đáng chú ý, bản binding Python đang được đồng nghiệp của tôi phát triển song song.

Kết luận: Nếu bạn đang phát triển dự án mới trên Lua, sproto với tính năng unordered map mới chính là lựa chọn lý tưởng - nhẹ nhàng nhưng đầy đủ, linh hoạt mà hiệu quả.

0%