Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cache nil values in the CachedEnvironment #723

Merged
merged 4 commits into from
Jun 23, 2022

Conversation

lsylvester
Copy link
Contributor

Values cached in the CachedEnvironment can be nil - in which case the current ||= caching still calls through to the original environment.

Benchmarking script (this was inside a real app - so your numbers may vary depending on assets/paths in the application):

# frozen_string_literal: true

require 'benchmark/ips'

require_relative "./config/environment"

# Any benchmarking setup goes here...

original_cache = Rails.application.assets.cached

class NewCachedEnvironment < Sprockets::Base
  def initialize(environment)
    initialize_configuration(environment)

    @cache   = environment.cache
    @stats   = {}
    @entries = {}
    @uris    = {}
    @processor_cache_keys = {}
    @resolved_dependencies = {}
  end

  # No-op return self as cached environment.
  def cached
    self
  end
  alias_method :index, :cached

  # Internal: Cache Environment#entries
  def entries(path)
    @entries.fetch(path){ @entries[path] = super(path) }
  end

  # Internal: Cache Environment#stat
  def stat(path)
    @stats.fetch(path){ @stats[path] = super(path) }
  end

  # Internal: Cache Environment#load
  def load(uri)
    @uris.fetch(uri){ @uris[uri] = super(uri) }
  end

  # Internal: Cache Environment#processor_cache_key
  def processor_cache_key(str)
    @processor_cache_keys.fetch(str){ @processor_cache_keys[str] = super(str) }
  end

  # Internal: Cache Environment#resolve_dependency
  def resolve_dependency(str)
    @resolved_dependencies.fetch(str){ @resolved_dependencies[str] = super(str) }
  end

  private
    # Cache is immutable, any methods that try to change the runtime config
    # should bomb.
    def config=(config)
      raise RuntimeError, "can't modify immutable cached environment"
    end
end

new_cache = NewCachedEnvironment.new(Rails.application.assets)

Benchmark.ips do |x|

  x.report("original") do
    original_cache.find_asset("rails-ujs.js")
  end

  x.report("new") do
    new_cache.find_asset("rails-ujs.js")
  end

  x.compare!
end

Result

Warming up --------------------------------------
            original    35.000  i/100ms
                 new    53.000  i/100ms
Calculating -------------------------------------
            original    350.256  (± 6.9%) i/s -      1.750k in   5.020250s
                 new    472.983  (± 8.0%) i/s -      2.385k in   5.076110s

Comparison:
                 new:      473.0 i/s
            original:      350.3 i/s - 1.35x  (± 0.00) slower

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants