Skip to content

Commit b993f86

Browse files
authored
refactor(es/lexer): Add fast lexer implementation (#10145)
**Description:** This is a rewrite from scratch. I'll split PRs into multiple parts to track improvements. I'll not publish these codes as a separate crate. I'll merge this into `swc_ecma_parser` before publishing`. ## Benchmark result: ### Original ``` Gnuplot not found, using plotters backend es/lexer/colors time: [4.1904 µs 4.1986 µs 4.2077 µs] change: [-2.4433% -2.1954% -1.9296%] (p = 0.00 < 0.05) Performance has improved. Found 9 outliers among 100 measurements (9.00%) 8 (8.00%) high mild 1 (1.00%) high severe es/lexer/angular time: [2.2530 ms 2.2538 ms 2.2546 ms] change: [+51.233% +51.601% +51.891%] (p = 0.00 < 0.05) Performance has regressed. Found 7 outliers among 100 measurements (7.00%) 5 (5.00%) high mild 2 (2.00%) high severe es/lexer/backbone time: [263.75 µs 265.09 µs 266.61 µs] change: [+70.699% +71.214% +71.745%] (p = 0.00 < 0.05) Performance has regressed. Found 9 outliers among 100 measurements (9.00%) 1 (1.00%) high mild 8 (8.00%) high severe Benchmarking es/lexer/jquery: Warming up for 3.0000 s Warning: Unable to complete 100 samples in 5.0s. You may wish to increase target time to 7.9s, enable flat sampling, or reduce sample count to 50. es/lexer/jquery time: [1.5150 ms 1.5171 ms 1.5197 ms] change: [+50.850% +52.439% +53.705%] (p = 0.00 < 0.05) Performance has regressed. Found 5 outliers among 100 measurements (5.00%) 4 (4.00%) high mild 1 (1.00%) high severe es/lexer/jquery mobile time: [2.2891 ms 2.2909 ms 2.2934 ms] change: [+39.568% +39.823% +40.053%] (p = 0.00 < 0.05) Performance has regressed. Found 4 outliers among 100 measurements (4.00%) 3 (3.00%) high mild 1 (1.00%) high severe Benchmarking es/lexer/mootools: Warming up for 3.0000 s Warning: Unable to complete 100 samples in 5.0s. You may wish to increase target time to 5.9s, enable flat sampling, or reduce sample count to 60. es/lexer/mootools time: [1.1470 ms 1.1515 ms 1.1576 ms] change: [+56.433% +57.853% +59.914%] (p = 0.00 < 0.05) Performance has regressed. Found 19 outliers among 100 measurements (19.00%) 1 (1.00%) low mild 2 (2.00%) high mild 16 (16.00%) high severe es/lexer/underscore time: [217.32 µs 217.42 µs 217.54 µs] change: [+79.825% +80.151% +80.449%] (p = 0.00 < 0.05) Performance has regressed. Found 7 outliers among 100 measurements (7.00%) 3 (3.00%) high mild 4 (4.00%) high severe es/lexer/three time: [6.8574 ms 6.8609 ms 6.8644 ms] change: [+45.520% +45.636% +45.743%] (p = 0.00 < 0.05) Performance has regressed. Benchmarking es/lexer/yui: Warming up for 3.0000 s Warning: Unable to complete 100 samples in 5.0s. You may wish to increase target time to 6.3s, enable flat sampling, or reduce sample count to 60. es/lexer/yui time: [1.2488 ms 1.2572 ms 1.2658 ms] change: [+48.947% +49.498% +50.119%] (p = 0.00 < 0.05) Performance has regressed. Found 21 outliers among 100 measurements (21.00%) 5 (5.00%) high mild 16 (16.00%) high severe ``` ### New: ``` es/fast-lexer/angular time: [1.6318 ms 1.6343 ms 1.6373 ms] Found 10 outliers among 100 measurements (10.00%) 2 (2.00%) high mild 8 (8.00%) high severe es/fast-lexer/backbone time: [176.71 µs 177.24 µs 177.81 µs] Found 12 outliers among 100 measurements (12.00%) 2 (2.00%) high mild 10 (10.00%) high severe Benchmarking es/fast-lexer/jquery: Warming up for 3.0000 s Warning: Unable to complete 100 samples in 5.0s. You may wish to increase target time to 5.5s, enable flat sampling, or reduce sample count to 60. es/fast-lexer/jquery time: [1.0616 ms 1.0638 ms 1.0663 ms] Found 3 outliers among 100 measurements (3.00%) 3 (3.00%) high mild Benchmarking es/fast-lexer/jquery mobile: Warming up for 3.0000 s Warning: Unable to complete 100 samples in 5.0s. You may wish to increase target time to 9.1s, enable flat sampling, or reduce sample count to 50. es/fast-lexer/jquery mobile time: [1.7711 ms 1.7734 ms 1.7767 ms] Found 12 outliers among 100 measurements (12.00%) 3 (3.00%) high mild 9 (9.00%) high severe es/fast-lexer/mootools time: [825.96 µs 828.12 µs 830.45 µs] Found 9 outliers among 100 measurements (9.00%) 7 (7.00%) high mild 2 (2.00%) high severe es/fast-lexer/underscore time: [138.14 µs 138.33 µs 138.59 µs] Found 7 outliers among 100 measurements (7.00%) 2 (2.00%) high mild 5 (5.00%) high severe es/fast-lexer/three time: [5.2196 ms 5.2250 ms 5.2319 ms] Found 7 outliers among 100 measurements (7.00%) 1 (1.00%) low mild 3 (3.00%) high mild 3 (3.00%) high severe es/fast-lexer/yui time: [931.84 µs 935.58 µs 940.20 µs] Found 9 outliers among 100 measurements (9.00%) 9 (9.00%) high mild ```
1 parent 58e4279 commit b993f86

35 files changed

+10113
-0
lines changed

.cursorrules

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
1. You should write performant code. Always prefer performance over other things.
2+
2. Always write comments in English.
3+
3. Do not use unstable, nightly only features.
4+
4. When creating Atom instances, it's better to use Cow<str> or &str instead of String. Note that `&str` is better than `Cow<str>` here.

Cargo.lock

Lines changed: 45 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ resolver = "2"
127127
wasm-bindgen-futures = "0.4.41"
128128
wasmer = { version = "=5.0.5-rc1", default-features = false }
129129
wasmer-wasix = { version = "0.35.0", default-features = false }
130+
wide = "0.7.32"
130131

131132
[profile.release]
132133
lto = true
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
[package]
2+
authors = ["강동윤 <[email protected]>"]
3+
description = "Feature-complete es2019 parser."
4+
documentation = "https://rustdoc.swc.rs/swc_ecma_fast_parser/"
5+
edition = { workspace = true }
6+
include = ["Cargo.toml", "src/**/*.rs", "examples/**/*.rs"]
7+
license = { workspace = true }
8+
name = "swc_ecma_fast_parser"
9+
publish = false
10+
repository = { workspace = true }
11+
version = "1.0.0"
12+
13+
[features]
14+
nightly = []
15+
16+
[dependencies]
17+
swc_atoms = { version = "5.0.0", path = "../swc_atoms" }
18+
swc_common = { version = "8.0.0", path = "../swc_common" }
19+
swc_ecma_ast = { version = "8.0.0", path = "../swc_ecma_ast" }
20+
21+
num-bigint = { workspace = true }
22+
phf = { workspace = true, features = ["macros"] }
23+
wide = { workspace = true }
24+
25+
[dev-dependencies]
26+
criterion = { workspace = true }
27+
pretty_assertions = { workspace = true }
28+
serde_json = { workspace = true }
29+
walkdir = { workspace = true }
30+
31+
codspeed-criterion-compat = { workspace = true }
32+
swc_ecma_ast = { version = "8.0.0", path = "../swc_ecma_ast", features = [
33+
"serde-impl",
34+
] }
35+
swc_ecma_visit = { version = "8.0.0", path = "../swc_ecma_visit" }
36+
swc_malloc = { version = "1.2.2", path = "../swc_malloc" }
37+
testing = { version = "8.0.0", path = "../testing" }
38+
39+
[[bench]]
40+
harness = false
41+
name = "lexer"
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
extern crate swc_malloc;
2+
3+
use codspeed_criterion_compat::{black_box, criterion_group, criterion_main, Bencher, Criterion};
4+
use swc_common::FileName;
5+
use swc_ecma_fast_parser::{token::TokenType, JscTarget, Lexer, Syntax};
6+
7+
fn bench_module(b: &mut Bencher, syntax: Syntax, src: &'static str) {
8+
let _ = ::testing::run_test(false, |cm, _| {
9+
let fm = cm.new_source_file(FileName::Anon.into(), src.into());
10+
11+
b.iter(|| {
12+
let mut count = 0;
13+
let mut lexer = Lexer::new(&fm.src, JscTarget::EsNext, syntax, None);
14+
15+
loop {
16+
if lexer.current.token_type == TokenType::EOF {
17+
break;
18+
}
19+
count += 1;
20+
let token = lexer.next_token();
21+
22+
black_box(token).unwrap_or_else(|err| {
23+
let loc = cm.lookup_char_pos(err.span.lo);
24+
panic!("{err:?}: {loc:?}");
25+
});
26+
}
27+
28+
assert_ne!(count, 0);
29+
});
30+
Ok(())
31+
});
32+
}
33+
34+
fn bench_files(c: &mut Criterion) {
35+
c.bench_function("es/fast-lexer/angular", |b| {
36+
bench_module(
37+
b,
38+
Default::default(),
39+
include_str!("../../swc_ecma_parser/benches/files/angular-1.2.5.js"),
40+
)
41+
});
42+
43+
c.bench_function("es/fast-lexer/backbone", |b| {
44+
bench_module(
45+
b,
46+
Default::default(),
47+
include_str!("../../swc_ecma_parser/benches/files/backbone-1.1.0.js"),
48+
)
49+
});
50+
51+
c.bench_function("es/fast-lexer/jquery", |b| {
52+
bench_module(
53+
b,
54+
Default::default(),
55+
include_str!("../../swc_ecma_parser/benches/files/jquery-1.9.1.js"),
56+
)
57+
});
58+
59+
c.bench_function("es/fast-lexer/jquery mobile", |b| {
60+
bench_module(
61+
b,
62+
Default::default(),
63+
include_str!("../../swc_ecma_parser/benches/files/jquery.mobile-1.4.2.js"),
64+
)
65+
});
66+
c.bench_function("es/fast-lexer/mootools", |b| {
67+
bench_module(
68+
b,
69+
Default::default(),
70+
include_str!("../../swc_ecma_parser/benches/files/mootools-1.4.5.js"),
71+
)
72+
});
73+
74+
c.bench_function("es/fast-lexer/underscore", |b| {
75+
bench_module(
76+
b,
77+
Default::default(),
78+
include_str!("../../swc_ecma_parser/benches/files/underscore-1.5.2.js"),
79+
)
80+
});
81+
82+
c.bench_function("es/fast-lexer/three", |b| {
83+
bench_module(
84+
b,
85+
Default::default(),
86+
include_str!("../../swc_ecma_parser/benches/files/three-0.138.3.js"),
87+
)
88+
});
89+
90+
c.bench_function("es/fast-lexer/yui", |b| {
91+
bench_module(
92+
b,
93+
Default::default(),
94+
include_str!("../../swc_ecma_parser/benches/files/yui-3.12.0.js"),
95+
)
96+
});
97+
}
98+
99+
criterion_group!(benches, bench_files);
100+
criterion_main!(benches);

0 commit comments

Comments
 (0)