Skip to content

Commit

Permalink
perf(css/minifier): Remove redundant clone (#6579)
Browse files Browse the repository at this point in the history
  • Loading branch information
kdy1 committed Dec 6, 2022
1 parent a475f61 commit 70ac028
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 31 deletions.
18 changes: 17 additions & 1 deletion crates/swc_css_ast/src/base.rs
@@ -1,5 +1,5 @@
use is_macro::Is;
use swc_common::{ast_node, EqIgnoreSpan, Span};
use swc_common::{ast_node, util::take::Take, EqIgnoreSpan, Span};

use crate::{
AlphaValue, AtRule, CalcSum, CmykComponent, Color, ComplexSelector, DashedIdent, Delimiter,
Expand Down Expand Up @@ -46,6 +46,12 @@ pub enum QualifiedRulePrelude {
ListOfComponentValues(ListOfComponentValues),
}

impl Take for QualifiedRulePrelude {
fn dummy() -> Self {
Self::SelectorList(Take::dummy())
}
}

#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
pub enum StyleBlock {
Expand All @@ -67,6 +73,16 @@ pub struct SimpleBlock {
pub value: Vec<ComponentValue>,
}

impl Take for SimpleBlock {
fn dummy() -> Self {
Self {
span: Take::dummy(),
name: Take::dummy(),
value: Take::dummy(),
}
}
}

#[ast_node("Function")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct Function {
Expand Down
9 changes: 9 additions & 0 deletions crates/swc_css_ast/src/selector.rs
Expand Up @@ -12,6 +12,15 @@ pub struct SelectorList {
pub children: Vec<ComplexSelector>,
}

impl Take for SelectorList {
fn dummy() -> Self {
Self {
span: Take::dummy(),
children: Take::dummy(),
}
}
}

#[ast_node("SelectorList")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct ForgivingSelectorList {
Expand Down
17 changes: 16 additions & 1 deletion crates/swc_css_ast/src/token.rs
Expand Up @@ -6,7 +6,7 @@ use std::{
use is_macro::Is;
use serde::{Deserialize, Serialize};
use swc_atoms::{Atom, JsWord};
use swc_common::{ast_node, EqIgnoreSpan, Span};
use swc_common::{ast_node, util::take::Take, EqIgnoreSpan, Span};

#[ast_node("PreservedToken")]
#[derive(Eq, Hash, EqIgnoreSpan)]
Expand All @@ -15,6 +15,15 @@ pub struct TokenAndSpan {
pub token: Token,
}

impl Take for TokenAndSpan {
fn dummy() -> Self {
Self {
span: Take::dummy(),
token: Take::dummy(),
}
}
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Is, EqIgnoreSpan)]
#[cfg_attr(
feature = "rkyv",
Expand Down Expand Up @@ -147,6 +156,12 @@ pub enum Token {
RBrace,
}

impl Take for Token {
fn dummy() -> Self {
Self::Semi
}
}

#[allow(clippy::derive_hash_xor_eq)]
#[allow(clippy::transmute_float_to_int)]
impl Hash for Token {
Expand Down
63 changes: 35 additions & 28 deletions crates/swc_css_minifier/src/compressor/rules.rs
@@ -1,7 +1,9 @@
use std::mem::take;

use swc_atoms::{js_word, JsWord};
use swc_common::{collections::AHashMap, EqIgnoreSpan, Span, Spanned, SyntaxContext};
use swc_common::{
collections::AHashMap, util::take::Take, EqIgnoreSpan, Span, Spanned, SyntaxContext,
};
use swc_css_ast::*;
use swc_css_visit::{Visit, VisitMutWith, VisitWith};

Expand Down Expand Up @@ -144,10 +146,14 @@ impl Compressor {
}
}

fn merge_selector_list(&self, left: &SelectorList, right: &SelectorList) -> SelectorList {
let mut children = left.children.clone();
fn merge_selector_list(
&self,
left: &mut SelectorList,
right: &mut SelectorList,
) -> SelectorList {
let mut children = left.children.take();

children.extend(right.children.clone());
children.extend(right.children.take());

SelectorList {
span: Span::new(left.span_lo(), right.span_hi(), SyntaxContext::empty()),
Expand All @@ -157,23 +163,23 @@ impl Compressor {

fn merge_relative_selector_list(
&self,
left: &RelativeSelectorList,
right: &RelativeSelectorList,
left: &mut RelativeSelectorList,
right: &mut RelativeSelectorList,
) -> RelativeSelectorList {
let mut children = left.children.clone();
let mut children = left.children.take();

children.extend(right.children.clone());
children.extend(right.children.take());

RelativeSelectorList {
span: Span::new(left.span_lo(), right.span_hi(), SyntaxContext::empty()),
children,
}
}

fn merge_simple_block(&self, left: &SimpleBlock, right: &SimpleBlock) -> SimpleBlock {
let mut value = left.value.clone();
fn merge_simple_block(&self, left: &mut SimpleBlock, right: &mut SimpleBlock) -> SimpleBlock {
let mut value = left.value.take();

value.extend(right.value.clone());
value.extend(right.value.take());

SimpleBlock {
span: Span::new(left.span_lo(), right.span_hi(), SyntaxContext::empty()),
Expand Down Expand Up @@ -212,8 +218,8 @@ impl Compressor {

fn try_merge_qualified_rules(
&mut self,
left: &QualifiedRule,
right: &QualifiedRule,
left: &mut QualifiedRule,
right: &mut QualifiedRule,
) -> Option<QualifiedRule> {
if !self.can_merge_qualified_rules(left, right) {
return None;
Expand All @@ -222,7 +228,7 @@ impl Compressor {
// Merge when declarations are exactly equal
// e.g. h1 { color: red } h2 { color: red }
if left.block.eq_ignore_span(&right.block) {
match (&left.prelude, &right.prelude) {
match (&mut left.prelude, &mut right.prelude) {
(
QualifiedRulePrelude::SelectorList(prev_selector_list),
QualifiedRulePrelude::SelectorList(current_selector_list),
Expand All @@ -232,7 +238,7 @@ impl Compressor {
let mut qualified_rule = QualifiedRule {
span: Span::new(left.span_lo(), right.span_hi(), SyntaxContext::empty()),
prelude: QualifiedRulePrelude::SelectorList(selector_list),
block: left.block.clone(),
block: left.block.take(),
};

qualified_rule.visit_mut_children_with(self);
Expand All @@ -250,7 +256,7 @@ impl Compressor {
let mut qualified_rule = QualifiedRule {
span: Span::new(left.span_lo(), right.span_hi(), SyntaxContext::empty()),
prelude: QualifiedRulePrelude::RelativeSelectorList(relative_selector_list),
block: left.block.clone(),
block: left.block.take(),
};

qualified_rule.visit_mut_children_with(self);
Expand All @@ -264,10 +270,10 @@ impl Compressor {
// Merge when both selectors are exactly equal
// e.g. a { color: blue } a { font-weight: bold }
if left.prelude.eq_ignore_span(&right.prelude) {
let block = self.merge_simple_block(&left.block, &right.block);
let block = self.merge_simple_block(&mut left.block, &mut right.block);
let mut qualified_rule = QualifiedRule {
span: Span::new(left.span_lo(), right.span_hi(), SyntaxContext::empty()),
prelude: left.prelude.clone(),
prelude: left.prelude.take(),
block,
};

Expand Down Expand Up @@ -299,14 +305,14 @@ impl Compressor {
}
}

fn try_merge_at_rule(&mut self, left: &AtRule, right: &AtRule) -> Option<AtRule> {
fn try_merge_at_rule(&mut self, left: &mut AtRule, right: &mut AtRule) -> Option<AtRule> {
// Merge when both at-rule's prelude is exactly equal
// e.g.
// @media print { .color { color: red; } }
// @media print { .color { color: blue; } }
if left.prelude.eq_ignore_span(&right.prelude) {
if let Some(left_block) = &left.block {
if let Some(right_block) = &right.block {
if let Some(left_block) = &mut left.block {
if let Some(right_block) = &mut right.block {
let block = self.merge_simple_block(left_block, right_block);
let mut at_rule = AtRule {
span: Span::new(
Expand All @@ -315,7 +321,7 @@ impl Compressor {
SyntaxContext::empty(),
),
name: left.name.clone(),
prelude: left.prelude.clone(),
prelude: left.prelude.take(),
block: Some(block),
};

Expand Down Expand Up @@ -350,7 +356,7 @@ impl Compressor {
if self.is_mergeable_at_rule(at_rule)
&& matches!(prev_rule, Some(Rule::AtRule(_))) =>
{
if let Some(Rule::AtRule(box prev_rule)) = &prev_rule {
if let Some(Rule::AtRule(box prev_rule)) = &mut prev_rule {
if let Some(at_rule) = self.try_merge_at_rule(prev_rule, at_rule) {
*rule = Rule::AtRule(Box::new(at_rule));

Expand All @@ -363,7 +369,7 @@ impl Compressor {
Rule::QualifiedRule(box qualified_rule @ QualifiedRule { .. })
if matches!(prev_rule, Some(Rule::QualifiedRule(_))) =>
{
if let Some(Rule::QualifiedRule(box prev_rule)) = &prev_rule {
if let Some(Rule::QualifiedRule(box prev_rule)) = &mut prev_rule {
if let Some(qualified_rule) =
self.try_merge_qualified_rules(prev_rule, qualified_rule)
{
Expand Down Expand Up @@ -478,7 +484,8 @@ impl Compressor {
ComponentValue::Rule(box Rule::AtRule(box at_rule @ AtRule { .. }))
if prev_rule.is_some() && self.is_mergeable_at_rule(at_rule) =>
{
if let Some(ComponentValue::Rule(box Rule::AtRule(box prev_rule))) = &prev_rule
if let Some(ComponentValue::Rule(box Rule::AtRule(box prev_rule))) =
&mut prev_rule
{
if let Some(at_rule) = self.try_merge_at_rule(prev_rule, at_rule) {
*rule = ComponentValue::Rule(Box::new(Rule::AtRule(Box::new(at_rule))));
Expand All @@ -493,7 +500,7 @@ impl Compressor {
if prev_rule.is_some() && self.is_mergeable_at_rule(at_rule) =>
{
if let Some(ComponentValue::StyleBlock(box StyleBlock::AtRule(box prev_rule))) =
&prev_rule
&mut prev_rule
{
if let Some(at_rule) = self.try_merge_at_rule(prev_rule, at_rule) {
*rule = ComponentValue::StyleBlock(Box::new(StyleBlock::AtRule(
Expand All @@ -510,7 +517,7 @@ impl Compressor {
box qualified_rule @ QualifiedRule { .. },
)) if prev_rule.is_some() => {
if let Some(ComponentValue::Rule(box Rule::QualifiedRule(box prev_rule))) =
&prev_rule
&mut prev_rule
{
if let Some(qualified_rule) =
self.try_merge_qualified_rules(prev_rule, qualified_rule)
Expand All @@ -530,7 +537,7 @@ impl Compressor {
)) if prev_rule.is_some() => {
if let Some(ComponentValue::StyleBlock(box StyleBlock::QualifiedRule(
box prev_rule,
))) = &prev_rule
))) = &mut prev_rule
{
if let Some(qualified_rule) =
self.try_merge_qualified_rules(prev_rule, qualified_rule)
Expand Down
7 changes: 7 additions & 0 deletions crates/swc_css_parser/scripts/instruemnt/bench-lexer.sh
@@ -0,0 +1,7 @@
#!/usr/bin/env bash
set -eu

export RUST_LOG=off
export MIMALLOC_SHOW_STATS=1

cargo profile instruments --release -t time --features swc_common/concurrent --bench lexer -- --bench --color $@
2 changes: 1 addition & 1 deletion crates/swc_css_parser/scripts/instruemnt/bench-parser.sh
Expand Up @@ -4,4 +4,4 @@ set -eu
export RUST_LOG=off
export MIMALLOC_SHOW_STATS=1

cargo profile instruments --release -t time --features swc_common/concurrent --bench parser -- --bench --color
cargo profile instruments --release -t time --features swc_common/concurrent --bench parser -- --bench --color $@

1 comment on commit 70ac028

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmark

Benchmark suite Current: 70ac028 Previous: 8633d27 Ratio
es/full/bugs-1 351451 ns/iter (± 22878) 355955 ns/iter (± 23391) 0.99
es/full/minify/libraries/antd 2033011685 ns/iter (± 34953270) 2074256177 ns/iter (± 42312882) 0.98
es/full/minify/libraries/d3 472046996 ns/iter (± 21570279) 470748383 ns/iter (± 12776484) 1.00
es/full/minify/libraries/echarts 1739599899 ns/iter (± 20672664) 1668518668 ns/iter (± 25975328) 1.04
es/full/minify/libraries/jquery 120770254 ns/iter (± 3493320) 113988748 ns/iter (± 4757739) 1.06
es/full/minify/libraries/lodash 141444213 ns/iter (± 4791323) 137292553 ns/iter (± 4524299) 1.03
es/full/minify/libraries/moment 73592059 ns/iter (± 4144471) 66923243 ns/iter (± 5153896) 1.10
es/full/minify/libraries/react 23665527 ns/iter (± 1646141) 25186007 ns/iter (± 1112396) 0.94
es/full/minify/libraries/terser 366967071 ns/iter (± 6293616) 353103492 ns/iter (± 13037696) 1.04
es/full/minify/libraries/three 643151453 ns/iter (± 22734070) 644744601 ns/iter (± 17554761) 1.00
es/full/minify/libraries/typescript 3837846518 ns/iter (± 167052390) 3829266116 ns/iter (± 62621533) 1.00
es/full/minify/libraries/victory 938503653 ns/iter (± 52163361) 912006407 ns/iter (± 30388870) 1.03
es/full/minify/libraries/vue 197556572 ns/iter (± 9767530) 172806701 ns/iter (± 7097635) 1.14
es/full/codegen/es3 34428 ns/iter (± 1287) 34648 ns/iter (± 3653) 0.99
es/full/codegen/es5 34074 ns/iter (± 4675) 34707 ns/iter (± 4450) 0.98
es/full/codegen/es2015 34044 ns/iter (± 851) 35481 ns/iter (± 4222) 0.96
es/full/codegen/es2016 34138 ns/iter (± 1786) 34698 ns/iter (± 5155) 0.98
es/full/codegen/es2017 34167 ns/iter (± 3197) 34945 ns/iter (± 4089) 0.98
es/full/codegen/es2018 34367 ns/iter (± 2431) 35886 ns/iter (± 6685) 0.96
es/full/codegen/es2019 34647 ns/iter (± 3683) 34359 ns/iter (± 2987) 1.01
es/full/codegen/es2020 34629 ns/iter (± 2430) 35858 ns/iter (± 6349) 0.97
es/full/all/es3 220761121 ns/iter (± 23849680) 206414744 ns/iter (± 14046727) 1.07
es/full/all/es5 205212711 ns/iter (± 17687171) 189877395 ns/iter (± 17583766) 1.08
es/full/all/es2015 165493615 ns/iter (± 14742950) 150824523 ns/iter (± 7502891) 1.10
es/full/all/es2016 165807431 ns/iter (± 14765169) 163363948 ns/iter (± 16297666) 1.01
es/full/all/es2017 160548536 ns/iter (± 16179076) 156392441 ns/iter (± 12666257) 1.03
es/full/all/es2018 161154787 ns/iter (± 15008888) 151988067 ns/iter (± 10754135) 1.06
es/full/all/es2019 158910141 ns/iter (± 12307004) 146125605 ns/iter (± 7321473) 1.09
es/full/all/es2020 154555362 ns/iter (± 15091502) 141531282 ns/iter (± 5759423) 1.09
es/full/parser 744682 ns/iter (± 30584) 736734 ns/iter (± 89877) 1.01
es/full/base/fixer 26354 ns/iter (± 1552) 26595 ns/iter (± 1940) 0.99
es/full/base/resolver_and_hygiene 91927 ns/iter (± 4556) 93144 ns/iter (± 6704) 0.99
serialization of ast node 210 ns/iter (± 2) 215 ns/iter (± 21) 0.98
serialization of serde 223 ns/iter (± 3) 233 ns/iter (± 36) 0.96

This comment was automatically generated by workflow using github-action-benchmark.

Please sign in to comment.