Google App Engineキャッシング

Google App Engine 前の記事で既に知っているように、App Engineには情報を保存する多くの方法があります。 しかし、それらの多くは非常に具体的であり、インスタンスメモリ、memcache、およびデータストアの3つだけが広範囲の使用に適しています。

カットの下に、数字と写真の要約、キャッシングに関する簡単な推奨事項、および単純なキャッシャーとテストアプリケーションのソースコードがあります。

テスト方法。


テストのために、データベースにさまざまなランダムデータを入力し、さまざまな方法でそれらを読み取ることができる別のアプリケーションが起動されました(ソースには写真のテストもありますが、この記事の範囲外にすることにしました)。 リクエストは数秒間隔でほぼ同時に再生され、結果はAppStatsを使用して記録され、その後平均結果が選択され、スクリーンショットが作成されました。

データ。


ランダムジェネレーターの結果が使用されます。各サブセクションでは、最初に約60Kbのテキストを持つ1つのレコードの結果があり、次に1000個の小さなレコードのリスト(平均コメントにほぼ対応)があります。

データストア。


もちろん、最も信頼性が高く、最も遅いストレージから始めましょう。 get_by_key_name()メソッドを使用して、データストアから60Kbの1つのレコードを取得します。
アプリエンジン、DBからのテキスト

見た目は良さそうです-ランタイムと消費リソースの両方の面で、今度は1000の「コメント」のサンプルを取得してみましょう。
アプリエンジン、DBからのリスト

これが、スケーラブルなApp Engine上のスケーラブルでないアプリケーションの主な理由です。データを取得するのに440ミリ秒かかり、わずかな量のコンピューティングリソースが消費されます。 このレートでは、アプリケーションはわずか数千のリクエストで無料の割り当てを消費できます。データをキャッシュする必要があります。

注:GqlQueryを実行すると、1000レコードのグループでall()。Fetch(1000)メソッドによって10秒のapi_cpuが取得され、より多くのリソースが消費されてより多くのレコードから選択されます。 私が見た最大のものは、1000レコードがHRDS(高レプリケーションデータストア)に追加されたときの561,000 api_cpu_msでした。 そのため、App Engineで多数の選択を行う場合は、非常に慎重に作業する必要があります。

Memcache


最も普遍的なツールはmemcacheであり、データストアへのクエリの結果を保存することをお勧めします。

アプリエンジン、memcacheからのテキスト

録音はほぼ2倍高速で、必要なプロセッサー時間は2倍短くなります。 確かに、絶対的な意味で、10msの節約は深刻ではないようです。 次に、memcacheがリストをダイジェストする方法を見てみましょう。
アプリエンジン、memcacheのリスト

ここで、節約ははるかに大きくなります。1.5倍速く、15倍安くなります。

Memcache + protobuf。


Memcacheは無料で、ほとんど制限はありませんが、それでもゴムではありません-プロトコルバッファ内のdb.Modelクラスのオブジェクトをシリアル化することで、データのサイズを小さくしてみてください( この記事で推奨)。 これにより、データをより長い間memcacheに保存できますが、アプリケーションの動作は改善されますか?..

アプリエンジン、プロトコルバッファを備えたmemcacheのテキスト
アプリエンジン、プロトコルバッファ付きのmemcacheからのリスト
最初のケースで差がほとんど見えない場合、2番目のケースでは実行時間と消費リソースの増加が20〜25%はっきりと見えます。

Memcache + protobuf + zlib。


サイズを縮小しているため、アーカイブを試みる必要があります。そのため、zlib.compressを使用してシリアル化された行を圧縮します。

アプリエンジン、プロトコルバッファとzlibを備えたインスタンスメモリからのテキスト

Memcache.Getランタイムは、圧縮されたテキストがはるかに高速で送信されるため、1ミリ秒減少しました。 ただし、データを解凍すると、蓄積された利点はすべて失われます。

アプリエンジン、プロトコルバッファとzlibを含むインスタンスメモリからのリスト
多数の小さなレコードでは、そのような利点はなく、時間とリソースが約5%増加するだけです。

ローカルメモリ。


そこで、生産性を向上させる極端な手段であるインスタンスメモリに到達しました。 多くの欠点に加えて(各インスタンスには独自のメモリがあり、このメモリは50 MBしかありません。インスタンスが最大9000リクエストに達することは非常にまれです)、主な利点があります-速度。
アプリエンジン、インスタンスメモリからのテキスト
いつものように、1つのエントリについて、節約額は重要ではありません。リストを使用すると、まったく別の問題になります。
アプリエンジン、インスタンスメモリからのリスト
ランタイムが100倍に短縮され、コンピューティングリソースがまったく必要なくなりました。これは、インスタンスメモリを使用してすべてを連続してキャッシュするための適切な引数です。

しかし、欠点を忘れないでください:
  1. 各インスタンスには独自のメモリがあり、それに応じてキャッシュがあります。
  2. メモリの50メガバイトの合計。


最初の問題を解決するために、キャッシュ同期のトリッキーなメカニズムを考え出すことができます。 たとえば、キャッシュハッシュをmemcacheに保存し、一致しない場合はキャッシュを更新します。 しかし、紛らわしいように思えます。最後の手段として、使い慣れたprotobufとzlibの助けを借りて、消費されるメモリ量をより少なくしようとしましょう。

ローカルメモリ+ protobuf。


アプリエンジン、プロトコルバッファを備えたインスタンスメモリからのテキスト
アプリエンジン、プロトコルバッファを備えたインスタンスメモリからのリスト
1つのレコードについて、時間の変動はほとんどエラー内にありますが、深刻な症状がリストに表示されます。インスタンスメモリとmemcacheの時間とリソースは実質的に一致しています。 このような単純な方法で、圧縮はパフォーマンスの向上を損なう可能性があります。

ローカルメモリ+ protobuf + zlib。


そして、注文のために、zlibを使用してインスタンスメモリからデータを取得します。

アプリエンジン、プロトコルバッファとzlibを備えたインスタンスメモリからのテキスト
アプリエンジン、プロトコルバッファとzlibを含むインスタンスメモリからのリスト
奇跡は起こりませんでした-リストの取得にはまだ時間がかかり、多くのリソースを消費します。

結論


アプリケーションコード。


テストアプリケーションコードはこちらからダウンロードできます。 プロジェクトでこのアーカイブのキャッシュを使用しないことをお勧めします;代わりに、ここから受け取ったデータ用に最適化されたバージョンを使用することをお勧めします。

Source: https://habr.com/ru/post/J113883/


All Articles