Skip to content

Async websocket creates a large binary & object file #2013

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

Open
amnuwan opened this issue Jul 11, 2020 · 26 comments
Open

Async websocket creates a large binary & object file #2013

amnuwan opened this issue Jul 11, 2020 · 26 comments
Assignees

Comments

@amnuwan
Copy link

amnuwan commented Jul 11, 2020

Version of Boost 1.70 ( 1.73 too )

Steps necessary to reproduce the problem

Build sample async ssl websocket example

https://www.boost.org/doc/libs/1_70_0/libs/beast/example/websocket/client/async-ssl/websocket_client_async_ssl.cpp

On Mac OS with clang,
This will produce a release binary 6.3 MB. This is not due to OpenSSL. You will see that object file ( websocket_client_async_ssl.o ) is also 3.8 MB.

And following statement contributes to shocking 3.1 MB of it.

// Perform the websocket handshake
ws_.async_handshake(host_, "/",
beast::bind_front_handler(
&session::on_handshake,
shared_from_this()));

while sync version of same ( ws_.handshake ), contributes only 400 KB extra.

File size changes as below.

  1. Async ws-handshake - ( obj: 3.8 MB, exe: 6.3 MB )
  2. No ws-handshake - ( obj: 0.5 MB, exe: 2.9 MB )
  3. Sync ws-handshake - ( obj: 0.9 MB, exe: 3.2 MB )

SSL present in all of above case.

I checked some cases with latest boost version 1.73 also, no noticeable change in reduction. Probably it takes more.

@madmongo1
Copy link
Collaborator

madmongo1 commented Jul 11, 2020 via email

@amnuwan
Copy link
Author

amnuwan commented Jul 11, 2020

Debug build or release? If release build, did you strip debugging symbols?

Release build.

Stripping ( compiling with option -S ) increases object file further : from 3.8 MB to 23 MB
Anyway I'm not able to link after stripping.

No luck with striping for me but better if we can find the reason for this bloat specially in async mode.

Further with respect to striping, additional symbols can help to debug a crash I suppose, which could be the reason they are in a release build, right ?

@djarek
Copy link
Contributor

djarek commented Jul 11, 2020

@amnuwan That's the wrong flag, -S does the following:

Stop after the stage of compilation proper; do not assemble. The output is in the form of an assembler code file for each non-assembler input file specified.

The flag for stripping is -s.

As for the bloat- it's most likely related to how the async functions of websocket stream cause multiple instantiations of the async algorithms of the underlying stream, because multiple buffer types are passed.

@amnuwan
Copy link
Author

amnuwan commented Jul 12, 2020

@djarek thanks, I'll check about the option, I know striping can reduce the size a little, but if it has a cost to crash error reporting, I don't preffer that.

single statement cause 3.1 MB size increase, making beast is a difficult option for a mobile or embeded library overall. I'm developing a communication library, can't sacrifice around 5 MB of size just for websocket connectivity.

@djarek Mentioned template instantiation, how many templates would it require increase the size to this level by a single line of code. If this is unavoidable, then something is not right with the design of asio/beast. It lead us to consider, beast as a heavy library to perform websocket connectivity.

@djarek
Copy link
Contributor

djarek commented Jul 13, 2020

Some things that may help:

  • don't use polymorphic executor (the default) on I/O objects, prefer the exact type (usually io_context::executor_type)
  • try to use the same buffer type in all async calls
  • if you're not using the timeouts/rate limiting features of beast::tcp_stream , don't use it, use a socket type from ASIO instead
  • enable LTO (not really related to beast, but in general), which enables more optimization opportunities
  • make sure you optimize for size (-Os), if size is important.

@stale
Copy link

stale bot commented Aug 16, 2020

This issue has been open for a while with no activity, has it been resolved?

@stale stale bot added the Stale No recent activity label Aug 16, 2020
@amnuwan
Copy link
Author

amnuwan commented Aug 16, 2020 via email

@stale stale bot removed the Stale No recent activity label Aug 16, 2020
@madmongo1
Copy link
Collaborator

Ok, I’ve been off work for a few days. I’ll tackle this on Monday.

Thanks for your patience.

@amnuwan
Copy link
Author

amnuwan commented Aug 23, 2020 via email

@madmongo1
Copy link
Collaborator

Yes, we've been in discussion on how we can reduce template type expansions for internal completion handlers with little impact on performance.

We have a plan, and work is under way.

@amnuwan
Copy link
Author

amnuwan commented Aug 24, 2020

Nice, so I will continue to use beast for mobile assuming size will be reduced in the recent future.

Below library generate a really small binary I was thinking use it if beast couldn't fix this.

https://machinezone.github.io/IXWebSocket/

Thanks !

@madmongo1
Copy link
Collaborator

great. we're on it.

@stale
Copy link

stale bot commented Oct 4, 2020

This issue has been open for a while with no activity, has it been resolved?

@stale stale bot added the Stale No recent activity label Oct 4, 2020
@stale
Copy link

stale bot commented Oct 12, 2020

It looks like this issue has either been abandoned or resolved so I will go ahead and close it. Feel free to re-open this issue if you feel it needs attention, or open new issues as needed. Thanks!

@stale stale bot closed this as completed Oct 12, 2020
@madmongo1 madmongo1 reopened this Oct 12, 2020
@stale stale bot removed the Stale No recent activity label Oct 12, 2020
@madmongo1 madmongo1 added this to the Backlog milestone Oct 12, 2020
@amnuwan
Copy link
Author

amnuwan commented Oct 13, 2020

Can this take some time to be resolved ? Like 2-4 months ?

@madmongo1
Copy link
Collaborator

It can, depending on what else is distracting the maintainer :)

PRs are always welcome if you'd like to help move the process along.

@stale
Copy link

stale bot commented Nov 16, 2020

This issue has been open for a while with no activity, has it been resolved?

@stale stale bot added the Stale No recent activity label Nov 16, 2020
@stale
Copy link

stale bot commented Dec 25, 2020

It looks like this issue has either been abandoned or resolved so I will go ahead and close it. Feel free to re-open this issue if you feel it needs attention, or open new issues as needed. Thanks!

@stale stale bot closed this as completed Dec 25, 2020
@madmongo1 madmongo1 self-assigned this Dec 25, 2020
@madmongo1 madmongo1 added Optimization and removed Stale No recent activity labels Dec 25, 2020
@madmongo1 madmongo1 reopened this Dec 25, 2020
@amnuwan
Copy link
Author

amnuwan commented Aug 29, 2021

As a mitigation, following things helped

-fvisibility=hidden -Os -flto=full
-Wl,--gc-sections,--as-needed
Also striping

In my project, overall I was able to obtain .so file of size 3.1 MB ( Around 2 MB goes to beast ).

Object file correspond to beast connection with above line is still 4.3 MB. It's a small 350 lines class which has nothing else but beast websocket connection with SSL.

This problem is severe only when it comes to android mobile applications. It will be really helpful for others if we put some warning at main page. Like below,

Warning : Websocket code with SSL contributes to additional ~1-2 MB release binary size when compiled as ".so" library.

@dfranusic
Copy link

I am using Boost.Beast to implement a Websocket SSL server on a range of embedded devices. Although "losing" around two megabytes of free space is not a big issue, it would be great if the resulting binary (or object file) could be trimmed down a bit.

@ashtum ashtum removed this from the Backlog milestone Jun 6, 2024
@pfeatherstone
Copy link

I've noticed massive binary sizes too. I'm also using Boost.Json for parsing/writing HTTP requests/response. A very simple HTTP + Websocket over SSL application with some JSON parsing results in a 7MB binary with everything statically linked. It's massive. I'm also putting this on an embedded device but i can get away with it. I've noticed this a lot with Boost libraries. The compile times and binary sizes are massive. Fantastic libraries but what is it about Boost and bloated bins.

@ashtum
Copy link
Collaborator

ashtum commented Oct 14, 2024

I've noticed massive binary sizes too. I'm also using Boost.Json for parsing/writing HTTP requests/response. A very simple HTTP + Websocket over SSL application with some JSON parsing results in a 7MB binary with everything statically linked. It's massive. I'm also putting this on an embedded device but i can get away with it. I've noticed this a lot with Boost libraries. The compile times and binary sizes are massive. Fantastic libraries but what is it about Boost and bloated bins.

Are you sure you're building in release mode? Based on what you've explained, a binary size of 1 to 2 MB is expected.

@pfeatherstone
Copy link

pfeatherstone commented Oct 14, 2024

I'm building with -O3 -ffast-math -s.
In debug mode, I get a binary of size 47MB.
I've also got a CLI using Boost.program_options. I forgot to mention that. But how much is that adding?

@ashtum
Copy link
Collaborator

ashtum commented Oct 14, 2024

Unfortunately, there isn’t much you can do about it. Both Asio and Beast are heavily templated, and even small changes to message types result in the re-instantiation of containers and operations. If you have many message types, you might want to give http::message_generator a try, but I don't expect it to make a huge difference.

@pfeatherstone
Copy link

OK, I guess that's the nature of heavily templated libraries. There is no such thing as a zero-cost abstraction.

@amnuwan
Copy link
Author

amnuwan commented Oct 15, 2024 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants