boa icon indicating copy to clipboard operation
boa copied to clipboard

Stack alloc reduce

Open Nikita-str opened this issue 11 months ago • 6 comments

This Pull Request closes #4089

Reduce the stack size. Mostly affected expression with nested parenthesizes.

Some examples & comparison charts
fn parenthesized_fn_test() {
    let n = ...;
    let js = "(function(){ ".repeat(n) + &" })()".repeat(n);

    let interner = &mut Interner::default();
    crate::Parser::new(crate::Source::from_bytes(&js))
        .parse_script(&boa_ast::scope::Scope::new_global(), interner)
        .expect("failed to parse");
}
profile prev max n
without stack overflow
new max n
without stack overflow
x
dev (opt-level = 0) 11 79 ~6
test (opt-level = 1) 50 160 ~3
release 50 217 ~4

fn parenthesized_sum_test() {
    let n = ...;
    let js = "(1+".repeat(n) + "41" + &")".repeat(n);

    let interner = &mut Interner::default();
    crate::Parser::new(crate::Source::from_bytes(&js))
        .parse_script(&boa_ast::scope::Scope::new_global(), interner)
        .expect("failed to parse");
}
profile prev max n
without stack overflow
new max n
without stack overflow
x
dev (opt-level = 0) 30 200 ~6.5
test (opt-level = 1) 105 390 ~3.5
release 105 510 ~4.5

Now there no stack overflow when running the boa_tester in debug(cargo run -p boa_tester -- run -v -o test262 ). The problem was here test262\test\language\statements\function\S13.2.1_A1_T1.js, so you can run cargo run -p boa_tester -- run -s test/language/statements/function/ to test the fix. For more details see the issue.


The reduction performed by 3 operations:

  1. boxing of large objects. It's affected all profiles and allow to reduce the stack size by ~ 3 times;
  2. In one place nested parse calls was unwrapped. Also affected all profiles;
  3. Splitting parse function. Affected only profile.dev (opt-level = 0) where the problem arose. Allow to reduce the stack size by ~ 2 times (and with boxing it becomes ~ 6 times).

There are some ugly changes that need to be discussed & maybe rewritten to a less ugly:

All of the changes reduce the stack size, so even if they are ugly, they are still not meaningless :/

Nikita-str avatar Feb 27 '25 17:02 Nikita-str

Codecov Report

Attention: Patch coverage is 71.97232% with 162 lines in your changes missing coverage. Please review.

Project coverage is 52.78%. Comparing base (6ddc2b4) to head (e324a18). Report is 385 commits behind head on main.

Files with missing lines Patch % Lines
core/parser/src/parser/expression/primary/mod.rs 45.45% 60 Missing :warning:
core/parser/src/parser/expression/mod.rs 76.08% 22 Missing :warning:
...ore/parser/src/parser/expression/assignment/mod.rs 68.65% 21 Missing :warning:
...parser/src/parser/expression/left_hand_side/mod.rs 52.27% 21 Missing :warning:
...ser/src/parser/expression/left_hand_side/member.rs 62.96% 10 Missing :warning:
core/parser/src/parser/expression/update.rs 91.11% 4 Missing :warning:
core/ast/src/expression/call.rs 62.50% 3 Missing :warning:
core/ast/src/expression/operator/binary/mod.rs 62.50% 3 Missing :warning:
...e/parser/src/parser/expression/assignment/yield.rs 40.00% 3 Missing :warning:
...arser/src/parser/expression/left_hand_side/call.rs 70.00% 3 Missing :warning:
... and 10 more
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4191      +/-   ##
==========================================
+ Coverage   47.24%   52.78%   +5.54%     
==========================================
  Files         476      488      +12     
  Lines       46892    52236    +5344     
==========================================
+ Hits        22154    27575    +5421     
+ Misses      24738    24661      -77     

:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.

codecov[bot] avatar Feb 27 '25 17:02 codecov[bot]

I would like to see the performance impact of this one, in release. Would you mind running the v8 combined benchmarks?

cargo run -p boa_cli --release -- -O $SRC/boa-dev/data/bench/bench-v8/combined.js

(with $SRC being wherever your root for boa-dev/data repo is)

hansl avatar Feb 28 '25 01:02 hansl

Current results of the bench.
PROGRESS Richards
RESULT Richards 72.8
PROGRESS DeltaBlue
RESULT DeltaBlue 64.4
PROGRESS Encrypt
PROGRESS Decrypt
RESULT Crypto 144
PROGRESS RayTrace
RESULT RayTrace 196
PROGRESS Earley
PROGRESS Boyer
RESULT EarleyBoyer 229
PROGRESS RegExp
RESULT RegExp 61.0
PROGRESS Splay
RESULT Splay 355
PROGRESS NavierStokes
RESULT NavierStokes 337
SCORE 147
undefined
Previous(checkout 35b44d9ce07efb45fb094887964d473911b21012) results of the bench.
PROGRESS Richards
RESULT Richards 76.0
PROGRESS DeltaBlue
RESULT DeltaBlue 64.8
PROGRESS Encrypt
PROGRESS Decrypt
RESULT Crypto 140
PROGRESS RayTrace
RESULT RayTrace 190
PROGRESS Earley
PROGRESS Boyer
RESULT EarleyBoyer 230
PROGRESS RegExp
RESULT RegExp 61.2
PROGRESS Splay
RESULT Splay 357
PROGRESS NavierStokes
RESULT NavierStokes 334
SCORE 147
undefined

Seems like a noise error. And it's pretty predictable, because as I can understand the bench tests the perf of js execution, and PR's changes affect only the parser stage. So is there a bench to test perf of the parser stage?

Nikita-str avatar Feb 28 '25 14:02 Nikita-str

Nice! I'll review when I have some time this weekend.

hansl avatar Feb 28 '25 18:02 hansl

Another question I would have is whether the new _boxed constructors are necessary, instead of simply replacing the regular constructors. WDYT?

hansl avatar Mar 08 '25 04:03 hansl

Another question I would have is whether the new _boxed constructors are necessary, instead of simply replacing the regular constructors. WDYT?

Hmm... new_boxed shows that the return value is not Self but Box<Self>; and sometimes there is another code which does not need Box<T>.

Nikita-str avatar Mar 09 '25 03:03 Nikita-str