7

要求/応答サイクル中に変更されることはないが、数百回 (場合によっては数千回) 呼び出されるデータベースの値に対して、インメモリ スレッド ローカル キャッシュを使用したいと考えています。私の限られた理解は、「グローバル」/モジュール変数を使用することが、このタイプのキャッシュを実装する 1 つの方法であるということです。

例えば:

#somefile.py

foo = None

def get_foo(request):
  global foo
  if not foo:
    foo = get_foo_from_db(request.blah)
  return foo

このタイプの「グローバル」を使用することがPythonでスレッドセーフであるかどうか疑問に思っているため、djangoでget_foo_from_db()が要求/応答サイクルごとに1回だけ呼び出されることに満足できます(runserverまたはgunicorn + geventのいずれかを使用) )。私の理解は正しいですか?このことは十分に呼び出されるため、memcached を使用して値を保存することさえボトルネックになります (私が話している間、私はそれをプロファイリングしています)。

4

2 に答える 2

6

いいえ、グローバルへのアクセスはスレッドセーフではありません。スレッドはグローバルの独自のコピーを取得せず、グローバルはスレッド間で共有されます。

コード:

if not foo:
    foo = get_foo_from_db(request.blah)

いくつかの python バイトコード ステートメントにコンパイルされます。

  2           0 LOAD_FAST                1 (foo)
              3 POP_JUMP_IF_TRUE        24

  3           6 LOAD_GLOBAL              0 (get_foo_from_db)
              9 LOAD_FAST                0 (request)
             12 LOAD_ATTR                1 (blah)
             15 CALL_FUNCTION            1
             18 STORE_FAST               1 (foo)
             21 JUMP_FORWARD             0 (to 24)

バイトコードの実行ごとにスレッド切り替えが発生する可能性があるためfoo 、テスト後に別のスレッドが変更される可能性があります。

于 2013-03-12T15:39:47.003 に答える
3

いいえ、あなたは 2 つの点で間違っています。

まず、ここでは「スレッド」の使用が少し曖昧です。サーバーの構成方法に応じて、Django はスレッドまたはプロセス、あるいはその両方を使用してサービスを提供できます (完全な説明については、mod_wsgi のドキュメントを参照してください)。プロセスごとに 1 つのスレッドがある場合は、各プロセスでモジュールのインスタンスを 1 つだけ使用できることを保証できます。しかし、それはその構成に大きく依存しています。

それでも、要求/応答サイクルごとにその関数が「1 回だけ」呼び出されるわけではありません。これは、プロセスの存続期間がそのサイクルとはまったく無関係であるためです。プロセスは複数のリクエストに対して持続するため、変数はそれらのすべてのリクエストに対して持続します。

于 2013-03-12T15:42:11.473 に答える