Artikel ini mengkaji dan membandingkan penyirian data dan penyahserikatan kaedah / format: JSON, Penampan (protokol binari tersuai), Protobuf dan MessagePack serta menawarkan panduan tentang cara melaksanakannya . (penanda aras prestasi pada penghujung)
Ini ialah kaedah yang paling biasa untuk menghantar mesej ialah JSON. Tempat anda mengekod data kepada rentetan supaya ia boleh dihantar melalui mesej Websocket dan menghuraikannya kembali.
ws.send(JSON.stringify({greeting: "Hello World"]})) ws.on("message", (message) => { const data = JSON.parse(message); console.log(data) })
Satu protokol binari tersuai ialah pelaksanaan tersuai yang ringan bagi mensiri dan menyahserialisasi data. Ia biasanya digunakan apabila kelajuan, prestasi dan pendaman rendah adalah penting cth. permainan berbilang pemain dalam talian dan banyak lagi (atau jika anda mahu mengoptimumkan apl anda). Apabila membina protokol binari tersuai, anda bekerja dengan penimbal dan binari, yang mungkin sukar untuk dilaksanakan, namun jika anda mempunyai pengetahuan tentang penimbal dan binari, ia sepatutnya tiada masalah.
const encoder = new TextEncoder(); const decoder = new TextDecoder(); function binary(text, num) { const messageBytes = encoder.encode(text); // array buffers cannot store strings, so you must encode // the text first into an array of binary values // e.g. "Hello World!" -> [72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33] const buffer = new ArrayBuffer(1 + messageBytes.length); // when creating array buffers, //you must predetermine the size of your array buffer const view = new DataView(buffer); // create a view to interact with the buffer view.setUint8(0, num); const byteArray = new Uint8Array(buffer); byteArray.set(messageBytes, 1); return buffer; } ws.on("open", () => { const msg = binary("Hello World!", 123); ws.send(msg); }) ws.on("message", (message) => { const buffer = message.buffer; const view = new DataView(buffer); const num = view.getUint8(0); const textLength = buffer.byteLength - 1 const textBytes = new Uint8Array(buffer, 1, textLength); const text = decoder.decode(textBytes); console.log(text, num); });
Fungsi ini mensiri dua sifat, satu menjadi teks dan satu lagi menjadi nombor menjadi penampan tatasusunan.
Dalam contoh kod ini, saya menggunakan protobuf.js, pelaksanaan javascript bagi protobuf. Saya menggunakan refleksi untuk menjana kod protobuf semasa runtime. Anda juga boleh menjana kod secara statik, tetapi ia tiada kesan pada prestasi menurut wiki protobuf.js, namun ia memuatkan kod protobuf dengan lebih pantas, tetapi itu tidak memberi kesan kepada prestasi sama sekali semasa menghantar mesej websocket.
syntax = "proto3"; message TestMessage { string text = 1; uint32 num = 2; }
import protobuf from "protobufjs"; const ws = new Websocket("ws://localhost:3000"); ws.binaryType = "arraybuffer"; protobuf.load("testmessage.proto", function (err, root) { if (err) throw err; if (root === undefined) return; const TestMessage = root.lookupType("TestMessage") ws.on("open", () => { const message = TestMessage.create({text: "Hello World!", num: 12345}); const buffer = TestMessage.encode(message).finish(); ws.send(buffer); }); ws.on("message", (msg) => { const buffer = new Uint8Array(msg); const data = TestMessage.decode(buffer); console.log(data.text); console.log(data.num); }); })
import { encode, decode } from "@msgpack/msgpack"; ws.binaryType = "arraybuffer" ws.on("open", () => { const msg = encode({"Hello World!", 123}); ws.send(msg); }) ws.on("message", (msg) => { const data = decode(msg); console.log(data); })
Untuk membandingkan prestasi setiap pesirisian data format / kaedah, saya telah menulis penanda aras yang mengukur prestasi semasa menghantar data melalui Soket Web.
Saya telah membahagikan penanda aras kepada kumpulan yang berbeza.
Input data kecil
Input data sederhana
Input data besar
Ini adalah untuk mengukur prestasi siri data ini pada saiz data yang berbeza. Saya juga telah merekodkan prestasi penyerialisasian, penyahserikatan dan jumlah masa untuk setiap kumpulan. Saya telah menjalankan penanda aras tepat 5 kali untuk setiap kumpulan dan mengira purata untuk memastikan kebolehpercayaan ujian ini.
Penanda aras menghantar mesej Websocket dalam 100,000 lelaran. Kod ditulis dalam Bun.js
Penanda aras ini direkodkan dalam masa untuk selesai (ms), jadi lebih kecil lebih cepat.
ws.send(JSON.stringify({greeting: "Hello World"]})) ws.on("message", (message) => { const data = JSON.parse(message); console.log(data) })
Method | Byte size (bytes) |
---|---|
JSON | 33 |
Custom Binary Protocol | 13 |
Protobuf | 17 |
MessagePack | 24 |
const encoder = new TextEncoder(); const decoder = new TextDecoder(); function binary(text, num) { const messageBytes = encoder.encode(text); // array buffers cannot store strings, so you must encode // the text first into an array of binary values // e.g. "Hello World!" -> [72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33] const buffer = new ArrayBuffer(1 + messageBytes.length); // when creating array buffers, //you must predetermine the size of your array buffer const view = new DataView(buffer); // create a view to interact with the buffer view.setUint8(0, num); const byteArray = new Uint8Array(buffer); byteArray.set(messageBytes, 1); return buffer; } ws.on("open", () => { const msg = binary("Hello World!", 123); ws.send(msg); }) ws.on("message", (message) => { const buffer = message.buffer; const view = new DataView(buffer); const num = view.getUint8(0); const textLength = buffer.byteLength - 1 const textBytes = new Uint8Array(buffer, 1, textLength); const text = decoder.decode(textBytes); console.log(text, num); });
Method | Byte size (bytes) |
---|---|
JSON | 117 |
Custom Binary Protocol | 70 |
Protobuf | 75 |
MessagePack | 102 |
syntax = "proto3"; message TestMessage { string text = 1; uint32 num = 2; }
Method | Byte size (bytes) |
---|---|
JSON | 329 |
Custom Binary Protocol | 220 |
Protobuf | 229 |
MessagePack | 277 |
MessagePack tiba-tiba berhenti berfungsi pada kira-kira 6600 mesej dihantar.
Dalam semua penanda aras, protokol binari tersuai adalah yang terpantas dalam jumlah masa dan mempunyai saiz bait terkecil / paling cekap semasa membuat siri mesej. Walau bagaimanapun, perbezaan prestasi adalah ketara.
Apa yang mengejutkan, masa penyiaran JSON' ialah lebih cepat dengan ketara daripada penyiaran Protokol Binari Tersuai. Ini mungkin kerana JSON.stringify() dilaksanakan c asli dengan Node dan zig asli dengan Bun. Keputusan juga mungkin berbeza apabila menggunakan Node kerana JSON.stringify() dengan Bun adalah 3.5x lebih pantas daripada Node.
MessagePack berpotensi menjadi lebih pantas kerana dalam penanda aras ini, saya menggunakan pelaksanaan MessagePack javascript rasmi. Terdapat pelaksanaan MessagePack lain yang berpotensi lebih pantas seperti MessagePackr.
Terima kasih kerana membaca!
Tanda aras (ditulis dalam skrip taip): https://github.com/nate10j/buffer-vs-json-websocket-benchmark.git
Lihat hasil di sini dalam helaian google.
Atas ialah kandungan terperinci Analisis Prestasi JSON, Penampan / Protokol Binari Tersuai, Protobuf dan MessagePack untuk Websockets. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!