Open paralin opened 6 months ago
Dial is a global function and the value returned on wasm is a dummy value.
Are people using these in interfaces? is that why? Other than that it seems like anyone using Dial would already be ignoring the dummy value on wasm.
People could be wrapping this library in some kind of API/helper for their own code and they might be checking resp or passing it up the chain. This patch would break that.
I don't know if it's common but it doesn't seem far fetched to me. I don't have a better suggestion unfortunately. I'll leave this open for now, let's see if anyone else has thoughts.
Hey @paralin. Thanks for this proposal, the weight reduction is impressive but I believe this is an uphill battle. For instance, in #373 there's a request to introduce *http.Client
as well as make the DialOptions
struct the same for both wasm and non-wasm.
We also want to avoid breaking the API while we're v1, targeting API breakages for a potential v2 in the future is of course an option, but will not be done lightly.
With these constraints in mind, I don't see how we could support this. The only option I can think of is to let users opt-in via a build tag, say GOOS=js GOARCH=wasm go build -tags slim
. As a result, we could radically change the wasm API and simplify the return values.
But before we consider adding more complexity to the code-base, I'd like to hear about use-cases where this weight reduction is necessary.
In a web browser app using wasm with Go, any weight reduction is significant.
While going through the list of packages taking up space in the binary, net/http was at the top of the list.
6.6 MB net/http
As of January 2024, the average download speed globally for mobile internet was 50 Mbps
That's around 1 second of time spent downloading net/http, and even a second delay loading a website feels like a lot.
Of course gzip / brotli compression reduces this significantly.
I understand the desire to keep API compatibility. I also use fetch on wasm to reduce binary size: https://github.com/aperturerobotics/util/blob/master/js/fetch/fetch.go
@paralin what you say makes sense but what I'm looking for is concrete use-cases. Code where you're using websocket
and building for wasm, without importing anything from net/http
.
If I'd write a program only using websocket.Dial
, the difference wouldn't be all that big:
❯ ls -lha
total 7.1M
drwxr-xr-x 2 coder coder 4.0K Aug 21 12:24 ./
drwxr-xr-x 5 coder coder 4.0K Aug 21 12:24 ../
-rwxr-xr-x 1 coder coder 3.1M Aug 21 12:24 dial-master*
-rwxr-xr-x 1 coder coder 897K Aug 21 12:24 dial-master.gz*
-rwxr-xr-x 1 coder coder 2.4M Aug 21 12:24 dial-pr*
-rwxr-xr-x 1 coder coder 704K Aug 21 12:24 dial-pr.gz*
-rw-r--r-- 1 coder coder 271 Aug 21 12:23 main.go
Sure, 0.7M
is still significant, as is 193K
gzipped. The thing we need to evaluate though is if the cost of supporting this use-case is worth the gain. How big will the gain be? How easy is it to write and maintain a program with no imports from http
, etc? And that's where real-world use-cases come in and would help a lot.
The concrete use case is compiling a wasm binary and running it in a webpage, then using websocket.Dial. It's quite easy to make a program that dials a websocket and exchanges messages with a server in wasm that doesn't otherwise use net/http.
That said if it requires a separate go tag I probably wouldn't use the feature and would just keep using my forked version. No worries if you don't feel that the 0.7MB difference is worth it. It definitely is in wasm apps though, and as wasm and go become more developed and widely used, this kind of size savings will become more valuable. At the moment it probably doesn't matter to anyone that wouldn't just fork the package for their use case anyway.
Using goweight: https://github.com/paralin/goweight
GOOS=js GOARCH=wasm goweight | less
Without this change:
7.9 MB runtime 6.6 MB net/http 3.1 MB net 3.0 MB crypto/tls 2.0 MB reflect 1.4 MB math/big 1.3 MB crypto/x509 935 kB os ...
With this change:
7.9 MB runtime 3.1 MB net 2.0 MB reflect 935 kB os ...
Slight modifications to avoid importing net/http reduce the binary size significantly.