From 242348ad682950fb6bf1f47877068cc23ba95879 Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Fri, 14 Jul 2017 15:20:31 +0900 Subject: Use `Concurrent::Map` than `Mutex` and `Mutex_m` for statement caches Statement caches are used as a concurrent map. It will more clarify to using `Concurrent::Map`. --- activerecord/lib/active_record/core.rb | 7 +++---- activerecord/lib/active_record/reflection.rb | 9 +++------ 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb index 5d673339cf..fbb4c671a5 100644 --- a/activerecord/lib/active_record/core.rb +++ b/activerecord/lib/active_record/core.rb @@ -2,6 +2,7 @@ require "active_support/core_ext/hash/indifferent_access" require "active_support/core_ext/string/filters" +require "concurrent/map" module ActiveRecord module Core @@ -149,7 +150,7 @@ module ActiveRecord end def initialize_find_by_cache # :nodoc: - @find_by_statement_cache = { true => {}.extend(Mutex_m), false => {}.extend(Mutex_m) } + @find_by_statement_cache = { true => Concurrent::Map.new, false => Concurrent::Map.new } end def inherited(child_class) # :nodoc: @@ -281,9 +282,7 @@ module ActiveRecord def cached_find_by_statement(key, &block) cache = @find_by_statement_cache[connection.prepared_statements] - cache[key] || cache.synchronize { - cache[key] ||= StatementCache.create(connection, &block) - } + cache.compute_if_absent(key) { StatementCache.create(connection, &block) } end def relation diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb index 2fdd2bf77c..97f1a83033 100644 --- a/activerecord/lib/active_record/reflection.rb +++ b/activerecord/lib/active_record/reflection.rb @@ -1,8 +1,8 @@ # frozen_string_literal: true -require "thread" require "active_support/core_ext/string/filters" require "active_support/deprecation" +require "concurrent/map" module ActiveRecord # = Active Record Reflection @@ -443,8 +443,7 @@ module ActiveRecord @type = options[:as] && (options[:foreign_type] || "#{options[:as]}_type") @foreign_type = options[:foreign_type] || "#{name}_type" @constructable = calculate_constructable(macro, options) - @association_scope_cache = {} - @scope_lock = Mutex.new + @association_scope_cache = Concurrent::Map.new if options[:class_name] && options[:class_name].class == Class ActiveSupport::Deprecation.warn(<<-MSG.squish) @@ -463,9 +462,7 @@ module ActiveRecord if polymorphic? key = [key, owner._read_attribute(@foreign_type)] end - @association_scope_cache[key] ||= @scope_lock.synchronize { - @association_scope_cache[key] ||= StatementCache.create(conn, &block) - } + @association_scope_cache.compute_if_absent(key) { StatementCache.create(conn, &block) } end def constructable? # :nodoc: -- cgit v1.2.3