Rumah  >  Artikel  >  hujung hadapan web  >  Analisis Prestasi JSON, Penampan / Protokol Binari Tersuai, Protobuf dan MessagePack untuk Websockets

Analisis Prestasi JSON, Penampan / Protokol Binari Tersuai, Protobuf dan MessagePack untuk Websockets

DDD
DDDasal
2024-11-03 07:28:03230semak imbas

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)

JSON

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)
})

Protokol Binari Tersuai

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.

Protobuf

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);
    });
})

MessagePack

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);
})

Penanda aras prestasi

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.

Penanda aras data kecil

ws.send(JSON.stringify({greeting: "Hello World"]}))

ws.on("message", (message) => {
    const data = JSON.parse(message);
    console.log(data)
})

Saiz bait setiap format bersiri

Method Byte size (bytes)
JSON 33
Custom Binary Protocol 13
Protobuf 17
MessagePack 24

Jumlah masa (ms)

Performance Analysis of JSON, Buffer / Custom Binary Protocol, Protobuf, and MessagePack for Websockets

Masa siri (ms)

Performance Analysis of JSON, Buffer / Custom Binary Protocol, Protobuf, and MessagePack for Websockets

Masa penyahserikatan (ms)

Performance Analysis of JSON, Buffer / Custom Binary Protocol, Protobuf, and MessagePack for Websockets

Penanda aras data sederhana

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);
});

Saiz bait mesej dalam setiap format bersiri

Method Byte size (bytes)
JSON 117
Custom Binary Protocol 70
Protobuf 75
MessagePack 102

Jumlah masa (ms)

Performance Analysis of JSON, Buffer / Custom Binary Protocol, Protobuf, and MessagePack for Websockets

Serialisasi (ms)

Performance Analysis of JSON, Buffer / Custom Binary Protocol, Protobuf, and MessagePack for Websockets

Penyahserikatan (ms)

Performance Analysis of JSON, Buffer / Custom Binary Protocol, Protobuf, and MessagePack for Websockets

Penanda aras data besar

syntax = "proto3";

message TestMessage {
    string text = 1;
    uint32 num = 2;
}

Saiz bait mesej dalam setiap format bersiri

Method Byte size (bytes)
JSON 329
Custom Binary Protocol 220
Protobuf 229
MessagePack 277

Jumlah masa (ms)

Performance Analysis of JSON, Buffer / Custom Binary Protocol, Protobuf, and MessagePack for Websockets

Serialisasi (ms)

Performance Analysis of JSON, Buffer / Custom Binary Protocol, Protobuf, and MessagePack for Websockets

Penyahserikatan (ms)

Performance Analysis of JSON, Buffer / Custom Binary Protocol, Protobuf, and MessagePack for Websockets

MessagePack tiba-tiba berhenti berfungsi pada kira-kira 6600 mesej dihantar.

Analisis penanda aras

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!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn