From a4fa6eab396e703eb70b70ed708220a6405f2899 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 6 Sep 2011 16:06:27 -0700 Subject: adding a statement pool for mysql and sqlite3 --- .../connection_adapters/mysql_adapter.rb | 33 +++++++++++++++--- .../connection_adapters/sqlite_adapter.rb | 38 +++++++++++++++++--- .../connection_adapters/statement_pool.rb | 40 ++++++++++++++++++++++ 3 files changed, 102 insertions(+), 9 deletions(-) create mode 100644 activerecord/lib/active_record/connection_adapters/statement_pool.rb diff --git a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb index e9bdcc2104..8ecb3cefde 100644 --- a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb @@ -1,4 +1,5 @@ require 'active_record/connection_adapters/abstract_mysql_adapter' +require 'active_record/connection_adapters/statement_pool' require 'active_support/core_ext/hash/keys' gem 'mysql', '~> 2.8.1' @@ -90,9 +91,36 @@ module ActiveRecord ADAPTER_NAME = 'MySQL' + class StatementPool < ConnectionAdapters::StatementPool + def initialize(connection, max = 1000) + super + @cache = {} + end + + def each(&block); @cache.each(&block); end + def key?(key); @cache.key?(key); end + def [](key); @cache[key]; end + def length; @cache.length; end + def delete(key); @cache.delete(key); end + + def []=(sql, key) + while @max <= @cache.size + @cache.shift.last[:stmt].close + end + @cache[sql] = key + end + + def clear + @cache.values.each do |hash| + hash[:stmt].close + end + @cache.clear + end + end + def initialize(connection, logger, connection_options, config) super - @statements = {} + @statements = StatementPool.new(@connection) @client_encoding = nil connect end @@ -187,9 +215,6 @@ module ActiveRecord # Clears the prepared statements cache. def clear_cache! - @statements.values.each do |cache| - cache[:stmt].close - end @statements.clear end diff --git a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb index a90c675bf6..a4e21b714b 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb @@ -1,4 +1,5 @@ require 'active_record/connection_adapters/abstract_adapter' +require 'active_record/connection_adapters/statement_pool' require 'active_support/core_ext/string/encoding' module ActiveRecord @@ -48,9 +49,40 @@ module ActiveRecord end end + class StatementPool < ConnectionAdapters::StatementPool + def initialize(connection, max = 1000) + super + @cache = {} + end + + def each(&block); @cache.each(&block); end + def key?(key); @cache.key?(key); end + def [](key); @cache[key]; end + def length; @cache.length; end + + def []=(sql, key) + while @max <= @cache.size + dealloc(@cache.shift.last[:stmt]) + end + @cache[sql] = key + end + + def clear + @cache.values.each do |hash| + dealloc hash[:stmt] + end + @cache.clear + end + + private + def dealloc(stmt) + stmt.close unless stmt.closed? + end + end + def initialize(connection, logger, config) super(connection, logger) - @statements = {} + @statements = StatementPool.new(@connection) @config = config end @@ -107,10 +139,6 @@ module ActiveRecord # Clears the prepared statements cache. def clear_cache! - @statements.values.map { |hash| hash[:stmt] }.each { |stmt| - stmt.close unless stmt.closed? - } - @statements.clear end diff --git a/activerecord/lib/active_record/connection_adapters/statement_pool.rb b/activerecord/lib/active_record/connection_adapters/statement_pool.rb new file mode 100644 index 0000000000..c6b1bc8b5b --- /dev/null +++ b/activerecord/lib/active_record/connection_adapters/statement_pool.rb @@ -0,0 +1,40 @@ +module ActiveRecord + module ConnectionAdapters + class StatementPool + include Enumerable + + def initialize(connection, max = 1000) + @connection = connection + @max = max + end + + def each + raise NotImplementedError + end + + def key?(key) + raise NotImplementedError + end + + def [](key) + raise NotImplementedError + end + + def length + raise NotImplementedError + end + + def []=(sql, key) + raise NotImplementedError + end + + def clear + raise NotImplementedError + end + + def delete(key) + raise NotImplementedError + end + end + end +end -- cgit v1.2.3