Skip to content

Optimized regexes in Whiskers#16549

Closed
msooseth wants to merge 1 commit intodevelopfrom
faster-regex
Closed

Optimized regexes in Whiskers#16549
msooseth wants to merge 1 commit intodevelopfrom
faster-regex

Conversation

@msooseth
Copy link
Copy Markdown
Contributor

@msooseth msooseth commented Mar 25, 2026

Fuzzing is slow because regex is taking ~28 of total(!) time. Yes, you heard that right. That includes generation, compilation, deployment ,running ,and comparing the logs/state/returndata.

It adds static, const, and std::regex::optimize.

Perf of fuzzing before:

Samples: 2M of event 'cpu/cycles/Pu', Event count (approx.): 1941889616920
  Children      Self  Command          Shared Object             Symbol
+   99.79%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] deregister_tm_clones
+   99.79%     0.00%  sol_proto2_ossf  libc.so.6                 [.] __libc_start_main
+   99.79%     0.00%  sol_proto2_ossf  libc.so.6                 [.] 0x00007f01f90f76c1
+   99.79%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] std::__unexpected(void (*)())
+   99.79%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long))
+   99.79%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] fuzzer::Fuzzer::Loop(std::__Fuzzer::vector<fuzzer::SizedFile, std::__Fuzzer::allocator<fuzzer::SizedFile> >&)
+   99.79%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] fuzzer::Fuzzer::ReadAndExecuteSeedCorpora(std::__Fuzzer::vector<fuzzer::SizedFile, std::__Fuzzer::allocator<fuzzer::Size
+   99.77%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*)
+   93.02%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long)
+   93.01%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] LLVMFuzzerTestOneInput
+   92.98%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] runOnce(solidity::langutil::EVMVersion, std::__1::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1
+   92.76%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] solidity::test::fuzzer::EvmoneUtility::compileDeployAndExecute(std::__1::basic_string<char, std::__1::char_traits<char>,
+   92.70%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] solidity::test::fuzzer::SolidityCompilationFramework::compileContract()
+   92.68%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] solidity::frontend::CompilerStack::compile(solidity::frontend::CompilerStack::State)
+   63.96%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] solidity::frontend::CompilerStack::generateIR(solidity::frontend::ContractDefinition const&, bool)
+   43.98%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] solidity::yul::OptimiserSuite::run(solidity::yul::GasMeter const*, solidity::yul::Object&, bool, std::__1::basic_string_
+   41.72%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] solidity::yul::YulStack::optimize()
+   39.06%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] solidity::yul::ObjectOptimizer::optimize(solidity::yul::Object&, solidity::yul::ObjectOptimizer::Settings const&, bool)
+   37.96%     0.01%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] solidity::yul::OptimiserSuite::runSequence(std::__1::basic_string_view<char, std::__1::char_traits<char> >, solidity::yu
+   37.17%     0.01%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] solidity::yul::OptimiserSuite::runSequence(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, st
+   29.31%    29.30%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] __sanitizer_cov_trace_const_cmp8
+   20.67%     0.04%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] bool std::__1::basic_regex<char, std::__1::regex_traits<char> >::__search<std::__1::allocator<std::__1::sub_match<char c
+   19.77%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] solidity::frontend::CompilerStack::compileContract(solidity::frontend::ContractDefinition const&, std::__1::map<solidity
+   19.20%     0.08%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] solidity::yul::ASTModifier::visit(std::__1::variant<solidity::yul::ExpressionStatement, solidity::yul::Assignment, solid
+   19.12%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] solidity::frontend::Compiler::compileContract(solidity::frontend::ContractDefinition const&, std::__1::map<solidity::fro
+   18.67%     0.42%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] bool std::__1::basic_regex<char, std::__1::regex_traits<char> >::__match_at_start_ecma<std::__1::allocator<std::__1::sub
+   17.71%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] solidity::frontend::IRGenerator::run(solidity::frontend::ContractDefinition const&, std::__1::vector<unsigned char, std:
+   16.99%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] solidity::frontend::IRGenerator::generate(solidity::frontend::ContractDefinition const&, std::__1::vector<unsigned char,
+   15.86%     0.04%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] void solidity::yul::ASTModifier::walkVector<std::__1::vector<std::__1::variant<solidity::yul::ExpressionStatement, solid
+   15.75%     0.01%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] bool std::__1::regex_search[abi:ne220000]<char const*, std::__1::allocator<std::__1::sub_match<std::__1::__wrap_iter<cha
+   14.00%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] solidity::frontend::MultiUseYulFunctionCollector::createFunction(std::__1::basic_string<char, std::__1::char_traits<char
+   13.42%     0.01%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] solidity::util::Whiskers::replace(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >
+   12.62%     0.01%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] solidity::yul::DataFlowAnalyzer::operator()(solidity::yul::Block&)
+   12.28%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] solidity::evmasm::Assembly::optimise(solidity::evmasm::Assembly::OptimiserSettings const&)
+   12.28%     0.02%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] solidity::evmasm::Assembly::optimiseInternal(solidity::evmasm::Assembly::OptimiserSettings const&, std::__1::set<unsigne
+   11.34%    11.34%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] __sanitizer_cov_trace_cmp8
+   10.45%     0.11%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] solidity::yul::ASTWalker::visit(std::__1::variant<solidity::yul::ExpressionStatement, solidity::yul::Assignment, solidit
+   10.29%     0.07%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] void solidity::yul::ASTWalker::walkVector<std::__1::vector<std::__1::variant<solidity::yul::ExpressionStatement, solidit
+    9.70%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] solidity::frontend::ContractCompiler::compileConstructor(solidity::frontend::ContractDefinition const&, std::__1::map<so
+    9.62%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] solidity::frontend::ContractCompiler::packIntoContractCreator(solidity::frontend::ContractDefinition const&)
+    8.74%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] std::__1::regex_iterator<std::__1::__wrap_iter<char const*>, char, std::__1::regex_traits<char> >::operator++()
+    8.57%     0.25%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] solidity::yul::ASTWalker::visit(std::__1::variant<solidity::yul::FunctionCall, solidity::yul::Identifier, solidity::yul:
+    8.54%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] solidity::frontend::Block::accept(solidity::frontend::ASTConstVisitor&) const
+    8.53%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] void solidity::frontend::ASTNode::listAccept<std::__1::shared_ptr<solidity::frontend::Statement> >(std::__1::vector<std:

Perf of fuzzing after:

Samples: 2M of event 'cpu/cycles/Pu', Event count (approx.): 1966155722749
  Children      Self  Command          Shared Object             Symbol
+   99.77%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] _start
+   99.77%     0.00%  sol_proto2_ossf  libc.so.6                 [.] __libc_start_main
+   99.77%     0.00%  sol_proto2_ossf  libc.so.6                 [.] 0x00007f201ccc66c1
+   99.77%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] main
+   99.77%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long))
+   99.77%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] fuzzer::Fuzzer::Loop(std::__Fuzzer::vector<fuzzer::SizedFile, std::__Fuzzer::allocator<fuzzer::SizedFile> >&)
+   99.77%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] fuzzer::Fuzzer::ReadAndExecuteSeedCorpora(std::__Fuzzer::vector<fuzzer::SizedFile, std::__Fuzzer::allocator<fuzzer::Size
+   99.75%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*)
+   92.91%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long)
+   92.90%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] LLVMFuzzerTestOneInput
+   92.86%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] runOnce(solidity::langutil::EVMVersion, std::__1::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1
+   92.60%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] solidity::test::fuzzer::EvmoneUtility::compileDeployAndExecute(std::__1::basic_string<char, std::__1::char_traits<char>,
+   92.52%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] solidity::test::fuzzer::SolidityCompilationFramework::compileContract()
+   92.50%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] solidity::frontend::CompilerStack::compile(solidity::frontend::CompilerStack::State)
+   73.61%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] solidity::frontend::CompilerStack::generateIR(solidity::frontend::ContractDefinition const&, bool)
+   48.25%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] solidity::yul::YulStack::optimize()
+   45.13%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] solidity::yul::ObjectOptimizer::optimize(solidity::yul::Object&, solidity::yul::ObjectOptimizer::Settings const&, bool)
+   43.00%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] solidity::yul::OptimiserSuite::run(solidity::yul::GasMeter const*, solidity::yul::Object&, bool, std::__1::basic_string_
+   37.34%     0.01%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] solidity::yul::OptimiserSuite::runSequence(std::__1::basic_string_view<char, std::__1::char_traits<char> >, solidity::yu
+   36.64%     0.01%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] solidity::yul::OptimiserSuite::runSequence(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, st
+   33.95%    33.93%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] __sanitizer_cov_trace_const_cmp8
+   23.28%     0.04%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] bool std::__1::basic_regex<char, std::__1::regex_traits<char> >::__search<std::__1::allocator<std::__1::sub_match<char c
+   20.91%     0.46%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] bool std::__1::basic_regex<char, std::__1::regex_traits<char> >::__match_at_start_ecma<std::__1::allocator<std::__1::sub
+   20.06%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] solidity::frontend::IRGenerator::run(solidity::frontend::ContractDefinition const&, std::__1::vector<unsigned char, std:
+   19.46%     0.07%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] solidity::yul::ASTModifier::visit(std::__1::variant<solidity::yul::ExpressionStatement, solidity::yul::Assignment, solid
+   19.22%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] solidity::frontend::IRGenerator::generate(solidity::frontend::ContractDefinition const&, std::__1::vector<unsigned char,
+   17.65%     0.01%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] bool std::__1::regex_search[abi:ne220000]<char const*, std::__1::allocator<std::__1::sub_match<std::__1::__wrap_iter<cha
+   16.01%     0.03%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] void solidity::yul::ASTModifier::walkVector<std::__1::vector<std::__1::variant<solidity::yul::ExpressionStatement, solid
+   15.78%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] solidity::frontend::MultiUseYulFunctionCollector::createFunction(std::__1::basic_string<char, std::__1::char_traits<char
+   15.50%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] solidity::util::Whiskers::render() const
+   15.49%     0.01%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] solidity::util::Whiskers::replace(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >
+   14.00%    13.99%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] __sanitizer_cov_trace_cmp8
+   12.76%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] solidity::yul::DataFlowAnalyzer::operator()(solidity::yul::Block&)
+   10.97%    10.97%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] __sanitizer_cov_trace_const_cmp4
+   10.36%     0.10%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] solidity::yul::ASTWalker::visit(std::__1::variant<solidity::yul::ExpressionStatement, solidity::yul::Assignment, solidit
+   10.23%     0.07%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] void solidity::yul::ASTWalker::walkVector<std::__1::vector<std::__1::variant<solidity::yul::ExpressionStatement, solidit
+   10.11%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] std::__1::regex_iterator<std::__1::__wrap_iter<char const*>, char, std::__1::regex_traits<char> >::operator++()
+    9.66%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] solidity::frontend::Block::accept(solidity::frontend::ASTConstVisitor&) const
+    9.65%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] void solidity::frontend::ASTNode::listAccept<std::__1::shared_ptr<solidity::frontend::Statement> >(std::__1::vector<std:
+    9.29%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] solidity::frontend::CompilerStack::generateEVMFromIR(solidity::frontend::ContractDefinition const&)
+    8.74%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] solidity::frontend::TryStatement::accept(solidity::frontend::ASTConstVisitor&) const
+    8.66%     0.26%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] solidity::yul::ASTWalker::visit(std::__1::variant<solidity::yul::FunctionCall, solidity::yul::Identifier, solidity::yul:
+    8.47%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] solidity::frontend::CompilerStack::compileContract(solidity::frontend::ContractDefinition const&, std::__1::map<solidity
+    7.96%     0.00%  sol_proto2_ossf  sol_proto2_ossfuzz_viair  [.] solidity::frontend::IRGenerator::generateQueuedFunctions()

optimize() is now 48 instead of 41% of total runtime. No idea how this affects normal compilation. But I'd guess it should help there too?

@clonker
Copy link
Copy Markdown
Member

clonker commented Mar 25, 2026

We should look into memory consumption as an effect of using optimize here...

@cameel cameel changed the title Faster regex Optimized regexes in Whiskers Mar 25, 2026
@msooseth
Copy link
Copy Markdown
Contributor Author

msooseth commented Apr 1, 2026

Closing, figuring out the memory thing would be require a set of benchmarks and a system to measure, which we don't have and I can't built it right now.

@msooseth msooseth closed this Apr 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants