Rails.cache.write
現在、dalli を使用してmemcachierクラウドにアイテムを書き込む際のパフォーマンスを改善することを考えています。
キャッシュに関連するスタックは、現在次のとおりです。
heroku, memcachier heroku addon, dalli 2.6.4, rails 3.0.19
パフォーマンス監視に newrelic を使用しています。
現在、「アクティブな学生」のリストを必要とするリクエストを処理するコントローラーからメソッドが呼び出されたBusinessUser
ときに、インスタンスで表される特定のログイン ユーザーの「アクティブな学生」を取得しています。active_students
class BusinessUser < ActiveRecord::Base
...
def active_students
Rails.cache.fetch("/studio/#{self.id}/students") do
customer_users.active_by_name
end
end
...
end
newrelic を調べた後、基本的に memcachier に重要な値を設定することで、アプリの大きなパフォーマンス ヒットを 1 つ絞り込みました。毎回平均225ミリ秒かかります。さらに、memcache キー値を設定するとメイン スレッドがブロックされ、最終的にリクエスト キューが中断されるようです。明らかに、これは望ましくありません。特に、キャッシング戦略の要点がパフォーマンスのボトルネックを減らすことである場合はなおさらです。
さらに、プレーン dalli と Rails.cache.write を使用してキャッシュ ストレージのベンチマークを行い、同じ値の 1000 個のキャッシュ セットを使用しました。
heroku run console -a {app-name-redacted}
irb(main):001:0> require 'dalli'
=> false
irb(main):002:0> cache = Dalli::Client.new(ENV["MEMCACHIER_SERVERS"].split(","),
irb(main):003:1* {:username => ENV["MEMCACHIER_USERNAME"],
irb(main):004:2* :password => ENV["MEMCACHIER_PASSWORD"],
irb(main):005:2* :failover => true,
irb(main):006:2* :socket_timeout => 1.5,
irb(main):007:2* :socket_failure_delay => 0.2
irb(main):008:2> })
=> #<Dalli::Client:0x00000006686ce8 @servers=["server-redacted:11211"], @options={:username=>"username-redacted", :password=>"password-redacted", :failover=>true, :socket_timeout=>1.5, :socket_failure_delay=>0.2}, @ring=nil>
irb(main):009:0> require 'benchmark'
=> false
irb(main):010:0> n = 1000
=> 1000
irb(main):011:0> Benchmark.bm do |x|
irb(main):012:1* x.report { n.times do ; cache.set("foo", "bar") ; end }
irb(main):013:1> x.report { n.times do ; Rails.cache.write("foo", "bar") ; end }
irb(main):014:1> end
user system total real
Dalli::Server#connect server-redacted:11211
Dalli/SASL authenticating as username-redacted
Dalli/SASL: username-redacted
0.090000 0.050000 0.140000 ( 2.066113)
Dalli::Server#connect server-redacted:11211
Dalli/SASL authenticating as username-redacted
Dalli/SASL: username-redacted
0.100000 0.070000 0.170000 ( 2.108364)
通常の dallicache.set
では、2.066113 秒を使用して 1000 エントリをキャッシュに書き込み、平均cache.set
時間は 2.06 ミリ秒です。
ではRails.cache.write
、2.108364 秒を使用して 1000 エントリをキャッシュに書き込み、平均Rails.cache.write
時間は 2.11 ミリ秒です。
⇒ memcachier の問題ではなく、単に保存しようとしているデータの量に問題があるようです。
#fetch メソッドのドキュメントによると、キャッシュセットをwrite
別read
のスレッドまたはワーカーにスローしたい場合、それは私が行きたい方法ではないようです。そして自明のことですが、私は非同期で読みたくないのです。
Rails.cache.write
キーの値を設定するときに、ワーカーにスローすることでボトルネックを減らすことはできますか? または、より一般的には、実行するたびにメインスレッドをブロックしないように、これを行うためのより良いパターンはありRails.cache.write
ますか?