Fix O(n²) in VarNameCleaner::findCleanName using per-base-name counter#16563
Fix O(n²) in VarNameCleaner::findCleanName using per-base-name counter#16563
Conversation
|
if you are very happy about this, then let's push this through instead that will fix all of this: |
nikola-matic
left a comment
There was a problem hiding this comment.
@clonker fixed the failing arch build - please rebase to fix the build.
108f6b6 to
402076b
Compare
b95e1be to
437f7e1
Compare
nikola-matic
left a comment
There was a problem hiding this comment.
Can you squash some of the commits please. Also, perfectly fine with this as a stop-gap until Yul IDs are merged (@clonker you wanna give this PR a final look before we merge?)
| YulName newNameSuffixed = YulName{newName.str() + "_" + std::to_string(nextSuffix)}; | ||
| if (!isUsedName(newNameSuffixed)) | ||
| { | ||
| ++nextSuffix; |
There was a problem hiding this comment.
if i interpret everything correctly, this is supposed to increment the suffix in the map, right? but I don't think it does, it's retrieved by value so the map value isnt updated, ever.
There was a problem hiding this comment.
Yes. I'm sorry. It was written correctly and then broken. in 4b13837
Fixing now.
There was a problem hiding this comment.
Haha some idiot probably suggested removing the reference. Wait a minute...
When many variables share the same stripped base name, findCleanName would probe name_1, name_2, ..., name_N sequentially for each variable, resulting in O(n²) calls to isUsedName (which involves regex matching via isRestrictedIdentifier). This was the dominant cost in fuzzer timeouts where the optimizer generated many variables. Track a counter per base name (m_nextSuffix) so we resume from the last assigned suffix instead of reprobing from 1 each time. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Fix more Update More tests More tests
Co-authored-by: Nikola Matić <nikola.matic@ethereum.org>
This reverts commit 4b13837.
437f7e1 to
c4eb333
Compare
clonker
left a comment
There was a problem hiding this comment.
Happy to approve if you put the const back :) also let's think about extracting this (plus the NameSimplifier) into an external tool that can be run on demand.
| } | ||
|
|
||
| YulName VarNameCleaner::findCleanName(YulName const& _name) const | ||
| YulName VarNameCleaner::findCleanName(YulName const& _name) |
There was a problem hiding this comment.
| YulName VarNameCleaner::findCleanName(YulName const& _name) | |
| YulName VarNameCleaner::findCleanName(YulName const& _name) const |
since the cache is now mutable, you can put back the const :)
When many variables share the same stripped base name, findCleanName would probe name_1, name_2, ..., name_N sequentially for each variable, resulting in O(n²) calls to isUsedName (which involves regex matching via isRestrictedIdentifier). This was the dominant cost in fuzzer timeouts where the optimizer generated many variables.
Track a counter per base name (m_nextSuffix) so we resume from the last assigned suffix instead of reprobing from 1 each time.
Found by the fuzzer with custom optimization ordering.