抽象的問題:約250,000ノードのグラフがあり、平均接続数は約10です。ノードの接続を見つけるのは長いプロセスです(たとえば、10秒)。ノードをデータベースに保存するのにも約10秒かかります。ノードがデータベースにすでに存在するかどうかを非常にすばやく確認できます。同時実行を許可しますが、一度に10を超える長いリクエストがない場合、グラフをトラバースして、最高のカバレッジを最も速く取得するにはどうすればよいでしょうか。
具体的な問題:ウェブサイトのユーザーページをスクレイプしようとしています。新しいユーザーを見つけるために、私は既知のユーザーから友達リストを取得しています。グラフの約10%を既にインポートしましたが、サイクルでスタックしたり、ノードが多すぎてメモリを使いすぎたりします。
私の現在の実装:
def run() :
import_pool = ThreadPool(10)
user_pool = ThreadPool(1)
do_user("arcaneCoder", import_pool, user_pool)
def do_user(user, import_pool, user_pool) :
id = user
alias = models.Alias.get(id)
# if its been updates in the last 7 days
if alias and alias.modified + datetime.timedelta(days=7) > datetime.datetime.now() :
sys.stderr.write("Skipping: %s\n" % user)
else :
sys.stderr.write("Importing: %s\n" % user)
while import_pool.num_jobs() > 20 :
print "Too many queued jobs, sleeping"
time.sleep(15)
import_pool.add_job(alias_view.import_id, [id], lambda rv : sys.stderr.write("Done Importing %s\n" % user))
sys.stderr.write("Crawling: %s\n" % user)
users = crawl(id, 5)
if len(users) >= 2 :
for user in random.sample(users, 2) :
if (user_pool.num_jobs() < 100) :
user_pool.add_job(do_user, [user, import_pool, user_pool])
def crawl(id, limit=50) :
'''returns the first 'limit' friends of a user'''
*not relevant*
現在の実装の問題:
- すでにインポートしたクリークでスタックするため、時間が無駄になり、インポートするスレッドがアイドル状態になります。
- 彼らが指摘されるにつれて、さらに追加されます。
したがって、完全な書き直しだけでなく、わずかな改善も歓迎します。ありがとう!