Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lets add http/3 support #14

Closed
4 of 10 tasks
frank-dspeed opened this issue Apr 11, 2021 · 31 comments
Closed
4 of 10 tasks

Lets add http/3 support #14

frank-dspeed opened this issue Apr 11, 2021 · 31 comments
Labels
enhancement New feature or request

Comments

@frank-dspeed
Copy link

frank-dspeed commented Apr 11, 2021

Trying to enable Quic - http/3 draft.

  • https://github.com/just-js/modules needs the patched openssl from Akamai and Microsoft.
    • BroingSSL Would be the correct SSL Lib by Googles Implementation
    • The Ring Crypto Package in Rust offers the needed Caps with nicer API
  • Overall It Translates to it does not matter if we use the quic implementation from google or cloudflare
    • Pro Google
      • is more mature
    • Pro Cloudflare
      • has the quicker iteration speed
      • nicer API
      • Would Produce RUST C => V8 Example usefull for all kind of people

Notes

Updates

Current Relevant Resources Readups

Ok good news SSL lib will be BoringSSL and we got a Rust Implementation that follows the standard and is deployed in production at cloudflare

Resources

@billywhizz
Copy link
Contributor

hi @frank-dspeed. not sure what you are proposing exactly? a module for http/3 support? that would be nice to have for sure. not so sure if http/2 is worth implementing. also a bit iffy about how much complexity http/3 adds. one of the things that is great about http/1.1 is it is so easy to debug and hack on and you definitely can't say the same for http/3 and QUIC, but that is the way a large part of the industry seems to be moving.

am happy to help out in any way if you want to suggest a plan for putting this together. using a patched openssl library should be pretty straightforward. i have only implemented bare minimum crypto and tls functionality with openssl so far. i also did an mbedtls module that i can resurrect if that would be useful. crypto/security not really my area of expertise so would be good to have someone involved who could advise on best practice etc.

@billywhizz billywhizz added the enhancement New feature or request label Apr 12, 2021
@frank-dspeed
Copy link
Author

@billywhizz i total understand your point but there are methods to debug that one common way is to store the key in a unencrypted way via the handshake and log it then you can decrypt the traffic as usal with wireshark and so on.

Out of my View Quic is Essential for Security and i want to produce Micro Services with that. A TCP Requests makes About 4 Roundtrips that cost me CPU and RAM before i can choose if the Connection is valid. So http/3 solves that for me and i can reduce DDoS Attacks.

That sayed. Http/3 Includes http/2 but i do not plan to implement it indipendent. I do not plan to offer a JS API for the http/2 part but that can be done by some one else later if he needs that.

@billywhizz
Copy link
Contributor

sounds good @frank-dspeed. if you want to discuss what's required let me know and i will help out whatever way i can. i'll see if i can get a change out in next week or so which will allow you to build an external module from a non just-js repo. it should be easy enough to set this up manually for now. will post some instructions later today if you haven't figured it out yourself.

@billywhizz
Copy link
Contributor

are you thinking of implementing the http/2 protocol part in JS or using nghttp2 like node.js does?

@frank-dspeed
Copy link
Author

frank-dspeed commented Apr 13, 2021

@billywhizz i will use and algin with https://github.com/stefanocasazza/ULib

but i will also test to implement it with nghttp2 and maybe even rust- i need to look what performs better

@billywhizz
Copy link
Contributor

@frank-dspeed have you looked at MSQuic at all? it seems like it might be a good candidate. will do some further research myself. https://techcommunity.microsoft.com/t5/networking-blog/making-msquic-blazing-fast/ba-p/2268963.

@billywhizz
Copy link
Contributor

also, there are some working low level ffi bindings examples here. they might be useful if you are experimenting.

@frank-dspeed
Copy link
Author

@billywhizz the ms stuff looks less performant as it uses openssl anyway under the hood https://microsoft.github.io/msquic/

but ya when it is easy integrate able it will do the job the first implementation doesn't need to be the best this is flexible enough to change that at anytime

@tomByrer
Copy link

tomByrer commented Jun 6, 2021

Seems that HTTP/3 is supported by 97% of the browsers that support HTTP/2. (Including Safari behind a flag.)
HTTP/2 is a multiplexing-streaming TCP protocol with prioritization & better header compression (never mind server push; few servers do that now anyhow, I could be interested, but that is a JustJS v2 IMHO).

I vote for HTTP/3 to be implemented first, HTTP/2 could be added later. Or the other way around? 🤷‍♂️
HTTP/1.1 is getting moldy ;)

@frank-dspeed
Copy link
Author

@tomByrer the problem is there are a lot of implementations around and i am not sure which should finally be supported

also i am not sure if it even should be directly implemented or if it would be better to use something like haproxy => http

it will take time to figure out the right solution. do you got a idea which would be the best option?

@tomByrer
Copy link

tomByrer commented Jun 8, 2021

got a idea which would be the best option

For HTTP/2 itself, or HTTP/3 vs 2?

I find Wikipedia has a decent listing of libraries for H3. I would believe those backed by corporations to be the most accurate & bug-free, though you could look at the fastest for inspiration.
https://en.wikipedia.org/wiki/HTTP/3#Libraries

H2 is not so easy to narrow down. This one is patched by Cloudflare, whom I'm a fanboi of:
https://github.com/hyperium/h2

@dumblob
Copy link

dumblob commented Jun 9, 2021

I personally prefer https://github.com/h2o/h2o/ - it covers all three major HTTP versions and their development cycle is well managed, test-backed, performance-measurements backed (ultra low latency, ~linear multithreaded scaling), etc. It's also plain C, so it works "everywhere".

@Wallacy
Copy link

Wallacy commented Aug 19, 2021

Anyway, just my two cents: https://github.com/cloudflare/quiche

@frank-dspeed
Copy link
Author

@Wallacy this is really low level but i think it is really a nice thing to have it as low level alternativ.

But my feeling is that for rapid development maybe something with more features like h2 could be better or even the nginx one we should not under estimate that we can use anything to embedded v8 inside it.

so we can apply both directions to our code we can include inside v8 and call into the the lib but we could also integrate v8 as a lib and call into that.

The hard point is now to decide the right processing mode and even enable diffrent once like Apache WebServer Did it.

mpm-prefork, mpm-event, mpm-worker.

@frank-dspeed
Copy link
Author

frank-dspeed commented Feb 7, 2022

Ok good news SSL lib will be BoringSSL and we got a Rust Implementation that follows the standard and is deployed in production at cloudflare

Resources

Open Source Repos

@alystair
Copy link

alystair commented Jul 7, 2022

Just a general note for no one in particular
https://github.com/litespeedtech/lsquic is actively maintained
https://en.wikipedia.org/wiki/HTTP/3#Implementations has a list of other potential implementations

@paulocoghi
Copy link

I believe the best approach is to look at quic-interop-runner, at https://interop.seemann.io/ , where many http/3 library implementations are tested both on interoperability and performance.

Then you can make a more informed decision, by knowing all the options, their implementations and dependencies, as well as their expected performance.

@billywhizz
Copy link
Contributor

from what i have looked at (not spent too much time on it), the MSFT Quic implementation seems to be the simplest and has a nice clean C api, which would be better for integrating with JS through bindings or FFI (which is now incredibly fast on JS, particularly V8).

One of the issues i have with most of the current implementations is they all want to take over the network interactions and/or the event loop, meaning we lose control from JS over non-blocking/async calls etc. If there is a set of QUIC/HTTP3 primitives available in library form that have nice clean C api's available and allow you to integrate your own event loop and network interfaces, please let me know.

The alternative of course would be to implement it from ground up in plain C/JS and engineer it specifically to integrate with and perform well embedded in JS, but this would be a pretty big undertaking.

@paulocoghi
Copy link

Looking at the detailed implementations list, https://github.com/quicwg/base-drafts/wiki/Implementations , another possible candidate is picoquic

@billywhizz
Copy link
Contributor

billywhizz commented Oct 1, 2023

thanks @paulocoghi. yes, picoquic looks nice - i actually had it already starred but had forgotten about it. 😅

this kinda relates to another dilemma i have with the Just-JS "approach". while v8 is incredibly fast and has tons of nice features and is incredibly well supported, it is becoming monstrously big as time goes on. i recently went from a version of v8 from may to the latest beta version and my runtime size went from ~23 MB to ~28MB 😨. The original Just-JS release from 2020 was 17MB).

I know QuickJS is an alternative and there are many other JS runtimes tailored for embedded systems, but none of them have JIT so performance on most tasks is orders of magnitude less than V8.

it may be possible to abstract away the interactions with the JS engine underneath and then build for different platforms using different JS engines. One of the nice things about the code i will be releasing is there is minimal C/C++ and most of the C/C++ is autogenerated from JS api definitions. You can see an early iteration of it here but it has changed a lot since then. I should be able to get the code out this week and hopefully there are some folks interested in discussing ways forward.

@paulocoghi
Copy link

paulocoghi commented Oct 2, 2023

i recently went from a version of v8 from may to the latest beta version and my runtime size went from ~23 MB to ~28MB 😨. The original Just-JS release from 2020 was 17MB).

I believe this isn't a big problem, considering the notorious performance benefit. Also, you are a lot better than the executable size generated by Bun:

Command Binary size xz / gz / zip compressed cold startup warm startup peak memory usage (binary)
bun build ./index.js --compile --outfile hello 94M 23M / 35M / 33M 0.025s 0.025s 32.9M
bkg -o hello . 42M 30M / 35M / 34M 5.430s 0.029s 36.4M
pkg -t node18-linux index.js 45M 13M / 18M / 17M 0.115s 0.116s 38.5M

I know QuickJS is an alternative and there are many other JS runtimes tailored for embedded systems, but none of them have JIT so performance on most tasks is orders of magnitude less than V8.

To this day, nothing can beat v8 and JSC. Even Spidermonkey can't (currently), but there are some experiments trying to create a runtime based on it (spiderfire).

@paulocoghi
Copy link

IMHO, the only scenario where the performance would be (maybe) comparable when using lightweight JS implementations like QuickJS, is when all the heavy lifting (like http calls, filesystem, general I/O, etc) is made outside of JS.

This would bring faster startup times compared to JIT runtimes, and (maybe) comparable performance for everything (that matters).

@leeoniya
Copy link

leeoniya commented Oct 2, 2023

Also, you are a lot better than the executable size generated by Bun:

i was gonna link oven-sh/bun#2541, but looks like you've seen it :)

@paulocoghi
Copy link

paulocoghi commented Oct 2, 2023

@leeoniya Great observation! Changing the unicode library to a lighter one can help a lot.

@billywhizz , do you think its feasible to replace v8's original unicode library to a lighter one, like icu4x?

@billywhizz
Copy link
Contributor

@paulocoghi

i recently went from a version of v8 from may to the latest beta version and my runtime size went from ~23 MB to ~28MB 😨. The original Just-JS release from 2020 was 17MB).

yeah. all the other runtimes are huge and increasing rapidly as they add more "features". this is basically what i would like to avoid. a very small core that doesn't change very much over time and allows all the other things to grow on top of it. or not - maybe folks will only want to do low-level things with it. there was a big debate in node.js over this back in the early days and the "batteries included" folks won. probably why they are so popular now though. i'm not expecting anything done here to be competition for bun/node.js/deno - rather, an alternative approach.

if you want to bundle your app and all it's assets into a single static binary that also makes things smaller - usually by a few megabytes. so you should be able to get redistributable single binaries down to around ~25 MB at the lower end. it used to 16-17 MB not so long ago.

I have also done some experiments with bundling the application into a shared library, which can be loaded and run by the main spin runtime. these can be super tiny - a few hundred kilobytes as long as you have the runtime installed wherever you intend to run.

@billywhizz
Copy link
Contributor

IMHO, the only scenario where the performance would be (maybe) comparable when using lightweight JS implementations like QuickJS, is when all the heavy lifting (like http calls, filesystem, general I/O, etc) is made outside of JS.

This would bring faster startup times compared to JIT runtimes, and (maybe) comparable performance for everything (that matters).

@paulocoghi yes, QuickJS can have fast bindings to C/C++ and can be fast if you can avoid writing much if any JS, but that wouldn't really work for what i am aiming for - i want folks writing more JS and only putting the minimum necessary code in C/C++/Rust land. with v8 fastcalls, the overhead into C++ from v8 JS is only ~2 nanoseconds which is negligible if you are doing mostly syscalls.

@billywhizz
Copy link
Contributor

@leeoniya Great observation! Changing the unicode library to a lighter one can help a lot.

@billywhizz , do you think its feasible to replace v8's original unicode library to a lighter one, like icu4x?

@paulocoghi i haven't looked into Unicode much. It's not even bundling ICU at the moment so no Intl. I will have a look and see what this will add to size. but i think it could be easily made optional if you don't need it for your final build.

@alystair
Copy link

alystair commented Oct 3, 2023

@leeoniya I can't believe what a small world this is. I used your dump_r package for years until it stopped working. I know this is horribly off-topic but please consider updating it based on one of the many forks to make it php8 compatible, don't force me to use Symphony's lesser var_dump 🙏

@leeoniya
Copy link

leeoniya commented Oct 3, 2023

don't force me to use Symphony's lesser var_dump 🙏

haha, don't force me to touch php again :D. i don't miss that dumpster fire or its lang committee's endless bikeshedding one bit.

@paulocoghi
Copy link

paulocoghi commented Oct 3, 2023

I have also done some experiments with bundling the application into a shared library, which can be loaded and run by the main spin runtime. these can be super tiny - a few hundred kilobytes as long as you have the runtime installed wherever you intend to run.

Wow! Just wow! This seems an interesting approach! And I can already imagine Just/Spindle library becoming standard on major Linux distributions. Using it will be just an "apt-get/dnf install" away.

@billywhizz I sent you an email.

@billywhizz
Copy link
Contributor

@paulocoghi

Wow! Just wow! This seems an interesting approach! And I can already imagine Just/Spindle library becoming standard on major Linux distributions. Using it will be just an "apt-get/dnf install" away.

yeah. one of the things i am looking at as i said is pretty much busybox but in JS. can also do really nice things with bundling like take your app and bundle it straight into an init which will be booted into in a VM. this should save some time off cold starts. i've done tons of mad experiments like this. the endpoint could be a whole linux distro completely written in JS, except for the kernel of course. you can also package your apps as vmlinux and have them run inside their own linux kernel from the shell.

is why i think exposing these lower level apis to JS without having lots of layers of abstraction could be a really nice feature. once you can get at those low level api's all sorts of new things become possible (from JS) and everything becomes a lot simpler and easier to reason about. imo anyway. 😅

i also have an x86_64 machine code generator which i used for creating ffi bindings instead of relying on libffi, which imo is kinda clunky. let's make all the things JS and have some fun! 🥳

if nothing else, i think it would be a useful thing for experimentation and education. i've been really enjoying hacking on it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

8 participants