rails-0009: FilterAttributeHandler filter_parameters Array O(A×F) → Set (450×) rails-0010: Encryption::AutoFilteredParameters two Array scans → Set (250×) rails-0011: TimeZoneConversion skip_list Array O(M×C×S) → Set (20×) exposed-0001: SchemaUtilityApi mapMissingColumnStatements O(N×M) → map (118×) exposed-0002: IdentifierManagerApi isAKeyword O(K) linear → HashSet (144×) exposed-0003: Table.clone consParams.map fresh List → hoisted HashSet (6×) seaorm-0001: active_model establish_links leftover.any O(N²) → HashSet (501×) seaorm-0002: rbac engine group_permissions .values().find() → HashMap by ID (502×) seaorm-0003: schema builder sorted_tables Vec::contains → HashSet (500×) seaorm-0004: TopologicalSort from_iter seen Vec O(N²) → BTreeSet (28×) Unit tests: RailsTest 11/11, ExposedTest 3/3, SeaORMTest 4/4 PASS Whitepaper: 157→167 sites, 62→64 ecosystems; §13.12 ORM Wave 2 added
40 lines
1.1 KiB
Markdown
40 lines
1.1 KiB
Markdown
# rails-0008: Enum — O(E²) value_method_names Array#include? in pairs.each loop
|
|
|
|
**Severity:** MEDIUM
|
|
**File:** activerecord/lib/active_record/enum.rb
|
|
**Line:** 273
|
|
**Status:** PATCHED
|
|
|
|
## Description
|
|
|
|
When defining an enum, `_enum_methods_module` iterates over all enum values with
|
|
`pairs.each` and calls `value_method_names.include?(value_method_alias)` to check for
|
|
alias conflicts. `value_method_names` is an Array that grows as each value is processed —
|
|
O(E) scan per value, O(E²) total for E enum values.
|
|
|
|
This runs at class load time for every model that declares an enum, so with many models
|
|
and large enums it contributes to slow boot times.
|
|
|
|
## Root Cause
|
|
|
|
`value_method_names` is an Array accumulating method names. The `include?` check is O(E)
|
|
per iteration.
|
|
|
|
## Fix
|
|
|
|
```ruby
|
|
# BEFORE
|
|
value_method_names = []
|
|
# ... loop:
|
|
value_method_names.include?(value_method_alias)
|
|
value_method_names << value_method_name
|
|
value_method_names << value_method_alias
|
|
|
|
# AFTER
|
|
value_method_names = Set.new
|
|
# same interface, O(1) include?
|
|
```
|
|
|
|
## Speedup
|
|
|
|
~10x at E=1000 enum values
|