tedious / JShrink

Javascript Minifier built in PHP
http://www.tedivm.com
BSD 3-Clause "New" or "Revised" License
749 stars 152 forks source link

endsInKeyword check slow on large Javascript #139

Closed mdetrano closed 9 months ago

mdetrano commented 9 months ago

I noticed something in the endsInKeyword function that I think is causing a large performance hit when processing large amounts of Javascript.

The check does a preg_match on the full output in order to see if it is ending with certain keywords. However, as that output grows this check takes longer and longer to run.

Would it not be better to limit the amount of output matched to something reasonable? For instance, I changed:

$testOutput = $this->output . $this->a;

to

$testOutput = substr($this->output . $this->a, -50);

and processing time for my experiment dropped from over a minute to a second or two. No change in the Javascript produced (though I am not entirely sure what condition this function is used for).

tedivm commented 9 months ago

This is a really good catch. It's worth noting that the keyword list is here-

https://github.com/tedious/JShrink/blob/35a83e0ab661d6130da5930c0c4eafcc663b8cec/src/JShrink/Minifier.php#L113

The largest keyword is instanceof.

The regex for that turns into [^\w]instanceof[ ]?$. It's looking for a single character in front of the keyword, and then an optional space before the end of the output. That's a maximum of largest keyword + 2, or in this case 10, characters needed for the check.

If you want to make the PR, assuming tests pass, I'll happily merge it.

mdetrano commented 9 months ago

Added pull request with fix based on max keyword length

141