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

Customers want guidance and docs for tree-shaking #33920

Open
Tracked by #5475
matanlurey opened this issue Jul 20, 2018 · 37 comments
Open
Tracked by #5475

Customers want guidance and docs for tree-shaking #33920

matanlurey opened this issue Jul 20, 2018 · 37 comments
Labels
area-web Use area-web for Dart web related issues, including the DDC and dart2js compilers and JS interop. customer-google3 P2 A bug or feature request we're likely to work on web-dart2js

Comments

@matanlurey
Copy link
Contributor

Despite tree-shaking being a prevalent feature/reason to use the language:

Dead code elimination in dynamic languages is a much harder problem than in static languages. The idea of a "treeshaker" originated in LISP2 in the 1990s. The idea is that all possible execution flows of a program can be represented as a tree of function calls, so that functions that are never called can be eliminated.

The algorithm was applied to JavaScript in Google Closure Tools and then to Dart in the dart2js compiler also written by Google, presented by Bob Nystrom in 2012 and described by the book "Dart in Action" by author Chris Buckett in 2013:

... it's not documented:

In fact the only references I can find anywhere to this feature is on the Dart2JS page:

Don’t worry about the size of your app’s included libraries. The dart2js tool performs tree shaking to omit unused classes, functions, methods, and so on. Just import the libraries you need, and let dart2js get rid of what you don’t need.

This has led customers to wild assumptions around what is and what is not tree-shakeable, and without any clear guidance to patterns that allow or disallow tree-shaking. For example internally, many large applications chose to store configurable metadata in a hash-map:

final _config = <String, Stuff>{};

class Stuff {
  void doStuff() {}
}
class FooStuff extends Stuff {}
class BarStuff extends Stuff {}

void main() {
  _config['foo'] = new FooStuff();
  _config['bar'] = new BarStuff();

  // ... elsewhere in the app ...
 config['foo'].doStuff();
}

... _config['bar'] isn't tree-shaken, nor is class BarStuff. Users did not believe this until I showed them (this issue is not about what should be tree-shaken or why or why not). I believe that tree-shaking is also a selling point for Dart on Flutter, but there is no documentation for Dart AOT either.

I'd personally like to see:

  • A page describing what tree-shaking is
  • A page of examples of stuff being tree-shaken, with explanations why
  • A page of best practices, perhaps separate for the VM and Dart2JS if necessary

@hterkelsen at one point wrote this: https://hterkelsen.github.io/dart2js_playground/

It could be a nice start.

@matanlurey matanlurey changed the title Customers want a "best practices" guide for tree-shaking Customers want guidance and docs for tree-shaking Jul 20, 2018
@matanlurey
Copy link
Contributor Author

matanlurey commented Jul 20, 2018

Another starting point might be looking at what the Closure Compiler documents:

@kevmoo
Copy link
Member

kevmoo commented Jul 20, 2018

CC @kwalrath

@matanlurey
Copy link
Contributor Author

matanlurey commented Jul 20, 2018

To be clear, I don't know if its possible for @kwalrath to write anything (other than a brief introduction) without the implementation teams. I'm happy to open meta issues for Dart2JS team and Dart AOT team too.

@lexaknyazev
Copy link
Contributor

Possible option to get some insights about dart2js tree-shaking is to use Dump-Info Visualizer:

  1. Run dart2js on some sources with --dump-info.
  2. Drop its result into https://dart-lang.github.io/dump-info-visualizer/

@matanlurey
Copy link
Contributor Author

That is not a realistic documentation medium for the majority of folks.

@matanlurey matanlurey added the P2 A bug or feature request we're likely to work on label Aug 27, 2018
@matanlurey
Copy link
Contributor Author

An external S/O related to tree-shaking for AoT (Flutter):
https://stackoverflow.com/questions/52822353/how-to-test-debug-tree-shaking-in-flutter

/cc @a-siva @mraleph

@rrousselGit
Copy link

I made that S/O question (+ partial answer)

I think it would be important to be able to test tree shaking.
With flutter it is relatively easy to include Cupertino widgets on an Android app by inadvertance.

@mraleph
Copy link
Member

mraleph commented Oct 16, 2018

We are looking to build tools that would allow you to inspect what is included into the resulting snapshot. The bug to track is #34632

There is already a rudimentary tooling for that (--print-instructions-sizes-to), but nothing that is nicely packaged for consumption.

/cc @sjindel-google

@matanlurey
Copy link
Contributor Author

@mraleph I think having tools is awesome, but this request is around docs. Most users will not want to write N-versions of their code, run analysis tools, and figure out when tree-shaking is applied or not. There needs to be some common sense rules/docs for most users.

@mraleph
Copy link
Member

mraleph commented Oct 16, 2018

@matanlurey it is very hard to write a good doc because results of the tree shaking highly depend on optimizations and describing those would be hard.

@matanlurey
Copy link
Contributor Author

@mraleph: How hard? I understand that it's practically speaking not possible to write a specification for dead code elimination - but I think a simple FAQ would go a long way. For example, knowing that certain constant booleans will tree-shake, that complex data structures (like lists or maps) will not, etc.

@matanlurey
Copy link
Contributor Author

I just think its silly to say "we provide awesome dead code elimination" and then offer no samples or guidance around when it applies.

@JeromePuttemans
Copy link

JeromePuttemans commented Mar 29, 2019

Hello,

Why not begin with some basic examples ?

Here is a little contribution with some experimental tests trying to understand tree-shaking.

Do you have other interesting tips/explanations to force tree-shaking ?

@rockingdice
Copy link

I was lead to this issue from my S/O question:
https://stackoverflow.com/questions/56306140/will-the-dart-codes-for-ios-be-removed-when-compiling-for-android
I'm still expecting an answer but seems it's not easy to answer just Yes or No.
My understanding from all the posts above would be it depends on the logic I write for different platforms.
Is there any solution to test the tree-shaking logic by now?

I think even the optimization is complicated, it's still logical and there must be some principles or directions to follow, like avoid to do something or manage to do something for tree-shaking codes.

But eventually, we have to make sure it's working as expected.

@rrousselGit
Copy link

There's currently no way to have an if/else depend on the platform target and still be code tree-shaked.

The only solution for tree shaking to eliminate iOS code on Android is to use different main.dart (using flutter build -t lib/my_main.dart) combined with a factory+singleton pattern. But that's not something trivial.

@rockingdice
Copy link

There's currently no way to have an if/else depend on the platform target and still be code tree-shaked.

The only solution for tree shaking to eliminate iOS code on Android is to use different main.dart (using flutter build -t lib/my_main.dart) combined with a factory+singleton pattern. But that's not something trivial.

Thank you for your answer.
I think it's convincing and I'll think another way to work around it. Like using channels to make native libs for different platforms.
Do you have a way to test this case? I tried your method from your question using Observation but don't know how to check within the code level.

@yoxel
Copy link

yoxel commented Jul 4, 2019

We just noticed that dart2js removes some getters that are used in our code and our Angular app gets MethodNotFound/not a function in runtime :( We have to run with -O0 now to make the app work. Any suggestions on how to understand the reason for dropping the live code? Thanks

@yoxel
Copy link

yoxel commented Jul 5, 2019

I have a feeling v2.4.0 broke this for us. Now, I am thinking dart2js has a bug in tree shaking, removing live code that the previous verion was not removing. Where should I file a bug on this. I can't imagine how we'd provide a reproducible testcase.

@mraleph
Copy link
Member

mraleph commented Jul 10, 2019

@yoxel if your code is failing because dart2js is dropping some live methods then this would be a bug. please file a separate issue for it.

@vsmenon vsmenon added the area-web Use area-web for Dart web related issues, including the DDC and dart2js compilers and JS interop. label Jul 20, 2019
@corymalcolmtaylor
Copy link

I am trying to squish a bug that exists in release mode but not it debug mode and was wondering if tree shaking might be part of the problem. Is there a way to turn off tree shaking when using the 'Flutter build web' command? I can supply the code sample if you wish. See here:
flutter/flutter#54026

@fzyzcjy
Copy link
Contributor

fzyzcjy commented Sep 7, 2020

Hi 2 years has passed - any updates? Thanks

@mraleph
Copy link
Member

mraleph commented Sep 8, 2020

@fzyzcjy are you asking from Web perspective (the issue has been labeled as mostly targeting Web) or Native perspective?

For native we now have package:vm_snapshot_analysis for analysing resulting binary size which gives you some insight into what got pulled into the resulting AOT snapshot. This information is also being exposed in Flutter Dev Tools.

@fzyzcjy
Copy link
Contributor

fzyzcjy commented Sep 8, 2020

@mraleph Wow I did not know that before! I will have a look at it! (I am asking the native)

@mraleph
Copy link
Member

mraleph commented Sep 8, 2020

@fzyzcjy fwiw I can't find any public documentation for the Code Size analysis views in Flutter Dev Tools (maybe because it is still being developed - or maybe I am looking in the wrong place. @kenzieschmoll might know where to look).

@fzyzcjy
Copy link
Contributor

fzyzcjy commented Sep 8, 2020

@mraleph I did a search and also did not find it. But the package looks promising!

@kenzieschmoll
Copy link
Contributor

Docs for the DevTools code size tool are here: https://flutter.dev/docs/development/tools/devtools/code-size

@lohanbodevan
Copy link

Hey @kenzieschmoll, thanks for sharing the docs.
Is it already available on Flutter 1.20.3? I'm trying to use it but I'm getting Could not find an option named "analyze-size".
I couldn't find anything about it on flutter build apk --help. Am I doing something wrong?

@kenzieschmoll
Copy link
Contributor

You need to be on 1.22.0-9.0.pre or greater, which should currently be on the dev branch

@fzyzcjy
Copy link
Contributor

fzyzcjy commented Sep 12, 2020

A related question: I write some native code (c++) and use dart:ffi to bind to Flutter. However, with only several functions it is 1.8MB size. Thus, I wonder some tools which is similar to vm_snapshot_analysis and can help me dig out which class/method/... takes space?

Thanks very much!

@mraleph
Copy link
Member

mraleph commented Sep 12, 2020

@fzyzcjy you can use https://github.com/google/bloaty for C++ code, alternatively there is also a tool in Dart SDK sources (https://github.com/dart-lang/sdk/blob/master/runtime/third_party/binary_size/src/run_binary_size_analysis.py) which you could try to use.

@fzyzcjy
Copy link
Contributor

fzyzcjy commented Sep 12, 2020

@mraleph Thanks very much! However, I have tried using bloaty, but it says most of the size is for TEXT region though I give it debug symbols... The issue: google/bloaty#213

@xuan-nguyen-swe
Copy link

xuan-nguyen-swe commented Jan 6, 2021

Beside of testing tree-shaking manually with devtools, is there an official doc to confirm how dart and flutter optimize code in general with tree shaking on android/iOS or not?

In this flutter doc, it doesn't say that tree shaking will be used for android/iOS.

Flutter will only do tree shaking when build for web: "The build is minified and tree shaking has been performed."

For non-web builds: "Compilation is optimized for fast startup, fast execution, and small package sizes." => does it mean with or without tree shaking? How does it actually optimize for android/iOS and other platform? Can some one confirm with deeper information on this?

@adnanjpg
Copy link

adnanjpg commented Jun 6, 2021

It's been 3 years, is there any update? thanks.

@cedvdb
Copy link

cedvdb commented Jun 8, 2021

It would be nice to have some information and rough guidelines indeed. Why can't maps and list be tree shaken ?

@dungnv2602
Copy link

In Flutter Web release mode, there is no doubt that dart2js supports tree-shaking in as it was mentioned here & here.

According to this post, I can 'safely' say that Flutter Engine supports tree-shaking in code & assets in Profile or Release mode.

It would be great if anyone from Flutter Team can verify this.

@venkatd
Copy link

venkatd commented May 18, 2022

What would be involved for us to get a command line tool that, similar to a code coverage tool, would tell us which lines of code are and aren't included in a final build?

Even if we don't have any specific guidance, I have no idea whether some piece of code made it into the final build.

@harryterkelsen
Copy link
Contributor

There is this (possibly outdated) tool which shows all of the code which made it into the compiled app: https://github.com/dart-lang/dump-info-visualizer

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-web Use area-web for Dart web related issues, including the DDC and dart2js compilers and JS interop. customer-google3 P2 A bug or feature request we're likely to work on web-dart2js
Projects
None yet
Development

No branches or pull requests