The FormBuilder#find_mapping method is relying on Object#const_get raising an exception if the constant doesn't exist, rather than directly checking if it exists with Object#const_defined?.
Exceptions are slow due to generating backtraces - and then when other debugging gems (such as did_you mean, which are included with Ruby and Rails these days) get involved it resulted in excessive Object allocation.
Normally the discovery_cache would mitigate this, so there wouldn't be many calls to #mapping_override, however when you use #simple_fields_for with a collection/has_many association the cache is empty for each item in the collection.
Before this change this code was taking approximately 2 seconds and 2.9million allocations for 235 records:
The
FormBuilder#find_mapping
method is relying onObject#const_get
raising an exception if the constant doesn't exist, rather than directly checking if it exists withObject#const_defined?
.Exceptions are slow due to generating backtraces - and then when other debugging gems (such as did_you mean, which are included with Ruby and Rails these days) get involved it resulted in excessive Object allocation.
Normally the
discovery_cache
would mitigate this, so there wouldn't be many calls to#mapping_override
, however when you use#simple_fields_for
with a collection/has_many association the cache is empty for each item in the collection.Before this change this code was taking approximately 2 seconds and 2.9million allocations for 235 records:
After this change it was down to approximately 100ms and 200,000 allocations. (All on my M1 MacBook Air)