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

Feature-gate to reduce binary size #66

Closed
arctic-hen7 opened this issue Oct 19, 2021 · 9 comments
Closed

Feature-gate to reduce binary size #66

arctic-hen7 opened this issue Oct 19, 2021 · 9 comments
Assignees
Labels
C-performance Category: performance D-hard Difficulty: hard P-high Priority: high S-in-design Status: in design

Comments

@arctic-hen7
Copy link
Member

Is your feature request related to a problem? Please describe.
Even with aggressive size optimizations, Perseus' binary sizes are still very large. This is barely an issue on non-mobile systems with a solid internet connection, and Perseus is still one of the fastest frameworks in the world (Wasm or JS), but this can be improved. Total blocking time on mobile is the particular issue that needs to be addressed here.

Describe the solution you'd like
Perseus should aggressively feature-gate as much as possible, particularly for systems like i18n or plugins, which aren't needed in simpler sites. The bottom line is: if an app isn't using a feature, it shouldn't be in their binary. Right now, the situation is practically the opposite of that.

Describe alternatives you've considered
More aggressive size optimizations, though these come with dangers at runtime, particularly if we force all panics to abort, because this can be problematic in a web browser, especially if the user tries to catch panics from Perseus (which shouldn't occur, but anything is possible).

Additional context
This will require significant refactoring of a number of critical parts of Perseus, and the introduction of a number of new feature flags before v0.3.0 goes stable, as this will be a significant breaking change for apps using i18n, plugins, or really any complex features. I am also considering potentially even feature-gating rendering strategies, as that would provide a significant performance boost.

Also note that the core perseus crate contains logic for both the server and the client, so this would be the largest point of feature-gating.

@arctic-hen7 arctic-hen7 added C-performance Category: performance D-hard Difficulty: hard P-high Priority: high S-in-design Status: in design labels Oct 19, 2021
@arctic-hen7 arctic-hen7 self-assigned this Oct 19, 2021
@lukechu10
Copy link
Contributor

Normally, most of the unused parts should be eliminated by dead code elimination. I would be somewhat surprised if feature gating features would actually improve binary size. Nevertheless, feature gating could still improve compile-times greatly so it's still worth it IMO.

@arctic-hen7
Copy link
Member Author

arctic-hen7 commented Oct 19, 2021

That would be really nice, but systems like i18n and the plugins system are unfortunately integrated into the codebase in such a way that they aren't dead code, even if they aren't used by the user. Another example is the plugins system, which runs whether any plugins were defined or not.

This is proven by the horrific increases in binary size I've seen in the basic example over time (which now weighs in at around 300-400kb). For a 'Hello World', that's waay too much.

arctic-hen7 added a commit that referenced this issue Oct 19, 2021
Note: there's still a size increase from the plugins system that'll be helped by #66.
@arctic-hen7
Copy link
Member Author

Okay, with beta 13's current status as including the plugin system without feature-gating, the Perseus Lighthouse score has regressed into red territory on total blocking time on mobile, so this definitely needs to happen sooner rather than later.

@arctic-hen7
Copy link
Member Author

arctic-hen7 commented Oct 23, 2021

Okay, I've done some analysis of the Perseus binary with twiggy, and that's showing me some very interesting stuff. Particularly, the following changes need to be made to reduce binary sizes:

  • Separate the client and server code, allowing size optimizations to only apply to one
  • Add the ability for plugins to only run at tinker-time (the tinker action should become separate from other actions)
  • Feature-gate i18n dependencies and translators so that fluent-bundle isn't brought in unless absolutely necessary (-50kb)
  • Refactor the templating systems to avoid server-side code spillage (e.g. a function from http has ended up in the client-side bundle)

@arctic-hen7
Copy link
Member Author

Okay, I've completed the optimizations I listed above, and that has led to the basic example's bundle size decreasing from 399kb to 328.3kb (without normal size optimizations), decreases that will likely be replicated even more aggressively in systems with large amounts of server-side code, and in systems that don't use i18n. Also, plugin authors can now set their plugins to only run at tinker-time, which means they won't be included in the client-side bundle!

I'm going to test this with the size optimizations plugin and on the website after deploying beta 14, and then this should be good to close!

@arctic-hen7
Copy link
Member Author

Okay, this is all working quite well (apart from #69), though tinker-only plugins don't seem to have quite the desired effects in that plugins still seem to leak into the final bundle, which is very interesting. For now then, I'll leave this open until I've figured that issue out.

@arctic-hen7
Copy link
Member Author

arctic-hen7 commented Oct 30, 2021

Just as a side note, these changes reduce the size of the website bundle by more than one third (without size optimizations!), and it still uses i18n. Down another 200kb with size optimizations to a final size of 488.8kb (was 1.5MB). Lighthouse scores are back to 100 on desktop and 90s for mobile! So, this has worked!

@arctic-hen7
Copy link
Member Author

Okay, I think I've solved the plugins issue by having a new function called .plugin_with_client_privilege() for plugins that have to run on the client, and I've learned a lot about Rust dead code elimination! I'll release beta 15 now and then close this issue if everything checks out with the size optimizations plugin!

@arctic-hen7
Copy link
Member Author

All issues with plugins are now fixed, and everything seems to be working with the website, so I'm happily closing this!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-performance Category: performance D-hard Difficulty: hard P-high Priority: high S-in-design Status: in design
Projects
None yet
Development

No branches or pull requests

2 participants