Home > Archives > 2009-09
2009-09
曽爾村に帰省
- 2009-09-25 (Fri)
- Uncategorized

十年ぶりぐらいに父親の実家(奈良県宇陀郡曽爾村)に帰省しました。自然しかない!サマーウォーズみた直後だったので、ちょっとテンションあがりました。草刈りのお手伝いとかしてきました。
太田家

縁側

彼岸花

とんぼ

牛

すすき(曽爾高原)

- Comments: 0
- Trackbacks: 0
Twinado = Tornado + async-python-twitter
- 2009-09-23 (Wed)
- Uncategorized

Twinadoという携帯向けのTwitterクライアントを書いてみました。日常的に使えるレベルにはなっていると思います。
特徴としては最近Facebookが公開したTornadoというフレームワークを使って、Twitter API呼び出しが全て非同期に行われている点です。なので、コネクション数が増えても高速に動くはずです。現状DoCoMo P905iでしか動作確認していません。
きっかけとしては、最近Perl界隈で非同期処理が流行っているのを見て、楽しそうだと思っていたところに、Tornadoが公開されたので、少し使ってみるかと思い立った事です。Tornadoについては以下を参考にして下さい(日本語訳、お疲れ様です!)。
Tornadoの特徴は、リクエストハンドラ内でHTTPリクエストを非同期に発行出来る事です。これによって、サーバー側でのネットワークの待ち時間を減らし、その間に別のリクエストを処理する事が出来ます。以下のサンプルコードは、FriendFeedのAPIを非同期で取得している例になります。取得終了時にon_response関数が呼ばれます。
class MainHandler(tornado.web.RequestHandler):
@tornado.web.asynchronous
def get(self):
http = tornado.httpclient.AsyncHTTPClient()
http.fetch("http://friendfeed-api.com/v2/feed/bret",
callback=self.async_callback(self.on_response))
def on_response(self, response):
if response.error: raise tornado.web.HTTPError(500)
json = tornado.escape.json_decode(response.body)
self.write("Fetched " + str(len(json["entries"])) + " entries "
"from the FriendFeed API")
self.finish()
で、何か作ろうと思って、激しく外部APIアクセスするものって何かなと思ったところ、Twitterクライアントしか思いつかなかったので、作る事にしました。PythonのTwitterクライアントライブラリ「python-twitter」とTornadoに付属しているAsyncHTTPClientを密結合させました。
変更後のソースはgithubにおいてあります。今のところ、一部の関数のみ非同期呼び出しに対応しています。差分を見て頂くと分かりますが、_FetchUrlAsync関数が肝です。
APIの非同期呼び出しは以下のように書けます。GetUserコマンドに渡しているasync_callbackというのがポイントです。読み込みが終わった瞬間に引数で渡した関数を呼び出してくれます。on_response関数ではAPIで取得したUserクラスのインスタンスが渡って来ます。
class UserMainHandler(tornado.web.RequestHandler):
@tornado.web.asynchronous
def get(self, username, password):
try:
api = async_twitter.Api(username, password)
api.GetUser(user = username,
async_callback = self.async_callback(self.on_response))
except:
self.write("twitter api failed")
print sys.exc_info()
self.finish()
def on_response(self, user):
if user == None:
self.write("twitter api failed")
self.finish()
return
self.do_render(user)
def do_render(self, user):
self.render("tpl/user_main.html",
user = user)
この辺でかなり満足し切ったのですが、適当に機能を足して、冒頭で紹介したTwinadoという携帯向けのTwitterクライアントを書いてみました。
Tornadoで書いてみた雑感ですが、コールバックベースの非同期処理は記述が面倒臭すぎます。特にAPIを複数回呼びだしたりする必要の有る処理なんかは、コールバック関数をその都度作らないといけない。
また結果を引き回すために関数のcurry化をしたいのだけど、pythonだとfunctoolsというモジュールで明示的に関数を作ってやる必要が有ったり、楽とは言えない感じです。関数型言語だと大分マシにはなるけど、根本的解決じゃ無い気がします。
エラー処理も、結構問題です。メソッド内で起こったエラーをコールバック内に伝える必要があるため、必然的にオブジェクトを引き回す必要が有ります。
かと言って条件引数引き回すのもなんだかなぁ…。
- Comments: 2
- Trackbacks: 3
jemallocの_malloc_preforkのバグ?
- 2009-09-17 (Thu)
- Uncategorized

前エントリの件に関連して、glibcのmallocはpthread_atforkを呼んでるから大丈夫だよね的な話がkosakiブログに追記されていたので、他のmallocはどうなんだろうとjemallocを読んでみた。で、バグっぽいのを発見。ソースは以下。
ここでpthread_atforkを呼んでいる。
以下のmalloc_prefork関数が呼ばれるのだが、arenas_lockをunlockしている。
malloc_preforkがarenas_lockをunlockした瞬間に、他のスレッドがlockして解放しないままforkに到達したら、malloc_postforkでデッドロックする気がする。
P.S
バグ報告しました。
- Comments: 0
- Trackbacks: 0
Java ProcessBuilderでデッドロック
- 2009-09-15 (Tue)
- Uncategorized

id:nobu-qが踏んだバグ。Twitterにて、kosaki先生に凄く色々アドバイスを頂いた。革命の日々の1000エントリ目のネタゲット!
やりたいこととしては、C++のマルチスレッドプログラムから、HDFS(Hadoop Distributed File system)にアクセスしたい。そのために、libhdfsを使用している。
HadoopはJavaで記述されているために、libhdfsは内部でJavaのコードを呼び出している。このJavaのクライアントライブラリが、ユーザー名などを取得するために”whoami”コマンドを呼び出しており、fork(2)を行う。その際にデッドロックが起きていた。
コードの階層は次のようになる。mallocの実装には、tcmalloc 1.2を使用していた。
C++ Server
C++ libhdfs
Java HDFSClient
Java ProcessBuilder
JavaVM
JavaVM C Layer
tcmalloc
デッドロックが起こっている箇所は、tcmallocの内部だった。よくよく調べてみると、Java VMがfork(2)とexec(2)の間に、親プロセスが開いている全てのファイルディスクリプタを閉じるために/proc/self/fdをopendir(3)している。ここでmallocが呼ばれている。
- UNIXProcess_md.c
- bug 6336770
最初は、tmallocがpthread_atforkでmutexをきちんと処理していないので、こちらが悪いと思っていた。が、kosaki先生によるとそもそもfork(2)
とexec(2)の間ではasync-signal safeな関数しか呼んではいけないらしい(これはPOSIXの仕様???)。mallocの実装は関係が無い。
解決策としては、まずアプリを動かすためだけなら、Hadoop側を改変してProcessBuilderを使わないようにすれば良い。
JVMの方を直すには、一番理想的にはFD_CLOSEEXECを使う方法だけど、これは変更範囲が大きそうだし漏れが有りそう。
なので、async-signal safeな関数だけを用いて、現在開いている全てのファイルディスクリプタ番号を取得する方法が必要となる。で、どうするかを今調べているところ。SolarisとかBSD系でも動かないといけないので、どうしたもんかなあ。
- Comments: 0
- Trackbacks: 0
MPICH2内のコードを変える時のTIPS
- 2009-09-02 (Wed)
- 研究


MPICH2のコードを1箇所いじると、やたらビルドに時間がかかって鬱陶しい…と言ってたら、色々切ると良いというのを教えてもらった。
$ ./configure --enable-romio --disable-mpe --disable-f77 --disable-f90 --disable-cxx --enable-dependencies
特にMPEと各種言語サポートを切ると、ビルド時間が飛躍的に変わります。誰の役にも立たないTIPSエントリ。
- Comments: 0
- Trackbacks: 0
Home > Archives > 2009-09
-
- February 2010
- December 2009
- November 2009
- October 2009
- September 2009
- August 2009
- July 2009
- June 2009
- May 2009
- April 2009
- March 2009
- February 2009
- January 2009
- December 2008
- November 2008
- October 2008
- September 2008
- August 2008
- July 2008
- June 2008
- May 2008
- April 2008
- March 2008
- February 2008
- January 2008
- December 2007
- November 2007
- October 2007
- September 2007
- August 2007
- July 2007
- June 2007
- May 2007
- April 2007
- March 2007
- February 2007
- January 2007
- December 2006
- November 2006
- October 2006
- September 2006
- August 2006
- July 2006
