RubyMine memory usage keeps climbing on a large Rails project: indexing, breakpoints, or a real leak?
0 reputation · 30 Jun 2020, 21:23 UTC
0 reputation · 30 Jun 2020, 21:23 UTC
When working with a large Ruby on Rails codebase in RubyMine, resident memory grows steadily over a session and is not released after closing files or running garbage collection. The goal is to determine whether this is expected caching behavior or an actual leak, and to identify which component is responsible.
Three candidate contributors are documented: the indexing engine retains parsed AST nodes for the session lifetime, the built-in Memory Profiler may miss leaks rooted in Ruby garbage collector references from dynamically loaded gems, and debugger breakpoint state persists across restarts, adding incremental overhead. Assume a recent RubyMine version on the default JVM heap settings.
Constraints: heap snapshots taken via the Memory Profiler show retained objects, but it is unclear how to distinguish intentional AST/index caches from genuinely leaked objects, or how much of the baseline growth is attributable to persisted breakpoints.
Which heap-snapshot comparison approach reliably separates expected index retention from a leak in this scenario?
Can memory retained by Ruby GC roots in dynamically loaded gems be diagnosed from within RubyMine at all, or does that require external tooling?
Is clearing all breakpoints and restarting a valid isolation test, or does breakpoint state leave residual allocations that survive a restart?
35275 reputation · 01 Jul 2020, 06:49 UTC
In a large Rails project RubyMine’s indexing engine keeps parsed AST nodes and PSI trees in memory for the whole IDE session. These objects belong to JetBrains internal packages (com.intellij.* and org.jetbrains.plugins.ruby.*) and appear as retained sets even after you close files or run the IDE’s garbage collection.
Help → Diagnostic Tools → Memory Profiler → Take heap snapshot.com.intellij. or org.jetbrains.plugins.ruby..java.util.*, custom plugin classes), that indicates a genuine leak.com.intellij.debugger.impl.*). Any leftover memory here is negligible.RubyMine’s Memory Profiler cannot see Ruby objects. To detect leaks that originate from dynamically loaded gems you need external Ruby tooling, for example:
# In a rails console or a dedicated script
require 'objspace'
ObjectSpace.trace_object_allocations_start
# … reproduce the suspected scenario …
ObjectSpace.trace_object_allocations_stop
results = ObjectSpace.trace_object_allocations_results
puts results.total_allocated_size
Compare the Ruby allocation trace with the JVM snapshot diff; if the JVM shows growth that is not mirrored in the Ruby trace, the source is on the IDE side (indexing, breakpoints, plugins).
If a noticeable retained set persists in non‑indexing classes after the breakpoint reset, collect the retained‑object tree from the second snapshot and file a bug report with JetBrains, including:
Missing diagnostic detail: Are you able to force a full JVM GC (System.gc()) via the Memory Profiler before taking the second snapshot? Forcing GC can reveal whether soft‑referenced indexing caches are being retained; if you cannot do this, the diff may over‑estimate the leak.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.