DEV: Speed up requests in development mode (#12890)

On every request, Rails checks to see whether any ruby code has been changed on the filesystem. The default FileUpdateChecker does this by iterating over every file on the autoload_paths and comparing its modified-time.

In Discourse, our autoload path of `/app` includes the `/app/assets` directory, and therefore thousands of non-ruby files (e.g. node_modules). This makes the `Dir["/app"]` call very slow (>100ms in my case). On my machine, every Rails-handled request spends around 150-200ms in the FileUpdateChecker. This commit introduces a couple of changes to completely eliminate this wasted time:

- The `/app/assets` directory is excluded from the file watchers. For me, this cut the time spent in the file_watcher to around 50-100ms

- Switches our development config to use the `EventedFileUpdateChecker`, which makes use of the `listen` gem to subscribe to os-specific notifications of changes. This completely removes the `FileUpdateChecker` from the critical path

On my machine, topic_list requests now return in around 80ms (previously >200ms). Live code reload still works as it did before
This commit is contained in:
David Taylor 2021-04-29 15:40:55 +01:00 committed by GitHub
parent 614166ab1e
commit 59c239d85c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 14 additions and 0 deletions

View File

@ -120,6 +120,19 @@ module Discourse
Rails.autoloaders.main.ignore(Dir["#{config.root}/app/models/reports"])
Rails.autoloaders.main.ignore(Dir["#{config.root}/lib/freedom_patches"])
def watchable_args
files, dirs = super
# Skip the assets directory. It doesn't contain any .rb files, so watching it
# is just slowing things down and raising warnings about node_modules symlinks
app_file_extensions = dirs.delete("#{config.root}/app")
Dir["#{config.root}/app/*"].reject { |path| path.end_with? "/assets" }.each do |path|
dirs[path] = app_file_extensions
end
[files, dirs]
end
# Only load the plugins named here, in the order given (default is alphabetical).
# :all can be used as a placeholder for all plugins not explicitly named.
# config.plugins = [ :exception_notification, :ssl_requirement, :all ]

View File

@ -7,6 +7,7 @@ Discourse::Application.configure do
# every request. This slows down response time but is perfect for development
# since you don't have to restart the web server when you make code changes.
config.cache_classes = false
config.file_watcher = ActiveSupport::EventedFileUpdateChecker
# Log error messages when you accidentally call methods on nil.
config.eager_load = false