{"action":"created","issue":{"url":"https://api.github.com/repos/babel/babel/issues/1486","labels_url":"https://api.github.com/repos/babel/babel/issues/1486/labels{/name}","comments_url":"https://api.github.com/repos/babel/babel/issues/1486/comments","events_url":"https://api.github.com/repos/babel/babel/issues/1486/events","html_url":"https://github.com/babel/babel/issues/1486","id":74541975,"number":1486,"title":"Speeeeed","user":{"login":"sebmck","id":853712,"avatar_url":"https://avatars.githubusercontent.com/u/853712?v=3","gravatar_id":"","url":"https://api.github.com/users/sebmck","html_url":"https://github.com/sebmck","followers_url":"https://api.github.com/users/sebmck/followers","following_url":"https://api.github.com/users/sebmck/following{/other_user}","gists_url":"https://api.github.com/users/sebmck/gists{/gist_id}","starred_url":"https://api.github.com/users/sebmck/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sebmck/subscriptions","organizations_url":"https://api.github.com/users/sebmck/orgs","repos_url":"https://api.github.com/users/sebmck/repos","events_url":"https://api.github.com/users/sebmck/events{/privacy}","received_events_url":"https://api.github.com/users/sebmck/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/babel/babel/labels/discussion","name":"discussion","color":"bfe5bf"},{"url":"https://api.github.com/repos/babel/babel/labels/generation","name":"generation","color":"eb6420"},{"url":"https://api.github.com/repos/babel/babel/labels/help%20wanted","name":"help wanted","color":"159818"},{"url":"https://api.github.com/repos/babel/babel/labels/optimisation","name":"optimisation","color":"006b75"},{"url":"https://api.github.com/repos/babel/babel/labels/refactor","name":"refactor","color":"bfd4f2"},{"url":"https://api.github.com/repos/babel/babel/labels/transformation","name":"transformation","color":"009800"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":35,"created_at":"2015-05-09T00:34:28Z","updated_at":"2015-07-04T14:19:42Z","closed_at":null,"body":"Babel could be **much** faster! Here are some possible areas to look into:\r\n\r\n**Check list:**\r\n\r\n - [ ] Code generator\r\n - [ ] Grouping more transformers\r\n - [ ] Optimising existing transformers\r\n   - [x] `es6.tailCall`\r\n   - [ ] `es6.blockScoping`\r\n   - [ ] `es6.objectSuper`\r\n   - [ ] `es6.classes`\r\n   - [x] `es6.constants`\r\n   - [x] `_shadowFunctions`\r\n - [x] Optimising scope tracking\r\n - [ ] Attach comments in parser\r\n - [x] Include comments in token stream\r\n - [x] Address regenerator concerns\r\n\r\n## Code generator\r\n\r\nWhile this isn't a massive issue, and usually doesn't impact most projects, the code generators performance is pretty poor on large outputs. This is partly due to the copious amounts of lookbehinds and  attempts to make the code as \"pretty\" as possible. There is a lot of room for improvement and this is an area where micro-optimisations pay off at a huge scale. Relevant folder is [here](https://github.com/babel/babel/tree/master/src/babel/generation).\r\n\r\n## Grouping more transformers\r\n\r\n#1472 bought the ability to merge multiple transformers into the same AST traversal. This impacts the way internal transformers are written but after a bit of getting used to I think I actually prefer this way. Regardless, transformers are now split into 6 groups. The internal transformers can be viewed [here](https://github.com/babel/babel/blob/master/src/babel/transformation/transformers/index.js).\r\n\r\nReducing these groups may be complicated due to the various concerns that each one may have. ie. `es3.memberExpressionLiterals` needs to be ran on the entire tree, it needs to visit every single `MemberExpression` even if they've been modified or dynamically inserted.\r\n\r\n## Optimising existing transformers\r\n\r\nSome transformers spawn \"subtraversals\". This is problematic as this negates the intention of minimising traversals signifcantly. For example, previously the `es6.constants` transformer would visit every single node that has it's \"own\" scope. It then spawns another \"subtraversal\" that checks all the child nodes for reassignments. This means that there are **a lot** of unnecessary visiting. Instead, with a75af0a5d20bdba5b93e3bba10529f0bd982810a, the transformer traversal is used and a scope binding lookup is done.\r\n\r\nThis technique (not that ingenius since the previous way was crap) could be used on the [`es6.blockScoping`](https://github.com/babel/babel/blob/master/src/babel/transformation/transformers/es6/block-scoping.js) and [`_shadowFunctions`](https://github.com/babel/babel/blob/master/src/babel/transformation/transformers/internal/shadow-functions.js) (this does the arrow function `this` and `arguments` aliasing) transformers.\r\n\r\n## Optimising scope tracking\r\n\r\nSimilar to optimising existing transformers, the current [scope tracking](https://github.com/babel/babel/blob/master/src/babel/traversal/scope.js) does multiple passes and has room for optimisation. This could all be done in a single pass and then when hitting a binding it could look up the tree for the current scope to attach itself to.\r\n\r\n## Attach comments in parser\r\n\r\nCurrently [`estraverse`](https://github.com/babel/babel/blob/b8b70f2f4acd0ed3772b93a87df3b47584a3992a/src/babel/helpers/parse.js#L31) is used to attach comments. This isn't great, it means that an entire traversal is required in order to attach comments. This can be moved to the parser, similar to [espree](https://github.com/eslint/espree) that's used in ESLint.\r\n\r\n## Include comments in token stream\r\n\r\nCurrently tokens and comments are [concatenated together and sorted](https://github.com/babel/babel/blob/b8b70f2f4acd0ed3772b93a87df3b47584a3992a/src/babel/generation/whitespace.js#L25). This is so newlines can be retained between nodes. This is relatively inefficient since you're sorting a large array of possibly millions of elements.\r\n\r\n## Address regenerator\r\n\r\nRegenerator uses `ast-types`, this means it has it's own set of scope tracking and traversal logic. It's slower than Babel's and is actually relatively heavy, especially on large node trees. There has been a lot of controversy about merging it into Babel and iterating on it from there. Nonetheless, it's a soloution that needs to be considered if all other avenues are unavailable.\r\n\r\n---\r\n\r\nI welcome contributions of any kind so any help is extremely appreciated!\r\n\r\ncc @amasad @DmitrySoshnikov @gaearon @stefanpenner @babel/contributors "},"comment":{"url":"https://api.github.com/repos/babel/babel/issues/comments/118515544","html_url":"https://github.com/babel/babel/issues/1486#issuecomment-118515544","issue_url":"https://api.github.com/repos/babel/babel/issues/1486","id":118515544,"user":{"login":"RReverser","id":557590,"avatar_url":"https://avatars.githubusercontent.com/u/557590?v=3","gravatar_id":"","url":"https://api.github.com/users/RReverser","html_url":"https://github.com/RReverser","followers_url":"https://api.github.com/users/RReverser/followers","following_url":"https://api.github.com/users/RReverser/following{/other_user}","gists_url":"https://api.github.com/users/RReverser/gists{/gist_id}","starred_url":"https://api.github.com/users/RReverser/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/RReverser/subscriptions","organizations_url":"https://api.github.com/users/RReverser/orgs","repos_url":"https://api.github.com/users/RReverser/repos","events_url":"https://api.github.com/users/RReverser/events{/privacy}","received_events_url":"https://api.github.com/users/RReverser/received_events","type":"User","site_admin":false},"created_at":"2015-07-04T14:19:41Z","updated_at":"2015-07-04T14:19:41Z","body":"I tried to play with parsing performance for big codebases, and while could improve it by ~25%, the actual difference in seconds is pretty low so not sure whether it will affect the overall result. https://twitter.com/RReverser/status/617334262086410240"}}