dackdive's blog

新米webエンジニアによる技術ブログ。JavaScript(React), Salesforce, Python など

[Google App Engine]NDBのIn-Context Cacheについて

In-Context Cache とは

https://cloud.google.com/appengine/docs/python/ndb/cache#incontext

  • 1 リクエスト内で有効なキャッシュ
  • 速度は In-Context Cache < Memcache < Datastore の順
    • In-Context Cache が microseconds に対し、Memcache は milliseconds とも( 参考

キャッシュのコントロール方法

キャッシュの有効・無効を設定するには Context クラスを使う。Context クラスは ndb.get_context() で取得可能。
In-Context Cache や Memcache を無効にしたい場合はそれぞれ set_cache_policy(), set_memcache_policy()False を渡す。

# context
ctx = ndb.get_context()

# In-Context Cache 無効
ctx.set_cache_policy(False)

# Memcache 無効
ctx.set_memcache_policy(False)

# 特定の kind だけ
ctx.set_cache_policy(lambda key: key.kind() != 'Person')

# 一度きり
key.get(use_cache=False)

# clear all caches
ctx.clear_cache()

サンプルコード

In-Context Cache の有効性を確認するため、次のようなコードを用意した。
(実際には Django の View の get メソッド)

def get(self, request):
    ctx = ndb.get_context()
    ctx.set_cache_policy(False)  # (1) In-Context Cache を無効にしたい場合
    ctx.set_memcache_policy(False)  # (2) Memcache を無効にしたい場合

    key = ndb.Key(MyModel, 'foo')  # エンティティは存在するという前提
    model1 = key.get()
    model2 = key.get()
    model3 = key.get()
    model4 = key.get()
    model5 = key.get()

実行結果

はじめに、キャッシュについて何も設定しない場合。
(1), (2) をコメントアウトした状態で実行する。

# ctx.set_cache_policy(False)  # (1) In-Context Cache を無効にしたい場合
# ctx.set_memcache_policy(False)  # (2) Memcache を無効にしたい場合

結果を AppStats で確認する。

f:id:dackdive:20150312193223p:plain

上記のように、RPC は最初の一度しか実行されていないことがわかる。


次に、In-Context Cache を無効にするとどうなるか。

ctx.set_cache_policy(False)  # (1) In-Context Cache を無効にしたい場合
# ctx.set_memcache_policy(False)  # (2) Memcache を無効にしたい場合

f:id:dackdive:20150312193235p:plain

たしかに、key.get() の数だけ RPC が実行されていることが確認できた。
なるほど。

おまけ

(2) のコメントアウトも外すと、ちゃんと Memcache でなく Datastore から取得しているのがわかる。

ctx.set_cache_policy(False)  # (1) In-Context Cache を無効にしたい場合
ctx.set_memcache_policy(False)  # (2) Memcache を無効にしたい場合

f:id:dackdive:20150312193238p:plain

set_context_policy() について

キャッシュを無効にするには set_context_policy(False) とすればいいと上で書いたが、
実際には set_context_policy() の引数は
Key クラスのインスタンスを引数とし、「このキーを持つエンティティをキャッシュするかどうか」という bool 値を返す関数
らしい。

例として、MyModel クラスのみキャッシュしないようにするには以下のようになる(はず)。

ctx.set_cache_policy(lambda key: key.kind() != 'MyModel')

リファレンス

(公式) https://cloud.google.com/appengine/docs/python/ndb/cache#incontext

http://ameblo.jp/cabeat-e/theme2-10061863878.html

http://blog.vier.jp/2013/02/google-app-engine-appengine-ja-night-23.html

https://docs.google.com/a/gigei.jp/presentation/d/1FDbkr0AoGxPOcEdaEjRb3ENxltxNxKTsdJW2PnmPU-8/edit#slide=id.g1ec03be_0_5

set_cache_policy() について https://cloud.google.com/appengine/docs/python/ndb/contextclass#Context_set_cache_policy