eventlet kqueue hub
先日のAppleのイベント用にこんなのを作って、動かしたりしてたいました。
中身はテキトーに書いたeventletベースCometサーバをFreeBSDで動かしてるのですが、eventletはkqueueのhubが無いのでちょっと負荷が心配になった。ので、kqueueのhubをでっち上げた。例によってテストは無いけど、一晩動いてたのでこの方向でいいのかしら。
kqueueバージンだったので、誰か優しく手ほどきしてください。
written by shn, on Jan 29, 2010 2:14:00 PM.
先日のAppleのイベント用にこんなのを作って、動かしたりしてたいました。
中身はテキトーに書いたeventletベースCometサーバをFreeBSDで動かしてるのですが、eventletはkqueueのhubが無いのでちょっと負荷が心配になった。ので、kqueueのhubをでっち上げた。例によってテストは無いけど、一晩動いてたのでこの方向でいいのかしら。
kqueueバージンだったので、誰か優しく手ほどきしてください。
Tagged as: Python, eventlet, kqueue | 2 comments
written by shn, on Jan 18, 2010 4:47:00 PM.
嫁の人がタダ券をもらったので、いまさら2012を見てきました。
3分に一回つっこみどころ(ニュートリノが核粒子?に変化する!、とか)がある面白い映画でした。 嫁の人が本編前の予告編だと思って「うわぁ ひでぇなこの映画」とか言ってたら、本編だったという感じです。
ネタバレなんですが、僕が一番気に入ったつっこみどころは、方舟のチケットに一席10億ドル(ユーロです、といいつつドルだったりする。相手によって値段が違う)といいつつ、後半ででてきた「船の建設費用は数10億ドル…」というセリフ。世界が終わるっていうのにぼろ儲けしてる奴がいるよ!と楽しかったです。
AVATARもそうなんですが、ハッピーエンドっぽいラストなんですけど、あの後本当の地獄が始まると思います。
written by shn, on Jan 17, 2010 6:05:00 PM.
eventletづいてるので、Cometサーバを書いてみたよ。
tinycomet.py at master from shnjp's tinycomet - GitHub
eventlet.wsgiを使って、200行ぐらいで簡単なのが書けました。楽しいですね。
python tinycomet.pyで起動して、 /update/<UUID>にPOSTするとデータを作成
% curl -v 'http://127.0.0.1:8090/update/hogehoge' -d mogemoge
...
< HTTP/1.1 201 Created
< X-Tc-Timestamp: 2
< Content-Length: 0
...
受け取るには、/wait/<UUID>
% curl -v 'http://127.0.0.1:8090/wait/hogehoge'
...
< HTTP/1.1 200 OK
< Content-Type: application/octet-stream
< X-Tc-Timestamp: 4
< Content-Length: 7
...
mogemoge
waitにsince=<timestamp>をつけると、その時間になるまで待ちます。
各レスポンスのヘッダにあるX-TC-Timestampが、そのデータの最終更新時刻になります。
timestampは論理時間なので、実世界の時刻とは関係ありません
% curl 'http://127.0.0.1:8090/wait/hogehoge?since=4' &
[1] 97027
# waitに入る
% curl -v 'http://127.0.0.1:8090/update/hogeoge' -d fugafuga
fugafuga[1] + done ....
ほかに、waitにtimeout=[timeout:float]を与えると、timeout秒待って408 Request Timeoutを返します。
また、updateにfinished=1を与えると、次のwaitが終わった後にデータを消します。またcontent_type=[mimetype]でContent-Typeを指定できます。デフォルトはapplication/octet-stream
eventletのdefault hubからthread safeじゃないという理由でpyeventが外されていたのだけど、今回はsingle threadなので試してみた。 しかしうまくimport出来ないので諦め。trunkも、配布バージョン(2007年!!)もだめじゃった。
python2.6からkqueueが使えるそうなので、自分でHubを書くのがよいのかな。eventlet自体もtrunkは結構変わっているので見ないといけなさげ
waitのところは、グローバルなConditionを作って
# wait側
with _update_lock:
while data.last_update <= since:
_update_lock.wait(timeout)
# update側
with _update_lock:
_update_lock.notify_all()
とやっているので、捌くdataの数が増えると破綻すると思う。dataごとにイベントを持たせて、WaitForMultipleObjects()的なことがしたいのだけど、この枠組みではどうやるんだろう。オシエテエライヒト
/wait_multiはmultipart/*を吐くコードを書くのが面倒なので実装していない。
Tagged as: Python, comet, eventlet | 0 comments
written by shn, on Jan 16, 2010 8:45:00 PM.
eventletっていうライブラリが僕好みの匂いを発していたので遊んでいる。 gearmanを使って、ブログのURLを与えたらそこのFeedのリストを返すってWorkerを書いていたので、それをeventlet化してみよう。
まず、gearmanのeventlet化、gearmanのライブラリにはpure-pythonのやつを使っていたのでさくっと行けた。
green_gearman.py
from eventlet import patcher
from eventlet.green import socket, select
for mod in ['worker', 'connection']:
patcher.inject('gearman.%s' % mod, globals(),
('socket', socket),
('select', select)
)
del patcher
eventletにはpatcherというざっくりしたモジュールがあって、これを使うと指定したモジュールのglobalsを置き換えてくれる。これでいいんかなっていうぐらい簡単。
試しにecho serverを書いてみる。
from eventlet import coros, api
from green_gearman import GearmanWorker
def echo_func(job):
print api.getcurrent(), job.arg
time.sleep(5.)
def main():
pool = coros.CoroutinePool(max_size=200)
waiters = []
for idx in range(10):
worker = GearmanWorker(['0.0.0.0:4730'])
worker.register_function('echo', echo_func)
waiters.append(pool.execute(worker.work))
for w in waiters:
w.wait()
main()
gearmanのprotocolは同時に1ジョブしか処理できないっぽいので、とりあえず10個ぐらい突っ込んでみる。
gearman -h localhost -p 4730 -s -f echo hogehogeを20個ぐらい飛ばしてみた所、
<greenlet.greenlet object at 0x804137f30> hogehoge
<greenlet.greenlet object at 0x804127c90> hogehoge
<greenlet.greenlet object at 0x804137db0> hogehoge
<greenlet.greenlet object at 0x804137e10> hogehoge
ってなってるので、なんかまぁそれっぽくなってる気がする。こんなコードじゃよくわからんな… これで良いのでしょうか。
さて肝心のWorkerもこれにのせたいのだが、urllib2を使っていたので、代わりにfrom eventlet.green import urllib2に代えるだけっぽい(まだやってない…)。
んでつらつらコード見てたんだが、今のところ(eventlet 0.9.2)はlibeventサポートがdisabledされているようで、ちょっとがっかり。
eventlet化する場合、全てのIOをこれにしないとブロックが発生してみんな止まることになっちゃうのだけど、MySQL周りとかをeventlet化するのはめんどくさそうなのでアレでアレしてアレですね。
Tagged as: Python, eventlet, gearman | 0 comments
written by shn, on Jan 12, 2010 1:13:00 AM.
去年の暮れにほってんとりになってた採用問題が公開されたのでやってみた。
というのも、当初問題文を読み違えていて(格子マップじゃなくて、連続的なマップだと思ってた)、「各経路点を取って最短経路問題ですかねぇ」とか「僕だったら、答えをASCIIにプロットするのに25分かかるなぁ」とか頓珍漢な事を言っていたのが恥ずかしかったからです。 問題文を読んでないので応募以前の問題ですね。ここらへんを参照
んで、最適解法を知った上でコード書いたのに40分かかりました…
さて、僕自身も経営者の端っこなので、いろいろ思う点がありました。
まず、こういうアルゴリズム系の問題を出すことでGoogleの使い方を知らない奴を簡単に落とせるのがわかったのは参考になりました。 というのも、問題解決について求められるのはその時点での知識ではなく、最終的に許される時間の中で解決できるかという点だからです。 また、実務をこなす上でのほとんどの細かい問題に関しては、それまで世界の誰もそんな問題に直面したことが無い!なんて事は殆どないはずなので、そういうった問題を確実に解けるのか?というのは重要なポイントだと思います。
また、話には聞いていましたが、それぐらいの人材が我々のような(勝手に一緒にしちゃいましたが)零細IT企業にふらっと応募することは少ないのだなというのも参考になります。そういう点で、公募する場合には根気よく採用を続ける必要がありそうなので、あんまり応募者をディスると今後の応募に影響してしまいそうな点は気になります。
このエントリに応えると、小さな企業が人を取った場合、新人の戦力が30で今の戦力と足して130だ!、というよりも、新人がしちめんどくせーことやってくれるお陰で俺らが強まって足して150だ!みたいな気概でいるのがいいんじゃないのかなーと思います。
イメージとしてはこんな感じ
以下がコード。Pythonです。:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import sys
CELLMAX = 9999
def main(input):
m, start, goal = load_map(input)
solve(m, start, goal)
print_result(m, goal)
def load_map(input):
start, goal = [], None
d = {
'*': -1,
' ': CELLMAX,
'S': 0
}
m = []
for l in input:
m.append([d.get(ch, ch) for ch in l.rstrip()])
for y in range(len(m)):
for x in range(len(m[y])):
if m[y][x] == 0:
start.append((x, y))
elif m[y][x] == 'G':
goal = (x, y)
return m, start, goal
def solve(m, start, goal):
cur = 0
while start:
next = []
for c in start:
m[c[1]][c[0]] = cur
for d in [(-1, 0), (0, -1), ( 1, 0), ( 0, 1)]:
if m[c[1]+d[1]][c[0]+d[0]] > cur:
next.append((c[0]+d[0], c[1]+d[1]))
start = next
cur += 1
if goal in start:
m[goal[1]][goal[0]] = cur # syoboi
return
if goal not in start:
raise RuntimeError, u'とけないよ'
def fill(m, c, x):
filled = []
for d in [(-1, 0), (0, -1), ( 1, 0), ( 0, 1)]:
if m[c[1]+d[1]][c[0]+d[0]] > x:
m[c[1]+d[1]][c[0]+d[0]] = x
filled.append((c[0]+d[0], c[1]+d[1]))
return filled
def print_result(m, goal):
c = goal
while True:
check = m[c[1]][c[0]] - 1
if check == -1:
break
m[c[1]][c[0]] = '$'
for d in [(-1, 0), (0, -1), ( 1, 0), ( 0, 1)]:
if m[c[1]+d[1]][c[0]+d[0]] == check:
c = (c[0]+d[0], c[1]+d[1])
break
else:
raise RuntimeError
m[goal[1]][goal[0]] = 'G' # syoboi
d = {
-1: '*',
0: 'S',
'$': '$',
'G': 'G',
}
for l in m:
print ''.join(d.get(ch, ' ') for ch in l)
if __name__=='__main__':
main(sys.stdin)
「最短性のチェック」というのは、(コードの外で)アルゴリズムの証明をせよ、という意味だろうか?基本的にダイクストラ法を格子マップでやっているので、最短性はダイクストラ法の証明となると思うのだけど。
って岡嶋さんてスウィフトの関係者なのか!
あとはっちゅう君バジョナップ期待しています!
Categories: 残滓 | 0 comments
written by shn, on Jan 3, 2010 12:38:00 AM.
弊社サービスを引っ越ししたりせなあかんなーと思いつつ、US-West初め。 いくつかはまった。
AMI作るときにはまった。 FirefoxのAddonのアレがUS-Westに対応しておらず、うっかりBucketを作るとUS-Eastに行っちゃう。 コマンドラインから頑張るのが面倒だったので、Bucket Explorerとかいうのを使って作成。
--region us-westを付ける。API-Toolの引数にus-westを付ける。付けないとeastにデフォルトで行くのかなこれ。
export EC2_URL=https://us-west-1.ec2.amazonaws.comにするとデフォでwest見に行くのかな。試してはいない。
Tagged as: aws | 0 comments
Proudly powered by Zine.