From 47908a49d3d773b7ffacf6ffa6e38c7e091101cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Donny/=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Mon, 28 Nov 2022 16:51:36 +0900 Subject: [PATCH] perf(common): Fix perf bug of sourcemap for inputs with multi-byte chars (#6523) **Description:** This PR makes the source map generator cache the previous position instead of searching it from 0 every time. **Related issue:** - Closes https://github.com/swc-project/swc/issues/6411. --- crates/swc/benches/minify.rs | 7 +++--- crates/swc/scripts/instrument.sh | 4 +++- crates/swc_common/src/lib.rs | 1 - crates/swc_common/src/source_map.rs | 37 +++++++++++++++++++++++++---- 4 files changed, 39 insertions(+), 10 deletions(-) diff --git a/crates/swc/benches/minify.rs b/crates/swc/benches/minify.rs index a54436d1ac1f..3e8328bb67a1 100644 --- a/crates/swc/benches/minify.rs +++ b/crates/swc/benches/minify.rs @@ -46,7 +46,7 @@ fn bench_minify(b: &mut Bencher, filename: &str) { module: Default::default(), safari10: Default::default(), toplevel: true, - source_map: Default::default(), + source_map: BoolOrDataConfig::from_bool(true), output_path: Default::default(), inline_sources_content: true, emit_source_map_columns: true, @@ -56,9 +56,9 @@ fn bench_minify(b: &mut Bencher, filename: &str) { }) .unwrap(); - let res = black_box(res); + black_box(res); - assert_eq!(res.map, None); + // assert_eq!(res.map, None); }) } @@ -84,6 +84,7 @@ fn files_group(c: &mut Criterion) { bench_file("typescript"); bench_file("victory"); bench_file("vue"); + // bench_file("large"); } criterion_group!(benches, files_group); diff --git a/crates/swc/scripts/instrument.sh b/crates/swc/scripts/instrument.sh index 984163d6d17f..d7aeb93b8789 100755 --- a/crates/swc/scripts/instrument.sh +++ b/crates/swc/scripts/instrument.sh @@ -1,5 +1,7 @@ #!/usr/bin/env bash set -eu -cargo profile instruments --release -t time --bench typescript --features tracing/release_max_level_info -- --bench $@ +export RUST_LOG=off + +cargo profile instruments --release -t time --bench minify --features tracing/release_max_level_info -- --bench $@ # MINIFY=1 cargo profile instruments --release -t time --bench typescript --features concurrent,tracing/release_max_level_info $@ \ No newline at end of file diff --git a/crates/swc_common/src/lib.rs b/crates/swc_common/src/lib.rs index a5e9f52d44eb..65e69bd94919 100644 --- a/crates/swc_common/src/lib.rs +++ b/crates/swc_common/src/lib.rs @@ -32,7 +32,6 @@ //! //! Use `fxhash` instead of `ahash` for `AHashMap` and `AHashSet`. #![deny(clippy::all)] -#![deny(unused)] #![cfg_attr(docsrs, feature(doc_cfg))] use std::fmt::Debug; diff --git a/crates/swc_common/src/source_map.rs b/crates/swc_common/src/source_map.rs index 9162045fa48c..8dc3a62c6b7b 100644 --- a/crates/swc_common/src/source_map.rs +++ b/crates/swc_common/src/source_map.rs @@ -954,7 +954,7 @@ impl SourceMap { } fn bytepos_to_file_charpos_with(&self, map: &SourceFile, bpos: BytePos) -> CharPos { - let total_extra_bytes = self.calc_extra_bytes(map, &mut 0, bpos); + let total_extra_bytes = self.calc_extra_bytes(map, &mut 0, &mut 0, bpos); assert!( map.start_pos.to_u32() + total_extra_bytes <= bpos.to_u32(), "map.start_pos = {:?}; total_extra_bytes = {}; bpos = {:?}", @@ -966,9 +966,15 @@ impl SourceMap { } /// Converts an absolute BytePos to a CharPos relative to the source_file. - fn calc_extra_bytes(&self, map: &SourceFile, start: &mut usize, bpos: BytePos) -> u32 { + fn calc_extra_bytes( + &self, + map: &SourceFile, + prev_total_extra_bytes: &mut u32, + start: &mut usize, + bpos: BytePos, + ) -> u32 { // The number of extra bytes due to multibyte chars in the SourceFile - let mut total_extra_bytes = 0; + let mut total_extra_bytes = *prev_total_extra_bytes; for (i, &mbc) in map.multibyte_chars[*start..].iter().enumerate() { debug!("{}-byte char at {:?}", mbc.bytes, mbc.pos); @@ -991,6 +997,8 @@ impl SourceMap { } } + *prev_total_extra_bytes = total_extra_bytes; + total_extra_bytes } @@ -1183,6 +1191,11 @@ impl SourceMap { let mut prev_dst_line = u32::MAX; + let mut prev_extra_bytes = 0; + let mut ch_start = 0; + let mut line_prev_extra_bytes = 0; + let mut line_ch_start = 0; + for (pos, lc) in mappings.iter() { let pos = *pos; @@ -1214,6 +1227,12 @@ impl SourceMap { builder.set_source_contents(src_id, Some(&f.src)); } + prev_extra_bytes = 0; + ch_start = 0; + + line_prev_extra_bytes = 0; + line_ch_start = 0; + cur_file = Some(f.clone()); &f } @@ -1240,6 +1259,7 @@ impl SourceMap { } let mut line = a + 1; // Line numbers start at 1 + let linebpos = f.lines[a as usize]; debug_assert!( pos >= linebpos, @@ -1248,8 +1268,15 @@ impl SourceMap { pos, linebpos, ); - let chpos = pos.to_u32() - self.calc_extra_bytes(f, &mut 0, pos); - let linechpos = linebpos.to_u32() - self.calc_extra_bytes(f, &mut 0, linebpos); + let chpos = + pos.to_u32() - self.calc_extra_bytes(f, &mut prev_extra_bytes, &mut ch_start, pos); + let linechpos = linebpos.to_u32() + - self.calc_extra_bytes( + f, + &mut line_prev_extra_bytes, + &mut line_ch_start, + linebpos, + ); let mut col = max(chpos, linechpos) - min(chpos, linechpos);