From deeeace841461fd674ec5392da9aa6169225911c Mon Sep 17 00:00:00 2001 From: Maximo Mussini Date: Wed, 21 Jul 2021 21:08:13 -0300 Subject: [PATCH] fix: Avoid scanning and building entries for silenced directories Building entries that will be ignored by the listener degrades the initialization performance, and can greatly increase memory consumption. Specially on projects with large .git or node_modules directories. --- lib/listen/adapter/base.rb | 2 +- lib/listen/record.rb | 5 ++++- spec/lib/listen/record_spec.rb | 7 +++++-- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/lib/listen/adapter/base.rb b/lib/listen/adapter/base.rb index 3e1b19d0..b7e10390 100644 --- a/lib/listen/adapter/base.rb +++ b/lib/listen/adapter/base.rb @@ -51,7 +51,7 @@ def configure # TODO: separate config per directory (some day maybe) change_config = Change::Config.new(config.queue, config.silencer) config.directories.each do |dir| - record = Record.new(dir) + record = Record.new(dir, config.silencer) snapshot = Change.new(change_config, record) @snapshots[dir] = snapshot end diff --git a/lib/listen/record.rb b/lib/listen/record.rb index 4f8fedf0..e34ae275 100644 --- a/lib/listen/record.rb +++ b/lib/listen/record.rb @@ -11,9 +11,10 @@ class Record attr_reader :root - def initialize(directory) + def initialize(directory, silencer) @tree = _auto_hash @root = directory.to_s + @silencer = silencer end def add_dir(rel_path) @@ -98,6 +99,8 @@ def _fast_unset_path(dirname, basename) def _fast_build_dir(remaining, symlink_detector) entry = remaining.pop + return if @silencer.silenced?(entry.record_dir_key, :dir) + children = entry.children # NOTE: children() implicitly tests if dir symlink_detector.verify_unwatched!(entry) children.each { |child| remaining << child } diff --git a/spec/lib/listen/record_spec.rb b/spec/lib/listen/record_spec.rb index d3674ee1..d99a2c33 100644 --- a/spec/lib/listen/record_spec.rb +++ b/spec/lib/listen/record_spec.rb @@ -2,7 +2,8 @@ RSpec.describe Listen::Record do let(:dir) { instance_double(Pathname, to_s: '/dir') } - let(:record) { Listen::Record.new(dir) } + let(:silencer) { Listen::Silencer.new } + let(:record) { Listen::Record.new(dir, silencer) } def dir_entries_for(hash) hash.each do |dir, entries| @@ -308,9 +309,11 @@ def record_tree(record) context 'with subdir containing files' do before do - real_directory('/dir' => %w[dir1 dir2]) + real_directory('/dir' => %w[dir1 dir2 .git]) + real_directory('/dir/.git' => %w[FETCH_HEAD]) real_directory('/dir/dir1' => %w[foo]) real_directory('/dir/dir1/foo' => %w[bar]) + lstat(file('/dir/.git/FETCH_HEAD')) lstat(file('/dir/dir1/foo/bar')) real_directory('/dir/dir2' => []) end