Skip to content

Conversation

@orien
Copy link
Member

@orien orien commented Jan 2, 2026

Context

The L33t matcher is a performance-critical component, accounting for approximately 57% of password matching time in benchmarks. The matcher identifies passwords using "l33t speak" substitutions (e.g., @ for a, 0 for o) by testing various substitution combinations against dictionary matchers.

Changes

Performance optimisations:

  • Added early bailout when no l33t characters are present in the password, avoiding unnecessary processing
  • Replaced string concatenation with Set-based comparison in the deduplication method for faster duplicate detection
  • Optimised the translate method to use each_char with direct string building instead of split/map/join, eliminating intermediate array allocations

Test improvements:

  • Expanded test coverage from 9 to 27 examples (3x increase)
  • Added tests for early bailout behaviour
  • Added tests for multiple substitution types and ambiguous l33t characters
  • Added edge case testing (empty passwords, repeated characters)
  • Added comprehensive translate method testing
  • Added verification of l33t flag and sub_display fields

Dependencies:

  • Added benchmark gem to development dependencies for performance measurement

Performance

Benchmark results (1000 iterations across 10 diverse passwords):

  • Before: 0.143ms per password
  • After: 0.135ms per password
  • Improvement: 5.6% faster

All 262 tests pass, confirming correctness is maintained whilst improving performance.

orien added 4 commits January 2, 2026 08:46
- Add early bailout when no l33t characters are present in password
- Replace string concatenation with Set-based dedup for better performance
- Use hash comparison instead of string labels for duplicate detection
- Add benchmark gem to development dependencies

Performance improvement: 5.6% faster (0.143ms -> 0.135ms per password)
Replace split/map/join with each_char string building for better performance.
This avoids creating intermediate array objects.
Add comprehensive tests covering:
- Early bailout when no l33t characters present
- Multiple l33t substitution types
- Ambiguous l33t characters (e.g., '1' for 'i' or 'l')
- Mixed case password handling
- Edge cases (empty passwords, repeated characters)
- Detailed translate method testing
- l33t flag and sub_display field verification

Test count increased from 9 to 27 examples.
Extract match processing logic into private process_match method to satisfy
RuboCop Metrics/PerceivedComplexity requirement whilst maintaining readability.
@orien orien merged commit 52e6b47 into master Jan 2, 2026
18 checks passed
@orien orien deleted the optimise-l33t-matcher branch January 15, 2026 05:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants