Stream: contributing

Topic: basic-cli reqwest lib size


view this post on Zulip Brendan Hansknecht (Nov 15 2023 at 22:13):

Circling back on basic cli size. Just pulled current basic cli sizes.

With the reqwest library: 6.7MB
Without the reqwest library: 1.1MB

view this post on Zulip Brendan Hansknecht (Nov 15 2023 at 22:14):

After that, backtraces are the next biggest contributor to bloat.

view this post on Zulip Richard Feldman (Nov 15 2023 at 22:24):

wow, is there any way to make reqwest smaller? :sweat_smile:

view this post on Zulip Brendan Hansknecht (Nov 15 2023 at 22:28):

We could try ureq or similar if we can make it fit a nice API.

view this post on Zulip Richard Feldman (Nov 15 2023 at 22:29):

I think ureq is synchronous only

view this post on Zulip Brendan Hansknecht (Nov 15 2023 at 22:33):

We only use it synchronously currently, but i guess that will change in the future? Actually, I don't think that will change for basic cli

view this post on Zulip Brendan Hansknecht (Nov 15 2023 at 22:33):

Otherwise, maybe attohttpc

view this post on Zulip Brendan Hansknecht (Nov 15 2023 at 22:37):

We also could try to user hyper directly. Not sure how low level it actually is.

view this post on Zulip Richard Feldman (Nov 15 2023 at 22:48):

I think we'll want to use async once we have Task.map2

view this post on Zulip Richard Feldman (Nov 15 2023 at 22:49):

basic-webserver uses hyper for receiving requests and it's totally fine

view this post on Zulip Richard Feldman (Nov 15 2023 at 22:49):

haven't tried it for making requests

view this post on Zulip Richard Feldman (Nov 15 2023 at 22:50):

but seems plausible since all we do is List U8 anyway!

view this post on Zulip Brendan Hansknecht (Nov 15 2023 at 22:52):

Ah, fair. Was thinking that basic CLI would always be single threaded, but it may be truly async with map2

view this post on Zulip Brendan Hansknecht (Nov 15 2023 at 22:55):

Also, I think the one called concern with hyper as an http client is that I don't think it deals with tls

view this post on Zulip Brendan Hansknecht (Nov 15 2023 at 22:56):

Oh wait, there is hyper-tls

view this post on Zulip Brendan Hansknecht (Nov 15 2023 at 22:57):

So yeah, looks simple enough to try hyper directly

view this post on Zulip Pearce Keesling (Nov 16 2023 at 13:42):

Are platform (in this case rust) features something that's on the table? For example if someone is making a cli that does not use networking they can save lots of binary size.

view this post on Zulip Agus Zubiaga (Nov 16 2023 at 16:47):

Maybe linking with —gc-sections is enough?

view this post on Zulip Agus Zubiaga (Nov 16 2023 at 16:48):

It’s still nice to have a small http lib for when you do use it, though

view this post on Zulip Brendan Hansknecht (Nov 17 2023 at 00:10):

So we totally could do something akin to rust features, but how Roc plans to distribute platforms, this is not really possible. In the Roc model, the entire platform is precompiled and distributed. So having some form of feature selection is not possible unless we either:

  1. Stop precompiling platforms
  2. Build a special system to enable opting into compiling a platform locally with certain features disabled
  3. Distribute 2^n binaries for each of the n features a platform has

view this post on Zulip Brendan Hansknecht (Nov 17 2023 at 00:16):

Also, I'm pretty sure gc-sections won't change anything. We have a reference to the http function and it references another 5MB of code. So nothing for GC sections to do.

view this post on Zulip Elias Mulhall (Nov 17 2023 at 00:23):

That is a pickle

Where does the effect interpreter live, is it implemented by hand per-platform?

view this post on Zulip Brendan Hansknecht (Nov 17 2023 at 00:25):

Yep. Or it will once we switch to that. Currently, it is technically all generated on the roc side and more adhoc, but that is changing

view this post on Zulip Notification Bot (Nov 17 2023 at 01:04):

23 messages were moved here from #contributing > contributor coordination meeting by Brendan Hansknecht.

view this post on Zulip Brendan Hansknecht (Nov 17 2023 at 01:09):

Just as a validation test, I made a basically empty rust binary (no roc involved) that uses reqwest to do a get request. That binary is 4.8MB.

view this post on Zulip Brendan Hansknecht (Nov 17 2023 at 01:10):

Oh, with lto, it drops to 3.0MB. That's a nice gain.

view this post on Zulip Luke Boswell (Nov 17 2023 at 01:19):

Are you still thinking about using hyper? Is that much smaller?

view this post on Zulip Brendan Hansknecht (Nov 17 2023 at 01:22):

about to test

view this post on Zulip Brendan Hansknecht (Nov 17 2023 at 01:23):

Though I don't expect it to be much smaller, reqwest is just a wrapper for hyper

view this post on Zulip Agus Zubiaga (Nov 17 2023 at 01:25):

Brendan Hansknecht said:

We have a reference to the http function and it references another 5MB of code.

Even when no Roc code calls the effect function?

view this post on Zulip Agus Zubiaga (Nov 17 2023 at 01:30):

I may have a bad understanding of how the platform and app are linked. I thought the platform just exposed C-like functions and roc would generate code that calls them directly. But I guess there’s some sort of switch on effect type that dispatches to the right function?

view this post on Zulip Brendan Hansknecht (Nov 17 2023 at 01:43):

But I guess there’s some sort of switch on effect type that dispatches to the right function?

Technically it isn't this yet, but it will be in the future. So I would just work under that assumption. Even without this all of the notes on precompilation apply here (plus surgical linking) and clean up is not a simple task.

view this post on Zulip Brendan Hansknecht (Nov 17 2023 at 01:44):

Are you still thinking about using hyper?

Initial tests with hyper seem promising (but I haven't wired up most of the features), I will try to update the platform as a whole.

view this post on Zulip Brendan Hansknecht (Nov 17 2023 at 22:58):

So removing reqwest and directly using hyper saved about 700KB.

Our hello world with basic-cli is now 3.0MB on my linux machine. Of that, I think 2.1MB comes from hyper, tokio, rusttls, etc to support http requests. The other 0.9MB is other libraries and rust code.

view this post on Zulip Brendan Hansknecht (Nov 17 2023 at 23:07):

general question, does basic cli need to support http2 for web requests? Given it is just directly requesting webpages and not doing anything with keep alive, I assume that 1 vs 2 shouldn't matter much?

But honestly I don't mess with web that much anymore, so not sure if I am missing something. Removing http2 save another 400KB.

view this post on Zulip Brendan Hansknecht (Nov 17 2023 at 23:49):

I am just gonna remove http2 for now. Can be added back in later if someone has an explicit need PR now up: https://github.com/roc-lang/basic-cli/pull/130

view this post on Zulip Luke Boswell (Nov 18 2023 at 00:08):

Makes sense, this is basic-cli right. That sounds like a good candidate for more-advanced-cli

view this post on Zulip Richard Feldman (Nov 23 2023 at 02:52):

hm, this made it into 0.6.0, right? I just saw https://www.reddit.com/r/ProgrammingLanguages/comments/17zp4m7/comment/ka5akck/ and tried it out locally on macOS; when I build helloWorld.roc (which is using 0.6.0 for its platform) I'm seeing:

$ du -h helloWorld
 23M    helloWorld

is it a lot smaller on Linux? :thinking:

view this post on Zulip Brendan Hansknecht (Nov 23 2023 at 04:19):

Would make sense for Linux to be smaller, when building a binary, rust and friends build something a lot slimmer than for an object file

view this post on Zulip Brendan Hansknecht (Nov 23 2023 at 04:28):

Also, have the size can be stripped away, probably debug info. Is basic cli release in debug instead of release for some reason?

view this post on Zulip Brendan Hansknecht (Nov 23 2023 at 04:32):

Yeah, pretty sure our basic cli package is a debug build and that is the issue.

view this post on Zulip Brendan Hansknecht (Nov 23 2023 at 04:32):

I just built from source with --optimize and it is 6.5MB on macos

view this post on Zulip Brendan Hansknecht (Nov 23 2023 at 04:32):

yep and debug is 23MB

view this post on Zulip Brendan Hansknecht (Nov 23 2023 at 04:33):

so we need to cut a new package release that is actually an optimized build. That is the root issue.

view this post on Zulip Brendan Hansknecht (Nov 23 2023 at 04:37):

As a note, this probably affects basic-webserver as well, so they probably both need to cut a new release that is an optimized build.

view this post on Zulip Luke Boswell (Nov 23 2023 at 04:38):

Nice pick up

view this post on Zulip Anton (Nov 24 2023 at 11:16):

Fixed in PR#6078

view this post on Zulip Richard Feldman (Nov 25 2023 at 00:53):

Brendan Hansknecht said:

I just built from source with --optimize and it is 6.5MB on macos

do you mean using cargo build --release on the basic-cli Rust host?

I tried adding --optimize to roc build on macOS and it didn't make a difference for me :thinking:

view this post on Zulip Brendan Hansknecht (Nov 25 2023 at 01:57):

roc build --optimize but on an example that will build basic-cli from source which will use --release. this hasn't made it to the url package yet

view this post on Zulip Brendan Hansknecht (Nov 25 2023 at 01:57):

Will require a new release with Anton's pr

view this post on Zulip Anton (Nov 25 2023 at 09:41):

I'll start building 0.6.2 after today's nightlies are up

view this post on Zulip Anton (Nov 25 2023 at 13:17):

Here it is.

view this post on Zulip Richard Feldman (Nov 26 2023 at 19:26):

I can't believe I didn't think of this until just now, but an obvious way to shrink the binary size here is for someone to implement http 1.1 in Roc

view this post on Zulip Richard Feldman (Nov 26 2023 at 19:26):

then basic-cli doesn't need any host libraries at all to do http, just tcp (which comes from the OS anyway)

view this post on Zulip Richard Feldman (Nov 26 2023 at 19:27):

and any http logic that isn't used by a given roc application will be dead code eliminated anyway!

view this post on Zulip Richard Feldman (Nov 26 2023 at 19:28):

http 1.1 is also ridiculously simple (http2 not so much)

view this post on Zulip Richard Feldman (Nov 26 2023 at 19:29):

I guess tls would also probably need to be in the host for now

view this post on Zulip Richard Feldman (Nov 26 2023 at 19:29):

but I'm not sure how big that is relative to all of hyper

view this post on Zulip Brian Carroll (Nov 26 2023 at 19:52):

I wrote a HTTP 1.1 parser in Roc and it's in the repo already. Could be something to build on.

https://github.com/roc-lang/roc/blob/main/examples/parser/Parser/Http.roc

view this post on Zulip Pearce Keesling (Nov 26 2023 at 20:12):

Is dynamic linking an option for something like tls? Or do platforms need to be totally static?

view this post on Zulip Richard Feldman (Nov 26 2023 at 20:28):

they don't need to be, but I think static is the best user experience for end users of the compiled program! :big_smile:

view this post on Zulip Brendan Hansknecht (Nov 26 2023 at 21:04):

I think about 1-2MB of the 5MB of extra size is from rustls. Most of the rest is from hyper and Tokio. If we build own on http on top of the current tcp I'm not sure exactly how much we will gain. Also, if we later switch to async tcp, that might readd a lot of the costs from Tokio.

view this post on Zulip Richard Feldman (Nov 26 2023 at 22:03):

interesting, good to know!

view this post on Zulip Luke Boswell (Nov 26 2023 at 22:54):

a little off topic, but I was reading about some of the developments with WASM runtimes, and it seems a lot of these primitives are being developed into these runtimes pretty quickly, so I don't think it will be long and I can imagine a Roc platform that is almost zero overhead and provides a lot of functionality. See interface proposals like wasm-http and wasi-filesystem. I'm keen to work on something like this, but maybe that is a Post-AoC thing.

view this post on Zulip Luke Boswell (Nov 26 2023 at 22:59):

I mean on the order of the next few years*


Last updated: Jul 06 2025 at 12:14 UTC