Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Memory leak and slowdowns in Primer::Forms components #3259

Open
cbliard opened this issue Jan 10, 2025 · 0 comments
Open

Memory leak and slowdowns in Primer::Forms components #3259

cbliard opened this issue Jan 10, 2025 · 0 comments
Labels

Comments

@cbliard
Copy link

cbliard commented Jan 10, 2025

In Primer::Forms::BaseComponent, each time #compile! is called, it calls this line:

renders_template File.join(dir, "#{self.name.demodulize.underscore}.html.erb"), :render_template

This adds the template file to the template_globs array of the Primer::Forms::ActAsComponent module (source), which is then used in compile! in the included ActAsComponent module to compile the templates before rendering (source).

The problem is that compile! is called each time Primer::Forms::BaseComponent#compile_and_render_template is called (source) which happens every time a component is rendered (source).

I confirmed it by adding a p template_globs in #renders_templates. The printed list keeps growing on each rendering.

It's not a big memory leak, but the problem becomes noticeable in development: because templates are always recompiled in dev, and the template list is ever growing, the same template gets compiled multiple times which eventually slows down the application.

I noticed it as I was waiting for more than 1 second for a simple page update. This was confirmed in the application logs:

D, [2025-01-10T14:48:30.157985 #37009] DEBUG -- :   ↳ app/forms/work_packages/dialogs/create_form.rb:63:in `block (2 levels) in <class:CreateForm>'
I, [2025-01-10T14:48:31.238213 #37009]  INFO -- : Completed 200 OK in 1131ms (Views: 0.0ms | ActiveRecord: 10.7ms | Allocations: 3158630)

After a restart, on first request:

D, [2025-01-10T16:14:44.258971 #46501] DEBUG -- :   ↳ app/forms/work_packages/dialogs/create_form.rb:63:in `block (2 levels) in <class:CreateForm>'
I, [2025-01-10T16:14:44.310702 #46501]  INFO -- : Completed 200 OK in 261ms (Views: 0.1ms | ActiveRecord: 108.5ms | Allocations: 233774)

To sum up numbers:

  • On startup: 0,052 seconds for rendering and 233 774 allocations
  • After using the app for a while: 1,080 seconds for rendering (+1,028) and 3 158 630 allocations (+2 924 856)

Replacing the array with a Set in app/lib/primer/forms/acts_as_component.rb fixes the issue

      def template_globs
        @template_globs ||= Set.new
      end

But maybe you'd prefer fixing it another way, like calling renders_template only once at class initialization.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant