Open
Description
About 3% of parse time on a 57MB input is spent in isValidMethodTypeArguments
.
This is a function that 99.x% of the time checks that the next token is not '<' and returns false.
I discovered this looking at the cpu_profile in Observatory.
A lot of new-gen GCs happen when allocating _Closures.
In parsing, a third of GCs triggered by _Closures come from this function.
About 1% of total parse time is GC originating in this function.
There is a lot here that makes me sad:
The language failed us.
- It is too hard to write mutually recursive local functions.
- The unnatural code we have to write instead is harder for compilers to understand too.
- This has been an open issue in the bug tracker for five years.
The VM implementation failed us:
- The profile data hints that four closures are allocated per call.
- Ideally, there would be no allocations - the four closures do not escape and are called directly.
- I would expect tryParseMethodTypeArguments to be inlined - it has just one call site, with no recursion. The 99.x% taken path would then return immediately.
dart2js is pretty terrible too.
- Due it the JIT-like legacy of compiling functions one-at-a-time and weak inlining ability, it too cannot do anything sensible. (See
Duration.toString.sixDigits
for an example of needless closure creation.)
Suggestion
I suggest in the short term that these local functions are moved to be private methods on the class.