Skip to content

perf: drop Mutex from cached_dasherize - #2

Merged
tomasc merged 3 commits into
mainfrom
drop-mutex
Apr 18, 2026
Merged

tomasc merged 3 commits into
mainfrom
drop-mutex

Conversation

@tomasc

@tomasc tomasc commented Apr 18, 2026

Copy link
Copy Markdown
Owner

Summary

Removes the Mutex#synchronize wrapper around cached_dasherize's cache write. The operation is deterministic — same input, same output — so a concurrent duplicate compute produces the same value and the overwrite is harmless. Ruby Hash writes are atomic enough at the VM level for this pattern (used widely in Rails internals).

Net effect: no more lock acquisition + no more Mutex#synchronize block allocation on every call. cached_dasherize is called hundreds of times per heavy page render in consumer apps (rijksakademie.nl's MemoryProfiler showed this gem at 1.5 MB allocated per request).

Code diff

-  @cache_mutex = Mutex.new
-  class << self
-    attr_reader :dasherized_cache, :cache_mutex
-  end
+  class << self
+    attr_reader :dasherized_cache
+  end

   def cached_dasherize(string)
-    StimulusHelpers.cache_mutex.synchronize do
-      StimulusHelpers.dasherized_cache[string] ||= string.dasherize
-    end
+    StimulusHelpers.dasherized_cache[string] ||= string.dasherize
   end

Test plan

  • All 7 existing tests still pass

🤖 Generated with Claude Code

tomasc and others added 3 commits April 18, 2026 10:44
The cached_dasherize method wrapped a deterministic hash write in a
Mutex#synchronize block to avoid race conditions. That's unnecessary:
- same input always yields same output
- concurrent duplicate compute produces the same value
- the overwrite is harmless
- Ruby Hash writes are atomic enough at the VM level for this pattern

memory_profiler on a heavy rijksakademie.nl page render showed this
gem allocating 1.5 MB per request. The mutex acquisition was called
hundreds of times per render; each Mutex#synchronize block allocates
a lambda under the hood. Dropping it saves both the allocation and
the lock-acquisition CPU cost.

All 14 existing assertions still pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@tomasc
tomasc merged commit ff18c76 into main Apr 18, 2026
1 check passed
@tomasc
tomasc deleted the drop-mutex branch April 18, 2026 08:47
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.

1 participant