Skip to content

Too many ast visitor in ecma minifier #10470

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
bvanjoi opened this issue May 15, 2025 · 1 comment
Open

Too many ast visitor in ecma minifier #10470

bvanjoi opened this issue May 15, 2025 · 1 comment
Milestone

Comments

@bvanjoi
Copy link
Contributor

bvanjoi commented May 15, 2025

We can merge the unrelated visitors to improve performance.

@bvanjoi
Copy link
Contributor Author

bvanjoi commented May 16, 2025

I've observed that the current ecma_minifier implementation contains an excessive number of visitors, which introduces significant unnecessary overhead. My goal is to reduce this inefficiency.

There are two potential approaches:

  • ​Fundamental Solution: Create an IR that's both visitor-friendly and easily parallelizable. However, this would require substantial architectural changes that may not be immediately practical.
  • ​Incremental Improvement: Implement a more efficient visitor pattern similar to Webpack's hook system. For example, we currently have two rename operations:
struct LabelRenamer {}
impl VisitorMut for LabelRenamer {
    fn visit_label() {
        rename_label()
    }
}

struct PrivateRenamer {}
impl VisitorMut for PrivateRenamer {
   fn visit_private_ident() {
        rename_private_ident()
   }
}

fn rename() {
   node.visit_mut_with(LabelRenamer);
   node.visit_mut_with(PrivateRenamer);
//~^ It means we should traverses twice.
}

If we implement a hook-based approach, the minifier would only need to traverse the AST once. This single traversal could then trigger all necessary transformations through registered hooks:

struct WebpackHooksLikeVisitor {
    plugins: Vec<Box<dyn NodeMutablePlugin>>
}

impl WebpackHooksLikeVisitor {
   fn visit_private_ident() {
        self.plugins.run(private_ident_node)
   }
    fn visit_label() {
        self.plugins.run(label_node)
    }
}

struct LabelRenamer;
impl NodeMutablePlugin for LabelRenamer {
   fn visit_label() {
      rename_label();
      true // means continue visit
   }
}

struct PrivateRenamer;
impl NodeMutablePlugin for PrivateRename {
   fn visit_private_ident() {
        rename_private_ident()
        true // means continue visit
   }
}

fn rename() {
  let plugins = vec![Box(LabelRenamer), Box(PrivateRenamer)]
  let visitor = WebpackHooksLikeVisitor::new(root_node);
  visitor.visit_root_node();
}

@kdy1 kdy1 added this to the Planned milestone May 16, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants