Djangoで時間のかかる処理をスレッド化して逃げる方法

Webアプリケーションを作る者にとって、プログラム中でフォーク(Fork)したりスレッド(Thread)を利用するシーンというのはそうそうない。
基本は一連の処理を上から下に流すだけで完了する物を書いていけば出来上がるからだ。

ただ、たまに出くわす。

例えば、超BIGなCVSをねじ込まれて「もうらめぇ」的なやつ。
あまりに長い時間がかかってしまうため、Apacheからタイムアウトを喰らってしまったり、
それ以前にお客さんがあまりに長い処理に辟易したりする。

その場合に考えられるのがフォークやスレッドだ。
今回はそういった時間がかかる処理をスレッドを使って逃げてみた。

「スレッドを選択した理由としてはDjango中でフォークってなんかこわくね?何起きるかわかんね」という理由。
一応フォークも試したみたところ、フォークしたプロセスがが起った後に、「Port already in use」といったエラーが出た。
たぶん・・・やばげ。

というわけでスレッドにレッツトライ。

1.大体はView中で重い処理をやってる
Djangoの場合はMVCではなく、MVT。MVCのC、ようはコントローラ部分はViews.pyに書き連ねる。

例えば、ここでアホな処理をやって重くしてみる

# Create your views here.
from django.shortcuts import render_to_response
import threading

def test(request):
 for x in range(1,1000000):
  print "%s : hoge" % (x)

 return render_to_response('test.html', )

もちろんこいつは重い。回すと15秒くらいかかる。
昨今のWebになれつつある客がコレをみたらきっと「おめーよハゲ」と言う。

じゃあ実際に、この重い部分をスレッドにして動かしてみる
上のコードを以下のように書き換えてみる。

from django.shortcuts import render_to_response
import threading

def test(request):
 t = threading.Thread(target=_testThread)
 t.start();
 return render_to_response('test.html', )

def _testThread():
 for x in range(1,1000000):
  print "%s : hoge" % (x)

上記のコードを動かすと、_testThreadを処理した状態が持続したまま "render_to_response" が動き、ブラウザにレスポンスが返る。

あとは、Ajax等つかってテクれば処理が完了したことをユーザーに知らせるような動きも作れるはず。

でも不安が残った。あまりフォークやらスレッドに詳しくないので「・・これ処理終わったらどうなるの?」という点。
もしかしたらスレッドが残り続けてメモリを喰っていくとかそんな話ない?みたいな。

というわけで、調べてみた。
実行環境はMac OS Xなので、Xcode付属の"Thread Viewer.app"を利用。動き的にはこんな感じになった

・・・はっつけようとおもったらビデオ木が文字化けしてMovie選択できねぇ。
なにやってんのはてな。マカーいるだろ中に。

で、問題なくスレッドは消え失せているので大丈夫そう。だと思う。
ブラウザ画面のhogehogeが変わらないのは、templateにhogehogeと書いてあるだけなので、リロードしてもhogehogeが表示されているため。

何はともあれこれで俺は助かった。

参考文献 : http://www.artfulcode.net/articles/threading-django/ (Threading in Django)

問題は、参考文献だとsetDaemonしてるんだけど、無くても動く。つか単一スレッドだからsetDaemonいらないんじゃないか?