Skip to content

Reduce inotify watches when cache_classes is enabled

Stan Hu requested to merge sh-reduce-inotify-watches into master

What does this MR do and why?

This only affects development environments. Previously when Puma started, 12 separate threads of rb-fsevent from the listen gem were running to monitor file changes even when the cache_classes setting were enabled. This occurred for two reasons:

  1. The factory_bot_rails gem spins up file watchers, and there is no way to disable this behavior. This appears to be responsible for 4 different threads. Upstream fix: https://github.com/thoughtbot/factory_bot_rails/pull/418

  2. The lookbook gem checks the reload_classes_only_on_change setting to determine whether to spin up file watchers. While Rails ignores this setting if cache_classes is enabled, the lookbook gem does not. This appears to be responsible for 8 different threads. Upstream fix: https://github.com/ViewComponent/lookbook/pull/514

Also disable these file watchers in Rake tasks or in the Rails console to improve performance and to reduce the number of inotify watches needed to run GitLab.

How to set up and validate locally

  1. gdk config set gitlab.cache_classes true
  2. gdk reconfigure
  3. Watch gdk tail rails-web and look for this WARNING message go from 13 to 1:
2023-08-03_00:25:14.92568 rails-web             : {"timestamp":"2023-08-03T00:25:14.925Z","pid":31768,"message":"! WARNING: Detected 13 Thread(s) started in app boot:"}
2023-08-03_00:25:14.92571 rails-web             : {"timestamp":"2023-08-03T00:25:14.925Z","pid":31768,"message":"! #\u003cThread:0x000000014e3e75c0@Timeout stdlib thread /Users/stanhu/.asdf/installs/ruby/3.1.4/lib/ruby/gems/3.1.0/gems/timeout-0.3.2/lib/timeout.rb:101 sleep\u003e - /Users/stanhu/.asdf/installs/ruby/3.1.4/lib/ruby/gems/3.1.0/gems/timeout-0.3.2/lib/timeout.rb:113:in `sleep'"}
2023-08-03_00:25:14.92578 rails-web             : {"timestamp":"2023-08-03T00:25:14.925Z","pid":31768,"message":"! #\u003cThread:0x00000001598b43e0@listen-wait_thread /Users/stanhu/.asdf/installs/ruby/3.1.4/lib/ruby/gems/3.1.0/gems/listen-3.7.1/lib/listen/thread.rb:17 sleep_forever\u003e - /Users/stanhu/.asdf/installs/ruby/3.1.4/lib/ruby/3.1.0/forwardable.rb:238:in `pop'"}
2023-08-03_00:25:14.92662 rails-web             : {"timestamp":"2023-08-03T00:25:14.926Z","pid":31768,"message":"! #\u003cThread:0x00000001598f4508@listen-worker_thread /Users/stanhu/.asdf/installs/ruby/3.1.4/lib/ruby/gems/3.1.0/gems/listen-3.7.1/lib/listen/thread.rb:17 sleep\u003e - /Users/stanhu/.asdf/installs/ruby/3.1.4/lib/ruby/gems/3.1.0/gems/rb-fsevent-0.11.2/lib/rb-fsevent/fsevent.rb:44:in `select'"}
2023-08-03_00:25:14.92667 rails-web             : {"timestamp":"2023-08-03T00:25:14.926Z","pid":31768,"message":"! #\u003cThread:0x0000000159ab5608@listen-run_thread /Users/stanhu/.asdf/installs/ruby/3.1.4/lib/ruby/gems/3.1.0/gems/listen-3.7.1/lib/listen/thread.rb:17 run\u003e - /Users/stanhu/.asdf/installs/ruby/3.1.4/lib/ruby/gems/3.1.0/gems/listen-3.7.1/lib/listen/record.rb:87:in `merge'"}
2023-08-03_00:25:14.92667 rails-web             : {"timestamp":"2023-08-03T00:25:14.926Z","pid":31768,"message":"! #\u003cThread:0x0000000159aafaf0@listen-wait_thread /Users/stanhu/.asdf/installs/ruby/3.1.4/lib/ruby/gems/3.1.0/gems/listen-3.7.1/lib/listen/thread.rb:17 sleep_forever\u003e - /Users/stanhu/.asdf/installs/ruby/3.1.4/lib/ruby/3.1.0/forwardable.rb:238:in `pop'"}
2023-08-03_00:25:14.92669 rails-web             : {"timestamp":"2023-08-03T00:25:14.926Z","pid":31768,"message":"! #\u003cThread:0x0000000159a97a18@listen-run_thread /Users/stanhu/.asdf/installs/ruby/3.1.4/lib/ruby/gems/3.1.0/gems/listen-3.7.1/lib/listen/thread.rb:17 run\u003e - \u003cinternal:dir\u003e:98:in `open'"}
2023-08-03_00:25:14.92670 rails-web             : {"timestamp":"2023-08-03T00:25:14.926Z","pid":31768,"message":"! #\u003cThread:0x0000000159a96730@listen-wait_thread /Users/stanhu/.asdf/installs/ruby/3.1.4/lib/ruby/gems/3.1.0/gems/listen-3.7.1/lib/listen/thread.rb:17 sleep_forever\u003e - /Users/stanhu/.asdf/installs/ruby/3.1.4/lib/ruby/3.1.0/forwardable.rb:238:in `pop'"}
2023-08-03_00:25:14.92790 rails-web             : {"timestamp":"2023-08-03T00:25:14.927Z","pid":31768,"message":"! #\u003cThread:0x000000012c204ef0@listen-wait_thread /Users/stanhu/.asdf/installs/ruby/3.1.4/lib/ruby/gems/3.1.0/gems/listen-3.7.1/lib/listen/thread.rb:17 sleep_forever\u003e - /Users/stanhu/.asdf/installs/ruby/3.1.4/lib/ruby/3.1.0/forwardable.rb:238:in `pop'"}
2023-08-03_00:25:14.92793 rails-web             : {"timestamp":"2023-08-03T00:25:14.927Z","pid":31768,"message":"! #\u003cThread:0x000000012c3c5668@listen-wait_thread /Users/stanhu/.asdf/installs/ruby/3.1.4/lib/ruby/gems/3.1.0/gems/listen-3.7.1/lib/listen/thread.rb:17 sleep_forever\u003e - /Users/stanhu/.asdf/installs/ruby/3.1.4/lib/ruby/3.1.0/forwardable.rb:238:in `pop'"}
2023-08-03_00:25:14.92793 rails-web             : {"timestamp":"2023-08-03T00:25:14.927Z","pid":31768,"message":"! #\u003cThread:0x000000012c32d868@listen-worker_thread /Users/stanhu/.asdf/installs/ruby/3.1.4/lib/ruby/gems/3.1.0/gems/listen-3.7.1/lib/listen/thread.rb:17 sleep\u003e - /Users/stanhu/.asdf/installs/ruby/3.1.4/lib/ruby/gems/3.1.0/gems/rb-fsevent-0.11.2/lib/rb-fsevent/fsevent.rb:44:in `select'"}
2023-08-03_00:25:14.92795 rails-web             : {"timestamp":"2023-08-03T00:25:14.927Z","pid":31768,"message":"! #\u003cThread:0x000000012c6ad858@listen-worker_thread /Users/stanhu/.asdf/installs/ruby/3.1.4/lib/ruby/gems/3.1.0/gems/listen-3.7.1/lib/listen/thread.rb:17 sleep\u003e - /Users/stanhu/.asdf/installs/ruby/3.1.4/lib/ruby/gems/3.1.0/gems/rb-fsevent-0.11.2/lib/rb-fsevent/fsevent.rb:44:in `select'"}
2023-08-03_00:25:14.92797 rails-web             : {"timestamp":"2023-08-03T00:25:14.927Z","pid":31768,"message":"! #\u003cThread:0x000000011cb3c758@listen-run_thread /Users/stanhu/.asdf/installs/ruby/3.1.4/lib/ruby/gems/3.1.0/gems/listen-3.7.1/lib/listen/thread.rb:17 sleep\u003e - \u003cinternal:dir\u003e:98:in `open'"}
2023-08-03_00:25:14.92797 rails-web             : {"timestamp":"2023-08-03T00:25:14.927Z","pid":31768,"message":"! #\u003cThread:0x000000011cac7160@listen-wait_thread /Users/stanhu/.asdf/installs/ruby/3.1.4/lib/ruby/gems/3.1.0/gems/listen-3.7.1/lib/listen/thread.rb:17 sleep_forever\u003e - /Users/stanhu/.asdf/installs/ruby/3.1.4/lib/ruby/3.1.0/forwardable.rb:238:in `pop'"}

This should now look something like:

2023-08-03_05:13:18.43211 rails-web             : {"timestamp":"2023-08-03T05:13:18.432Z","pid":65371,"message":"! WARNING: Detected 1 Thread(s) started in app boot:"}
2023-08-03_05:13:18.43218 rails-web             : {"timestamp":"2023-08-03T05:13:18.432Z","pid":65371,"message":"! #\u003cThread:0x0000000160c46150@Timeout stdlib thread /Users/stanhu/.asdf/installs/ruby/3.1.4/lib/ruby/gems/3.1.0/gems/timeout-0.3.2/lib/timeout.rb:101 sleep\u003e - [\"/Users/stanhu/.asdf/installs/ruby/3.1.4/lib/ruby/gems/3.1.0/gems/timeout-0.3.2/lib/timeout.rb:113:in `sleep'\", \"/Users/stanhu/.asdf/installs/ruby/3.1.4/lib/ruby/gems/3.1.0/gems/timeout-0.3.2/lib/timeout.rb:113:in `wait'\", \"/Users/stanhu/.asdf/installs/ruby/3.1.4/lib/ruby/gems/3.1.0/gems/timeout-0.3.2/lib/timeout.rb:113:in `block (2 levels) in create_timeout_thread'\", \"/Users/stanhu/.asdf/installs/ruby/3.1.4/lib/ruby/gems/3.1.0/gems/timeout-0.3.2/lib/timeout.rb:111:in `synchronize'\", \"/Users/stanhu/.asdf/installs/ruby/3.1.4/lib/ruby/gems/3.1.0/gems/timeout-0.3.2/lib/timeout.rb:111:in `block in create_timeout_thread'\"]"}

MR acceptance checklist

This checklist encourages us to confirm any changes have been analyzed to reduce risks in quality, performance, reliability, security, and maintainability.

Edited by Stan Hu

Merge request reports