From c5535f3e84288a44112a70b07d4658d8875702a3 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 | 44 ++++++++++++++++++------------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/lib/jekyll/filters/url_filters.rb b/lib/jekyll/filters/url_filters.rb index 777502d0718..72150a36d45 100644 --- a/lib/jekyll/filters/url_filters.rb +++ b/lib/jekyll/filters/url_filters.rb @@ -10,16 +10,20 @@ 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] ||= begin + input = input.url if input.respond_to?(:url) + site = @context.registers[:site] + if Addressable::URI.parse(input.to_s).absolute? + input + elsif site.config["url"].nil? + relative_url(input) + else + Addressable::URI.parse( + site.config["url"].to_s + relative_url(input) + ).normalize.to_s + end + end end # Produces a URL relative to the domain root based on site.baseurl @@ -30,14 +34,18 @@ 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] ||= begin + input = input.url if input.respond_to?(:url) + if Addressable::URI.parse(input.to_s).absolute? + input + else + parts = [sanitized_baseurl, input] + Addressable::URI.parse( + parts.compact.map { |part| ensure_leading_slash(part.to_s) }.join + ).normalize.to_s + end + end end # Strips trailing `/index.html` from URLs to create pretty permalinks