From a4a6678b0ea38184a2eb9a7a6482d63d56b78f4a Mon Sep 17 00:00:00 2001 From: Nikhil Benesch Date: Sun, 18 Aug 2019 21:47:07 -0400 Subject: [PATCH] Memoize absolute_url and relative_url filters These two filters are quite slow, as Addressable::URI.parse is quite slow. Fortunately, they are pure functions and so can be easily memoized. This one change shaves 8s off the CockroachDB docs build (github.com/cockroachdb/docs). --- lib/jekyll/filters/url_filters.rb | 50 ++++++++++++++++++------------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/lib/jekyll/filters/url_filters.rb b/lib/jekyll/filters/url_filters.rb index 777502d0718..2c8e268884b 100644 --- a/lib/jekyll/filters/url_filters.rb +++ b/lib/jekyll/filters/url_filters.rb @@ -9,17 +9,8 @@ module URLFilters # # Returns the absolute URL as a String. def absolute_url(input) - return if input.nil? - - input = input.url if input.respond_to?(:url) - return input if Addressable::URI.parse(input.to_s).absolute? - - site = @context.registers[:site] - return relative_url(input) if site.config["url"].nil? - - Addressable::URI.parse( - site.config["url"].to_s + relative_url(input) - ).normalize.to_s + cache = (@context.registers[:cached_absolute_urls] ||= {}) + cache[input] ||= compute_absolute_url(input) end # Produces a URL relative to the domain root based on site.baseurl @@ -29,15 +20,8 @@ def absolute_url(input) # # Returns a URL relative to the domain root as a String. def relative_url(input) - return if input.nil? - - input = input.url if input.respond_to?(:url) - return input if Addressable::URI.parse(input.to_s).absolute? - - parts = [sanitized_baseurl, input] - Addressable::URI.parse( - parts.compact.map { |part| ensure_leading_slash(part.to_s) }.join - ).normalize.to_s + cache = (@context.registers[:cached_relative_urls] ||= {}) + cache[input] ||= compute_relative_url(input) end # Strips trailing `/index.html` from URLs to create pretty permalinks @@ -53,6 +37,32 @@ def strip_index(input) private + def compute_absolute_url(input) + return if input.nil? + + input = input.url if input.respond_to?(:url) + return input if Addressable::URI.parse(input.to_s).absolute? + + site = @context.registers[:site] + return relative_url(input) if site.config["url"].nil? + + Addressable::URI.parse( + site.config["url"].to_s + relative_url(input) + ).normalize.to_s + end + + def compute_relative_url(input) + return if input.nil? + + input = input.url if input.respond_to?(:url) + return input if Addressable::URI.parse(input.to_s).absolute? + + parts = [sanitized_baseurl, input] + Addressable::URI.parse( + parts.compact.map { |part| ensure_leading_slash(part.to_s) }.join + ).normalize.to_s + end + def sanitized_baseurl site = @context.registers[:site] site.config["baseurl"].to_s.chomp("/")