Doge log

Abby CTO 雑賀 力王のオフィシャルサイトです

Spawningの話

一部で話題のSpawning
Spawning · PyPI
速いだの遅いだのなんか揉めてたけどどうなったのか。

とりあえず中でやってる事のメモ

  1. socketをbind,listenまでする(rangeで8回繰り返す意味がよくわからなかった)
  2. num_processの指定数分だけプロセスを作りにかかる
  3. 親子で通信する用にpipeを生成
  4. fork
  5. fork後、execveでプロセスを上書きする(ここで親でlistenしているfdを渡して子でacceptしまくる)
  6. processpool_workersを設定している場合
    1. 親子でデータをやり取りするためtempfile作成
    2. プロセスPool生成
    3. workerの生成時にtempfileをmmap。pipeをread、write通知用に2本張る
    4. worker(process_child.py)をexecveで生成
    5. worker間はtempfile、pipe経由でやり取りする(この辺がぐちゃぐちゃな気がする)
  7. threadpool_workersを設定している場合
    1. 基本eventletのtpoolにおまかせ(native thread poolに放り込む)

あと

  1. 開発モードでファイル監視してreloadする仕組みがある
  2. 開発モードではない場合、無駄にsvnのリビジョンを監視してreloadする仕組みがある

基本的にexecveで子プロセスを上書きする方法。
(どうせ上書きするならvforkとかの方がいいのかも知れないけどpythonからは叩けない。所詮最初だけだしみたいな感じか)
コードベースなんかごにょごにょせず割り切っている感じ。
(forkでコードがぐちゃぐちゃになるとメンテがめんどいからか?)
上書きするプロセスのコマンドライン引数でfdなどを渡し、そこから連携する。

fd dispatchでもいい気もするけどやってないのは重いからなのかも。
(でもちょっと前fd dispatchでうまく動かなかったな、そーいえば)

とりあえずprocesspool_workerのコードがキモイ。
使いたくない感じ。

あと、eventletを使うならばpyeventをインスコしてると優先して使ってくれるのでインスコをおすすめする。

eventlet/api.py
def get_default_hub():
    """Select the default hub implementation based on what multiplexing
    libraries are installed. Tries libevent first, then poll, then select.
    """
    try:
        import eventlet.hubs.libevent
        return eventlet.hubs.libevent
    except ImportError:
        pass

    import select
    if hasattr(select, 'poll'):
        import eventlet.hubs.poll
        return eventlet.hubs.poll
    else:
        import eventlet.hubs.selects
        return eventlet.hubs.selects

多分そのうちpython2.6のkqueue、epollのHubが実装される...かなあ。
(pyeventより速いように感じる)