2012-01-09 7 views
7

私は、機械化とスレッディングを使ってウェブサイトに接続して作業するために使用する約50のクラスを書きました。それらはすべて同時に動作しますが、お互いに依存しません。つまり、1クラス - 1ウェブサイト - 1スレッドを意味します。コードの多くは各クラスで繰り返されます(しかし、一部のサイトでは、メソッドの途中で取得されたデータを追加処理する必要があるため、引数を渡すためにクラスを1つにするには十分ではありません) - 「ログイン」のように - 他人が必要としないかもしれない)。私が言ったように、それはエレガントではない - しかし、それは動作します。言うまでもなく、各Webサイトのアプローチに1つのクラスを使用せずに、これをどのように書くか全推奨事項を歓迎します。各クラスの追加機能や全体的なコード管理を追加するのは大変な作業です。どのようにスレッドのPythonコードのメモリ使用量を減らすには?

しかし、私たちはおよそ400メガバイトの利用状況を見ている50個の実行中のスレッドを持つように、各スレッドは、8メガバイトのメモリほどかかりますことを、分かりました。私のシステムで動作していたのであれば問題はありませんが、1GBのメモリしか搭載していないVPSで動作しているので、問題になり始めています。メモリ使用量を減らす方法を教えてもらえますか、複数のサイトを同時に使用する方法はありますか?

私はそれはメモリ、または何か他のものを使用している私のアプリケーションの変数に格納されたデータだかどうかをテストするためにこのクイックテストのpythonプログラムを使用していました。次のコードでわかるように、sleep()関数の処理だけですが、各スレッドは8MBのメモリを使用しています。

from thread import start_new_thread 
from time import sleep 

def sleeper(): 
    try: 
     while 1: 
      sleep(10000) 
    except: 
     if running: raise 

def test(): 
    global running 
    n = 0 
    running = True 
    try: 
     while 1: 
      start_new_thread(sleeper,()) 
      n += 1 
      if not (n % 50): 
       print n 
    except Exception, e: 
     running = False 
     print 'Exception raised:', e 
    print 'Biggest number of threads:', n 

if __name__ == '__main__': 
    test() 

私はこれを実行すると、出力は次のとおりです。

50 
100 
150 
Exception raised: can't start new thread 
Biggest number of threads: 188 

そしてrunning = False行を削除することによって、私はその後、シェルでfree -mコマンドを使用して空きメモリを測定することができます。

   total  used  free  shared buffers  cached 
Mem:   1536  1533   2   0   0   0 
-/+ buffers/cache:  1533   2 
Swap:   0   0   0 

実際なぜ私はスレッドあたり約8メガバイトを取っていることを知っている計算する前に、上記のテストアプリケーションの間に使用されたメモリの違いを分割することによって簡単ですアプリケーションが動いているgを開始できる最大スレッド数で割ったものです。

topを見ることで、pythonのプロセスは、メモリの約0.6%を使用していますので、おそらく唯一の割り当てられたメモリです。

+0

メモリは何を占めていますか?私はあなたがサイトから抽出したデータだと推測しています。その場合、おそらく実行スレッドの数を制限することができないほど多くはありません。 –

+0

どのように正確にメモリ使用量を測定しますか?私は、それらの8MBがそれぞれのスレッドに本当に割り当てられていないと思います。それらの8MBの大部分はスレッド間で共有されるかもしれません(ちょうど推測..)? – Frunsi

+0

Demianとfrunsi、私はあなたの質問の両方に答えるために私の質問を編集しました。ありがとう! – Gargauth

答えて

4
+0

これです。リソース管理が問題になっている場合は、スレッドプールがあり、プール制限を調整するだけです。 –

+0

ありがとう! Geventは私が探していたものです。 – Gargauth

0

私はPythonの熟練者ではありませんが、アクティブなスレッドの総数を制御するスレッドプールをいくつか持っていて、前のスレッドで終了したスレッドに「要求」を渡します。要求は完全なスレッドオブジェクトである必要はなく、要求が何であれ完了するのに十分なデータです。あなたがウェブサイトにpingを実行し、N個のスレッドを持つスレッドプールのAを持っているので、あなたはまた、それを構造化することができ

データが取得されると、YのスレッドがデータをバリバリとプールBを通すために、データを、それを引き渡します。

2

「リクエストごとに1つのスレッド」を使用すると、多くのユースケースでOKで簡単です。しかし、多くのリソースが必要になります(経験したように)。

より良いアプローチは、非同期のものを使用することですが、残念なことにはるかに複雑です。

この方向にいくつかのヒント:ThreadPoolExecutor example

+0

ありがとう、大変感謝しています。私は以前Twistedについて読んでいましたが、悲しいことに私はそれについてはあまりよく分かりません。見た目では機械化はできません。私は機械化をasyncoreで動作させることができるかどうか見ていきます。 – Gargauth

+0

結局のところ、「完璧な」ソリューションは、CPUコアごとに1つのスレッド(タスクの処理に使用するスレッド)と非同期IOの1つのスレッドプールを組み合わせたものです。実用的な解決策は、実際のアプリケーションコードに依存します。たぶん、 'select'に基づく簡単な解決策でさえ、あなたのためにやってくれるでしょう。 – Frunsi

+1

これは次のことを意味します:あなたのスレッドでは、たくさんのリクエストを送信し、適切なソケットで 'select'するループを入力し、入ってくるデータを1つずつ処理します。結局のところ、OSはとにかくソケットIOを気にするので、できるだけ効率的な方法でOSとインターフェースすることがあなたの仕事です。 – Frunsi

1

ソリューションは、このようなコードを置き換えることです:

  • が非同期的なアプローチを試してみたPython 2.xの上futuresをインストールします。 。
    2)何か起こるのを待ちます。
    3)他の操作をします。このようなコードで

    1)が何かをします。
    2)何かが起きたときに何か他のことが起こるように整理します。
    3)完了。どこか別の

    、あなたはこれを行う、いくつかのスレッドを持っている:

    1)が起こるために何かを待ちます。
    2)何が起こったかを処理します。
    3)手順1に進みます。

    50件が発生するのを待っている場合、50個のスレッドが周りに座っていて、50個の事態が発生するのを待っています。 2番目のケースでは、50個のうちのいずれかを実行する必要があるスレッドを1つ待ちます。

    したがって、スレッドを使用して1つのことが起こるのを待つことはできません。代わりに、そのことが起きたときに、他のスレッドが次に行う必要があるものを実行するように配置します。

  • 関連する問題