03. FlatBuffers: 0 ms Parslash va Zero-Copy
gRPC & High-Performance System Design
03. FlatBuffers: 0 ms Parslash va Xotira Mo'jizasi (Zero-Copy)
"Eng tez kod — bu umuman ishlamaydigan koddur. Eng tez deserializatsiya — bu umuman deserializatsiya qilmaslikdir."
Oldingi darsda biz Protobuf qanday qilib JSON'dan 10 barobar tez ishlashini ko'rdik. Ammo Protobuf'da ham bir cheklov bor: u baribir binar baytlarni o'qib, xotirada yangi obyekt (struct yoki class) yaratadi (Deserialization).
Agar sizda sekundiga 60 ta kadr (60 FPS) chizilishi kerak bo'lgan o'yin, xaritadagi minglab taksilar harakati yoki 1 millionta obyekt bo'lsa-chi? Bu yerda sahnaga Google FlatBuffers (va Cap'n Proto) chiqadi!
1. Zero-Copy (Nol Nusxa) Nima Degani?
Oddiy tizimlarda ma'lumotlar oqimi:
Tarmoq (Socket) ---> Binar Baytlar ---> [PARSER / DECODER] ---> Xotirada Yangi Obyektlar (Heap Allocations)
FlatBuffers Zero-Copy tizimida:
Tarmoq (Socket) ---> Binar Baytlar (RAM ga yuklanadi)
^
| To'g'ridan-to'g'ri ko'rsatkich (Pointer Offset)
[Sizning Kodingiz] ---------------+ (0 ms, 0 bayt yangi RAM!)
FlatBuffers ma'lumotlarni xotiraga shunday joylashtiradiki, siz ularni deserializatsiya qilmasdan, to'g'ridan-to'g'ri binar massiv ustidan o'qiysiz!
2. FlatBuffers Sxemasi (.fbs)
// monster.fbs
namespace GameEngine;
enum Color:byte { Red = 0, Green, Blue = 2 }
table Vec3 {
x:float;
y:float;
z:float;
}
table Monster {
pos:Vec3;
mana:short = 150;
hp:short = 100;
name:string;
inventory:[ubyte];
color:Color = Blue;
}
root_type Monster;
3. Swift 6 da Zero-Copy O'qish
Qarang, hech qanday JSONDecoder().decode(...) yoki try Monster(serializedBytes: ...) yo'q!
import Foundation
import FlatBuffers
// 1. Tarmoqdan kelgan xom baytlar
let rawBytes: [UInt8] = networkPacketData
// 2. ByteBuffer yaratiladi (hech qanday xotira ko'chirilmaydi!)
var byteBuffer = ByteBuffer(bytes: rawBytes)
// 3. To'g'ridan-to'g'ri ko'rsatkich orqali o'qish
let monster = Monster.getRootAsMonster(bb: byteBuffer)
// 4. Qiymatlarni chaqirish (VTable offset orqali O(1) vaqtda olinadi)
print("Monstr nomi: \(monster.name ?? "")")
print("HP: \(monster.hp)")
print("Pozitsiya X: \(monster.pos?.x ?? 0)")
Bu Nega Mo'jiza?
Agar sizga 100 megabaytlik ma'lumot kelsa va sizga undan faqatgina bitta foydalanuvchining ismi kerak bo'lsa:
- JSON: 100 MB li matnning hammasini boshidan oxirigacha o'qib chiqishga majbur (2-3 soniya ketadi).
- Protobuf: 100 MB li binar faylning barcha maydonlarini xotiraga nusxalaydi (200-300 ms).
- FlatBuffers: Xotiradan faqat kerakli maydonning bayt manziliga sakraydi va uni o'qiydi (0.0001 ms!).
4. Benchmark: Protobuf vs FlatBuffers vs JSON
1,000,000 ta murakkab obyektni o'qish tezligi:
| Xususiyat | REST (JSON) | Protobuf v3 | FlatBuffers (Zero-Copy) |
|---|---|---|---|
| Deserializatsiya Vaqti | 1,850 ms | 160 ms | 0.02 ms (Instant!) |
| Xotira Ajratish (Allocations) | ~120 MB | ~18 MB | 0 Bayt (Zero Allocations) |
| Oldinga/Orqaga Moslik | Mavjud | Juda qulay | Juda qulay (VTable) |
| Foydalanish Sohalari | Oddiy Web | Microservices, gRPC | O'yinlar, AI modellar, Yuqori tezlik |
5. Qachon Qaysi Birini Tanlash Kerak?
- Protobuf + gRPC ni tanlang: Agar sizga mikroxizmatlararo aloqa, standart mobil API, qulay streaming va oson integratsiya kerak bo'lsa (Sanoat standarti).
- FlatBuffers ni tanlang: Agar sizda o'yinlar (Unity/Unreal), real-vaqtli 3D render, TensorFlow Lite neyrotarmoq og'irliklari, yoki soniyasiga millionlab binar voqealar oqimi bo'lsa.
- JSON ni tanlang: Faqat tashqi public API yoki oddiy CMS saytlar uchun.