5 ms·
Why not just gzip the data? It might not beat a bespoke hand-crafted protocol that minimizes message size, but your use of the word "negotiate" makes me think
by chaosite 3y ago
Why not just gzip the data?
It might not beat a bespoke hand-crafted protocol that minimizes message size, but your use of the word "negotiate" makes me think that that's not what you're taking about...
- Timon3 3y agoThe embedded device the server is running on has a very weak CPU. Since I'm trying to optimize throughput this would have quite an impact. It's fine if the first few messages are slow, the speed just has to pick up after initialization is done, which is why negotiation is okay for me. So e.g. the client requesting IDs for every method on first connection would be fine, and would keep complexity down.
- marksomnian 3y agoI imagine you could write a custom tRPC link to send the data over something like MQTT which may be better for an embedded client - there's prior art in the likes of electron-trpc, showing how tRPC could be adapted to non-HTTP transports. Not sure how that interacts with the JSON-RPC bits of the subscription protocol though, if there's no way around it then plain MQTT may be better suited to your use case.
- Timon3 3y agoThank you for the suggestions! I am specifically looking to optimize frontend-to-server communication, so WebSocket is a must. Is there some way I could inject a custom transform function between TRPC and the WebSocket? I could copy the existing WebSocket link and add my transform in there, but it would of course be easier if I could just do my own wire handling with the existing code. Essentially I'd like to inject a custom respond[0] encoder and a custom parseMessage[1] decoder, and same for the client. [0]: https://github.com/trpc/trpc/blob/main/packages/server/src/adapters/ws.ts#L123-L129 https://github.com/trpc/trpc/blob/main/packages/server/src/a... [1]: https://github.com/trpc/trpc/blob/main/packages/server/src/adapters/ws.ts#L284 https://github.com/trpc/trpc/blob/main/packages/server/src/a...
- Timon3 3y agoUpdate: I was able to get this working by wrapping WebSocket and WebSocketServer! The API surface for the wrapper seems to be pretty minimal. If I do use TRPC in the rewrite of the embedded server, I'll implement a custom message scheme as an alternative and benchmark them. Here's a gist with the wrappers (transporting the data as a JSON array instead of a dict): https://gist.github.com/TimonLukas/7c757a3b234344ad71e6bd5a6a10adc1 https://gist.github.com/TimonLukas/7c757a3b234344ad71e6bd5a6... It's not ideal insofar that I have to parse the stringified JSON again. Some kind of real "encoder/decoder" parameter could be an amazing help.
- Timon3 3y agoUpdate: I've now implemented a small PoC with ID negotation, you can see it here: https://gist.github.com/TimonLukas/c0bb7e8f9bde9d3d74d6b776b5abdb72 https://gist.github.com/TimonLukas/c0bb7e8f9bde9d3d74d6b776b... This will reduce message size quite a bit, since the data isn't sent as: { "id": 3, "method": "subscription.stop" } but instead as: [3,1]
- Timon3 3y agoUpdate: I've implemented a simple TS library around this: https://github.com/TimonLukas/ts-websocket-compressor https://github.com/TimonLukas/ts-websocket-compressor I will add wrappers for WebSocket/WebSocketServer in the future to allow using this without the library having to support it, like in the PoC with trpc.