diff --git a/lib/rdoc/code_object/class_module.rb b/lib/rdoc/code_object/class_module.rb index b564059ae7..370f95914b 100644 --- a/lib/rdoc/code_object/class_module.rb +++ b/lib/rdoc/code_object/class_module.rb @@ -741,10 +741,12 @@ def search_record # Returns an HTML snippet of the first comment for search results. def search_snippet + return @search_snippet_cache if instance_variable_defined?(:@search_snippet_cache) + first_comment = @comment_location.each_value.first&.first return '' unless first_comment && !first_comment.empty? - snippet(first_comment) + @search_snippet_cache = snippet(first_comment) end ## @@ -757,6 +759,7 @@ def rebuild_comment_from_location } merged = texts.join("\n---\n") @comment = merged.empty? ? '' : RDoc::Comment.new(merged) + remove_instance_variable(:@search_snippet_cache) if instance_variable_defined?(:@search_snippet_cache) end ## diff --git a/lib/rdoc/code_object/constant.rb b/lib/rdoc/code_object/constant.rb index 20015b86f1..d49622548d 100644 --- a/lib/rdoc/code_object/constant.rb +++ b/lib/rdoc/code_object/constant.rb @@ -168,7 +168,7 @@ def path def search_snippet return '' if comment.empty? - snippet(comment) + @search_snippet_cache ||= snippet(comment) end def pretty_print(q) # :nodoc: diff --git a/lib/rdoc/code_object/method_attr.rb b/lib/rdoc/code_object/method_attr.rb index 3169640982..745c040e3c 100644 --- a/lib/rdoc/code_object/method_attr.rb +++ b/lib/rdoc/code_object/method_attr.rb @@ -397,7 +397,7 @@ def search_record def search_snippet return '' if @comment.empty? - snippet(@comment) + @search_snippet_cache ||= snippet(@comment) end def to_s # :nodoc: diff --git a/lib/rdoc/generator/aliki.rb b/lib/rdoc/generator/aliki.rb index d8314196f9..45fe14a66f 100644 --- a/lib/rdoc/generator/aliki.rb +++ b/lib/rdoc/generator/aliki.rb @@ -86,7 +86,7 @@ def build_search_index end end - @methods.each do |method| + methods.each do |method| next unless method.display? index << build_method_entry(method) diff --git a/lib/rdoc/generator/darkfish.rb b/lib/rdoc/generator/darkfish.rb index 8e63f5bd23..fd12c1dc74 100644 --- a/lib/rdoc/generator/darkfish.rb +++ b/lib/rdoc/generator/darkfish.rb @@ -118,9 +118,13 @@ class RDoc::Generator::Darkfish attr_reader :json_index ## - # Methods to be displayed by this generator + # Methods to be displayed by this generator. + # Computed lazily from @classes to avoid sorting 10K+ methods on every + # refresh_store_data call. - attr_reader :methods + def methods + @methods ||= @classes&.flat_map { |m| m.method_list }&.sort + end ## # Sorted list of classes and modules to be displayed by this generator @@ -588,10 +592,11 @@ def setup def refresh_store_data @classes = @store.all_classes_and_modules.sort @files = @store.all_files.sort - @methods = @classes.flat_map { |m| m.method_list }.sort + @methods = nil # computed lazily by #all_methods @modsort = get_sorted_module_list @classes end + ## # Creates a template from its components and the +body_file+. # diff --git a/lib/rdoc/server.rb b/lib/rdoc/server.rb index 9dbb342908..70676680d4 100644 --- a/lib/rdoc/server.rb +++ b/lib/rdoc/server.rb @@ -85,6 +85,7 @@ def start @running = true @watcher_thread = start_watcher(@rdoc.last_modified.keys) + prebuild_search_index url = "http://localhost:#{@port}" $stderr.puts "\nServing documentation at: \e]8;;#{url}\e\\#{url}\e]8;;\e\\" @@ -118,6 +119,20 @@ def create_generator gen end + ## + # Pre-builds the search index so it's ready when the user first + # requests search_data.js. This avoids a multi-second delay + # on the first search request. Called before accepting connections + # so no synchronization is needed. + + def prebuild_search_index + index = @generator.build_search_index + @page_cache['js/search_data.js'] = "var search_data = #{JSON.generate(index: index)};" + $stderr.puts "Search index ready (#{index.size} entries)" + rescue => e + $stderr.puts "Search index pre-build error: #{e.message}" + end + ## # Reads an HTTP request from +client+ and dispatches to the router.