Browser Dialer: Change from ES5 to ES6+ for performance #3832
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
First of all... What. The. Heck.
Problems with the current code
I can only do so much to try getting the current code up to shape.
A mix of ES5 and ES6+ syntax in compatible mode
I really don't know if the browser dialer was designed to work on Internet Explorer, but proper web stream API support don't really exist on that platform. So why didn't the browser dialer have strict mode enabled when this could bring performance gains...
Unscoped value declarations with
var
TL;DR, avoid using
var
at all costs.var
introduces problems of the yesteryear, wherelet
declarations are much safer, cleaner and straightforward, with stricter constraints allowing the JS JIT to work more efficiently.Uses
if
-else
chains instead ofswitch
I don't know why
if
-else
chains are used instead ofswitch
, as this isn't either C or C++. Both JS and Go support using switch on any type, and JS in specific has single-pass optimizations forswitch
statements, avoiding sequentially querying for each possibility.Fundamental design flaws
The problems
I have no idea why the data plane and the control plane are smashed together. Evident in the code that each message of the single local WebSocket connection is parsed, where with a separation of data plane and control plane can avoid most of the processing. Unless it's tuned for the individual upload packets SplitHTTP needs, so in this specific case data could be smashed together. Since WebSocket can overwhelm the browser easily with enough throughput and without any counteracting measure, the only solution for now would be get rid processing as much as possible on the data plane.
And somehow the browser dialer of SplitHTTP is implemented via WebSocket instead of
fetch
request in either direction. At least on Chrome,ReadableStream
could be set as the body, so instead of reading and processing chunks, bodies can simply be passed along without the browser doing much at all. Even better, since Chrome has streaming support for WebSocket in the latest versions, a zero-cost optimization is incredibly feasible with separated control and data planes.A probably better design
Feel free to conduct critique on this, as this isn't fleshed out much yet.
/control?token=csrfToken
Control socket. Where the control messages should go, be it
WS
,GET
orPOST
. Though non-streamed uploads should go here as well to reduce the overhead./ws?socket=aRandomId
Direct WebSocket message pass-through between the server and the client.
/http?socket=aRandomId&role=ingress
Where the magic for streamed web request happens. Allows stream pass-through without any manual reading, unless it's on Firefox.
Because the browser doesn't support
h2c
, two request streams for each client-facing streamed SplitHTTP connection are required.ingress
streams are what the Xray server sends to the client, andegress
streams are what the client sends to the server.