2009年12月24日木曜日

client part

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
んで、前々回のエントリのクライアントサイド。submitでreturn falseして、それ以上のsubmit動作を抑制しなきゃいけないことを忘れていたのは公然の秘密。

<html>
<head>
<title>comet tests</sample>
<!--
Copyright 2009 Noriyuki Hosaka bgnori@gmail.com
-->

<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load("jquery", "1.3.2");
</script>

<script type="text/javascript">
function update(){
$.ajax({
url: "http://localhost:3165",
dataType : "jsonp",
type: "GET",
cache : false,
data : {},
timeout: 60*1000,
success : function (data, dataType){
$("#chat").append($("<div>" + data.who + ":" + data.message + "</div>"));
update();
},
error : function(){
alert("error");
}
});
};

$(document).ready(function(){
$("form").submit(function(){
d = $('#message').val()
$.ajax({
url:"http://localhost:3124",
dataType : "jsonp",
//type: "POST",
type: "GET",
cache : false,
data : {message:d},
timeout: 60*1000,
success : function (data, dataType){
$('#message').val('');
},
error : function(){
alert("error");
},
});
return false;
});
$("#chat").append($("<div>this is chat area.</div>"));
update();
});
</script>

</head>
<div id="chat">
<div> 0 </div>
</div>

<form >
<input type="text" id="message" />
<input type="submit" />
<input type="reset" />
</form>
<body>
</body>
</html>

chrome for linux

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
LSBのバージョンが3.2である必要があるといわれたが、CentOSでは3.1でしかないので無理矢理いれてみた。

[nori@shinano]~% sudo rpm -U --force --nodeps google-chrome-beta_current_x86_64.rpm


ランチャのプロパティを見ると起動のpathが

/opt/google/chrome/google-chrome %U

になっているが、そんなものは無い。orz

pythonでとりあえずcometしてみた。

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
標準のWSGI refのsimple serverからかっぱいできたhandlerを無理矢理くっつけてみた。
グチャグチャなのだが、恥を忍んで公開。

コアとなるアイディアは、標準のHTTPHandlerはsocketをfileとして読み書きするので、そのファイルをStringIOで差し替え、Protocol:dataReceivedで受け取ったdataをStringIOインスタンス(rfile)にどんどん書いてからHTTPHandlerに渡す。responseに関してはその逆をする(wfile)。


def connectionMade(self):
print 'Subscription::connectionMade'
self.rfile = StringIO.StringIO()#'rb', self.rbufsize)
self.wfile = StringIO.StringIO()#'wb', self.wbufsize)
self.adaptor = WSGIAdaptor(('localhost', 3165), WSGISupportHandler) #ugh!
self.adaptor.set_app(subscribe)
clients.append(self)



class WSGISupportHandler(WSGIRequestHandler):
def setup(self):
self.rfile, self.wfile = self.request


seekして巻戻すのを忘れていたせいでかなり時間を無駄にした。requestの完了をなんらかの方法で検出して、検出できたときにseek(0)してhandlerを呼ぶようにすべきだ(dataReceivedで全部もらえる保証がない為)が、とりあえずは放置。

def handle(self):
self.rfile.seek(0) #UGH! UGH! UGH!
WSGIRequestHandler.handle(self)



#/usr/bin/python

import StringIO

from twisted.internet import reactor, protocol

from SocketServer import BaseServer, TCPServer
from wsgiref.simple_server import WSGIRequestHandler, WSGIServer, demo_app
import cgi

import simplejson

clients = []

class WSGIAdaptor(WSGIServer):
application = None

def __init__(self, server_address, RequestHandlerClass):
print 'WSGIAdaptor:__init__'
BaseServer.__init__(self, server_address, RequestHandlerClass)
#self.socket = socket.socket(self.address_family,
# self.socket_type)
self.server_bind()
#self.server_activate()

def server_bind(self):
"""Override server_bind to store the server name."""
print 'WSGIAdaptor::server_bind'
#TCPServer.server_bind(self)
#HTTPServer.server_bind(self)
self.server_name = 'localhost' # fake
self.server_port = '9999' # fake
self.setup_environ()
self.base_environ['server'] = self

def get_message(self):
return self.message

def set_message(self, message):
self.message = message


class WSGISupportHandler(WSGIRequestHandler):
def setup(self):
self.rfile, self.wfile = self.request

def finish(self):
pass

def handle(self):
self.rfile.seek(0) #UGH! UGH! UGH!
WSGIRequestHandler.handle(self)

def parse_request(self):
print 'raw_requestline', self.raw_requestline
ok = WSGIRequestHandler.parse_request(self)
print "WSGIRequestHandler:parse_request", ok
if not ok:
print 'rfile'
print self.rfile.getvalue()
print 'wfile'
print self.wfile.getvalue()

return ok


def subscribe(environ, start_response):
stdout = StringIO.StringIO()
q = cgi.parse_qs(environ['QUERY_STRING'])
msg = environ['server'].get_message()
value = {'message':msg, 'who':'hogeo'}
j = '%s(%s);'%(q['callback'][0], simplejson.dumps(value))
print >> stdout, j
start_response("200 OK", [('Content-Type','text/javascript')])
return [stdout.getvalue()]


class Subscription(protocol.Protocol):
def connectionLost(self, reason):
pass

def connectionMade(self):
print 'Subscription::connectionMade'
self.rfile = StringIO.StringIO()#'rb', self.rbufsize)
self.wfile = StringIO.StringIO()#'wb', self.wbufsize)
self.adaptor = WSGIAdaptor(('localhost', 3165), WSGISupportHandler) #ugh!
self.adaptor.set_app(subscribe)
clients.append(self)

def dataReceived(self, data):
self.rfile.write(data)

def sendMessge(self, msg):
adaptor = self.adaptor
adaptor.set_message(msg)
peer = self.transport.getPeer()
adaptor.finish_request((self.rfile, self.wfile), peer)
print '=== Subscriver (request) ===='
print self.rfile.getvalue()
print
print '=== Subscriver (response) ===='
print self.wfile.getvalue()
print
self.transport.write(self.wfile.getvalue())

class Subscriver(protocol.ServerFactory):
def buildProtocol(self, addr):
return Subscription()



def publish(environ, start_response):
stdout = StringIO.StringIO()
print 'publish'
q = cgi.parse_qs(environ['QUERY_STRING'])
msg = q['message'][0]
print msg
environ['server'].set_message(msg)
value = {'status': True}
j = '%s(%s);'%(q['callback'][0], simplejson.dumps(value))
print >> stdout, j
start_response("200 OK", [('Content-Type','text/javascript')])
return [stdout.getvalue()]


class Publication(protocol.Protocol):
def connectionMade(self):
print 'Publication::connectionMade'
self.rfile = StringIO.StringIO()#'rb', self.rbufsize)
self.wfile = StringIO.StringIO()#'wb', self.wbufsize)
self.adaptor = WSGIAdaptor(('localhost', 3124), WSGISupportHandler) #ugh!
self.adaptor.set_app(publish)

def connectionLost(self, reason):
pass

def dataReceived(self, data):
self.rfile.write(data) #ugh!
print '=== Publisher ===='
print data
print
peer = self.transport.getPeer()
self.adaptor.finish_request((self.rfile, self.wfile), peer)
msg = self.adaptor.get_message()
for c in clients:
c.sendMessge(msg)
self.transport.write(self.wfile.getvalue())


class Publisher(protocol.ServerFactory):
def buildProtocol(self, addr):
return Publication()


reactor.listenTCP(3165, Subscriver())
reactor.listenTCP(3124, Publisher())
reactor.run()

2009年12月23日水曜日

つまる。

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
どうしたんだろう。ProtocolのsubclassのconnectionMadeがdataReceivedのあとに呼ばれている?!なにが間違っているのやら。


Traceback (most recent call last):
File "/usr/lib64/python2.4/site-packages/twisted/python/log.py", line 51, in callWithLogger
return callWithContext({"system": lp}, func, *args, **kw)
File "/usr/lib64/python2.4/site-packages/twisted/python/log.py", line 36, in callWithContext
return context.call({ILogContext: newCtx}, func, *args, **kw)
File "/usr/lib64/python2.4/site-packages/twisted/python/context.py", line 59, in callWithContext
return self.currentContext().callWithContext(ctx, func, *args, **kw)
File "/usr/lib64/python2.4/site-packages/twisted/python/context.py", line 37, in callWithContext
return func(*args,**kw)
--- ---
File "/usr/lib64/python2.4/site-packages/twisted/internet/selectreactor.py", line 146, in _doReadOrWrite
why = getattr(selectable, method)()
File "/usr/lib64/python2.4/site-packages/twisted/internet/tcp.py", line 362, in doRead
return self.protocol.dataReceived(data)
File "cometd.py", line 114, in dataReceived
self.rfile.write(data) #ugh!
exceptions.AttributeError: Publication instance has no attribute 'rfile'
Subscription::connectionMade


あ・・・methodを上書きして消していた・・・orz

2009年12月22日火曜日

Twistedでcometする一歩目

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
Python:Twistedの短いソースコードのコード(下)を起点にできる限り単純なcometなコードを書こう。

from twisted.internet import reactor, protocol

class MyProtocol(protocol.Protocol):
def connectionLost(self, reason):
pass

def dataReceived(self, data):
print data
self.transport.write('test message\n')
self.transport.loseConnection()

class TCPServer(protocol.ServerFactory):
def buildProtocol(self, addr):
return MyProtocol()

reactor.listenTCP(12345, TCPServer())
reactor.run()


まずは動きを理解するためにそのまま実行。

サーバ側

[nori@shinano]~/Desktop/work/jsboard/comet/sample% python twisted-server.py
hello



クライアント側

[nori@shinano]~/Desktop/work/jsboard/comet/sample% telnet 127.0.0.1 3165
Trying 127.0.0.1...
Connected to shinano.tonic-water.com (127.0.0.1).
Escape character is '^]'.
hello
test message
Connection closed by foreign host.

self.transport.loseConnectionのおかげで切れてしまいます。そこでこれをコメントアウトし、つなぎっぱにしてふたつtelnetを立ち上げてつなげると、つながります。つまりちゃんと多重化されているんです。

これでは何もできないのでtransportやprotocolのメンバを調べます。本家のapi reference

2 Twisted解剖図鑑 を見ながら進めていきます。reactorが差し替えられる云々の話が出てきますが、ここが話が速い。今回はUIがない、デーモンを作るのであまり気にしなくていい。また、ここの例ではlineReceivedのなかでsendResponseしているが、このままではCometにならない。sendResponseに相当するメソッドを、別のタイミング(chat serverならbroadcastするタイミング)で呼んでやらないといけない。HTTP GETをなんらかの形で覚えておいて外部から指定されたタイミングで返す。そのために使えるAPIを探すことになる。

とりあえずはchat serverっぽい動きをするようにしてみた。connectionが切れたときにunregisterされていないのはご愛嬌。

#/usr/bin/python

# from
# http://omake.accense.com/wiki/Twisted%E3%81%AE%E7%9F%AD%E3%81%84%E3%82%BD%E3%83%BC%E3%82%B9%E3%82%B3%E3%83%BC%E3%83%89%E9%9B%86


from twisted.internet import reactor, protocol

host = 'localhost'
port = 3165


clients = []
class MyProtocol(protocol.Protocol):
def connectionLost(self, reason):
pass

def connectionMade(self):
clients.append(self)

def dataReceived(self, data):
print data
for c in clients:
c.sendMessge(data)

def sendMessge(self, msg):
self.transport.write(msg)

class TCPServer(protocol.ServerFactory):
def buildProtocol(self, addr):
return MyProtocol()

reactor.listenTCP(port, TCPServer())
reactor.run()


reactorに何か追加すればよいのだろう。listenTCPの代わりになにかメソッドを追加するか、もしくはほかのサーバと連携するための口としてTCPを使ってしまい、もうひとつProtocolを書く。その中でclientsをなめてsendMessageすればよい。

とりあえず、TCP version

#/usr/bin/python

from twisted.internet import reactor, protocol


clients = []

class Subscription(protocol.Protocol):
def connectionLost(self, reason):
pass

def connectionMade(self):
clients.append(self)

def dataReceived(self, data):
pass

def sendMessge(self, msg):
self.transport.write(msg)

class Subscriver(protocol.ServerFactory):
def buildProtocol(self, addr):
return Subscription()


class Publication(protocol.Protocol):
def connectionLost(self, reason):
pass

def connectionMade(self):
pass

def dataReceived(self, data):
for c in clients:
c.sendMessge(data)

def sendMessge(self, msg):
pass

class Publisher(protocol.ServerFactory):
def buildProtocol(self, addr):
return Publication()


reactor.listenTCP(3165, Subscriver())
reactor.listenTCP(3124, Publisher())
reactor.run()

2009年12月19日土曜日

xorg.conf

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
with ati-driver-installer-9-10-x86.x86_64.run

ati-driver-installer-9-12-x86.x86_64.runはなぜかうまく動かない。


Section "ServerLayout"
Identifier "Multihead layout"
Screen 0 "Screen0" 1920 0
Screen 1 "Screen1" 0 0
InputDevice "Keyboard0" "CoreKeyboard"
EndSection

Section "Files"
EndSection

Section "Module"
Load "GLcore"
Load "glx"
Load "dri"
Load "vbe"
Load "dbe"
EndSection

Section "ServerFlags"
Option "AIGLX" "on"
Option "Xinerama" "on"
Option "Clone" "off"
EndSection

Section "InputDevice"
Identifier "Keyboard0"
Driver "kbd"
Option "XkbModel" "pc101"
Option "XkbLayout" "us"
Option "XkbVariant" "intl"
EndSection

Section "Monitor"

### Comment all HorizSync and VertSync values to use DDC:
Identifier "Monitor0"
VendorName "BenQ"
ModelName "G2220HD"
DisplaySize 480 270
HorizSync 31.5 - 37.9
VertRefresh 50.0 - 70.0
Option "VendorName" "ATI Proprietary Driver"
Option "XaaNoOffscreenPixmaps" "true"
Option "DPMS" "true"
EndSection

Section "Monitor"
Identifier "Monitor1"
VendorName "BenQ"
ModelName "G2220HD"
DisplaySize 480 270
HorizSync 31.5 - 37.9
VertRefresh 50.0 - 70.0
Option "VendorName" "ATI Proprietary Driver"
Option "XaaNoOffscreenPixmaps" "true"
Option "DPMS" "true"
EndSection

Section "Device"
Identifier "RADEON-HD-4850-port0"
Driver "fglrx"
BoardName "ATI Technologies Inc RV770 [Radeon HD 4850]"
BusID "PCI:2:0:0"
Screen 0
EndSection

Section "Device"
Identifier "RADEON-HD-4850-port1"
Driver "fglrx"
BoardName "ATI Technologies Inc RV770 [Radeon HD 4850]"
BusID "PCI:2:0:0"
Screen 1
EndSection

Section "Screen"
Identifier "Screen0"
Device "RADEON-HD-4850-port0"
Monitor "Monitor0"
DefaultDepth 24
SubSection "Display"
Viewport 1920 0
Depth 24
Modes "1920x1080"
EndSubSection
EndSection

Section "Screen"
Identifier "Screen1"
Device "RADEON-HD-4850-port1"
Monitor "Monitor1"
DefaultDepth 24
SubSection "Display"
Viewport 0 0
Depth 24
Modes "1920x1080"
EndSubSection
EndSection

Section "DRI"
Mode 0666
EndSection

Section "Extensions"
Option "RENDER" "ENABLE"
Option "Composite" "Disable"
#http://builder.japan.zdnet.com/news/story/0,3800079086,20365215,00.htm
EndSection

2009年10月16日金曜日

gnubg

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

8618b7a2a5be11dd7f6bf5a4e4746040ac0f5822 is first bad commit
commit 8618b7a2a5be11dd7f6bf5a4e4746040ac0f5822
Author: Superfly_Jon
Date: Thu Sep 17 17:47:49 2009 +0000

Create a Mutex for windows installer

:100644 100644 2960215ee98b671c8905f8a2b3d52300ce822856 01667e68ef61690c5500764cadf314a28e039bbf M gnubg.c

2009年9月5日土曜日

sudo

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
ここより


ユーザパスワードを盗んで誰かにメールする(Ubuntu/Mac)
方法

sudo コマンドを実行した時に要求されるユーザパスワードを盗む.

`read -s x` で文字を表示させずに入力させることができ,その文字列が $x に保存される.それを mail コマンド*1で攻撃者に送信する.ついでに alias を解除する.動作がおかしいと怪しまれるので,入力されたコマンドをちゃんと実行する./usr/bin/sudo とフルパスで指定すれば本当の sudo が使え,-S オプションで標準入力からパスワードを入力できるので echo $x のパイプでさきほど入力されたパスワードをわたし,プロンプトが2回表示されると怪しいので -p "" オプションでプロンプトを表示しないようにする.偽の sudo に与えられた引数は,この本当の sudo に渡されるので,見た目はいつも通りの sudo ができあがる.



sudoを実行するときに尋ねるpasswordをユーザのパスワードにすればいいのではないかということを思った。sudoをパスワード無しにするものよいが、それでは席を離れた瞬間をつかれる可能性があるので。
sudoerのアカウントを奪われることをどのくらいに考えているかにもよるでしょうが、わたしははてしなくrootをとられることに近いと思っているので、こういうのもありかな〜とおもったり。

2009年7月20日月曜日

i7

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
これをconsoleに吐かれてもなぁ・・・。

Message from syslogd@ at Mon Jul 20 02:43:03 2009 ...
shinano kernel: CPU7: Temperature/speed normal
Message from syslogd@ at Mon Jul 20 02:43:03 2009 ...
shinano kernel: CPU5: Temperature above threshold, cpu clock throttled
Message from syslogd@ at Mon Jul 20 02:43:03 2009 ...
shinano kernel: CPU3: Temperature/speed normal
Message from syslogd@ at Mon Jul 20 02:43:03 2009 ...
shinano kernel: CPU1: Temperature above threshold, cpu clock throttled
Message from syslogd@ at Mon Jul 20 02:43:03 2009 ...
shinano kernel: CPU6: Temperature/speed normal
Message from syslogd@ at Mon Jul 20 02:43:03 2009 ...
shinano kernel: CPU0: Temperature/speed normal
Message from syslogd@ at Mon Jul 20 02:43:03 2009 ...
shinano kernel: CPU4: Temperature/speed normal
Message from syslogd@ at Mon Jul 20 02:43:04 2009 ...
shinano kernel: CPU2: Temperature/speed normal

2009年7月19日日曜日

Radeon HD 4850 dual head

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
結局、ドライバがちゃんと入っていなかった。kernel-develが入ってなかったせい。全然体感速度が違います。ドライバが入る前は、旧世代マシンかとおもうほど遅かった。windowの移動には全然反応しないし、スクロールするとカンガルージャンプしてたし。
amdcccもいいですね。windowsちっく。


[nori@shinano ~]$ /usr/bin/glxgears
36545 frames in 5.0 seconds = 7308.920 FPS
45853 frames in 5.0 seconds = 9170.426 FPS
45993 frames in 5.0 seconds = 9198.482 FPS
45945 frames in 5.0 seconds = 9188.717 FPS
X connection to :0.0 broken (explicit kill or server shutdown).
[nori@shinano ~]$ /usr/bin/fgl_glxgears
Using GLX_SGIX_pbuffer
9021 frames in 5.0 seconds = 1804.200 FPS
10117 frames in 5.0 seconds = 2023.400 FPS
11007 frames in 5.0 seconds = 2201.400 FPS
12585 frames in 5.0 seconds = 2517.000 FPS
12573 frames in 5.0 seconds = 2514.600 FPS
11283 frames in 5.0 seconds = 2256.600 FPS
12137 frames in 5.0 seconds = 2427.400 FPS
10573 frames in 5.0 seconds = 2114.600 FPS
12706 frames in 5.0 seconds = 2541.200 FPS
11311 frames in 5.0 seconds = 2262.200 FPS


# Xorg configuration created by system-config-display

Section "ServerLayout"
Identifier "Multihead layout"
Screen 0 "Screen0" 0 0
InputDevice "Keyboard0" "CoreKeyboard"
Option "AIGLX" "on"
Option "Xinemara" "on"
Option "Clone" "off"
EndSection

Section "Files"
EndSection

Section "Module"
Load "GLcore"
Load "glx"
Load "dri"
Load "vbe"
Load "dbe"
EndSection

Section "InputDevice"
Identifier "Keyboard0"
Driver "kbd"
Option "XkbModel" "pc101"
Option "XkbLayout" "us"
Option "XkbVariant" "intl"
EndSection

Section "Monitor"
Identifier "Monitor0"
VendorName "BenQ"
ModelName "G2220HD"
Option "VendorName" "ATI Proprietary Driver"
Option "DPMS" "true"
Option "XaaNoOffscreenPixmaps" "true"
Option "DRI" "true"
EndSection

Section "Monitor"
Identifier "Monitor1"
VendorName "BenQ"
ModelName "G2220HD"
Option "VendorName" "ATI Proprietary Driver"
Option "DPMS" "true"
Option "XaaNoOffscreenPixmaps" "true"
Option "DRI" "true"
EndSection
Section "Device"
Identifier "RADEON-HD-4850-port0"
Driver "fglrx"
BoardName "ATI Technologies Inc RV770 [Radeon HD 4850]"
BusID "PCI:2:0:0"
Screen 0
Option "VideoOverlay" "on"
Option "OpenGLOverlay" "on"
Option "OverlayOnCRTC2" "0"
Option "DesktopSetup" "horizontal"
EndSection

Section "Screen"
Identifier "Screen0"
Device "RADEON-HD-4850-port0"
Monitor "Monitor0"
DefaultDepth 24
SubSection "Display"
Viewport 0 0
Depth 24
Modes "1920x1080"
EndSubSection
EndSection

Section "DRI"
MODE 0666
EndSection

Section "Extensions"
Option "RENDER" "ENABLE"
Option "Composite" "Disable"
EndSection

Section "ServerFlags"
EndSection

2009年7月12日日曜日

RAID

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク




diskが

Bit 5: SMART status check returned "DISK OK" but we found that some (usage or prefail) Attributes have been <= thresh-
old at some time in the past.

を返していたが放置していた。交換するのだが、もう予備がない。この後エラーを返されても、どうにもならない。基本に使うdiskを変えて組み直すしかない。そのためにはおそらくRAIRD cardをもう一枚買って2枚刺してローカルコピーするしかない。

reset対策でマシンをくんでいる途中で、diskを買ってくるのを忘れていて、予備ディスクを使うかどうか悩んでいたときにディスクで思い出してこのざま。マシンを2台もばらすのは大変すぎる。

2009年7月5日日曜日

Dual Head configやり直し。

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
あまりにもよく落ちるので、見直した。体感的な描画速度も速くなった。安定したかどうかはしばらく様子を見る。

Section "ServerLayout"
Identifier "Multihead layout"
Screen 0 "theScreen" 0 0
InputDevice "Keyboard0" "CoreKeyboard"
InputDevice "Mouse0" "CorePointer"
Option "Xinerama" "on"
Option "Clone" "off"
EndSection

Section "Files"
FontPath "unix/:7100"
EndSection

Section "Module"
#Load "dbe"
#Load "extmod"
#Load "type1"
#Load "freetype"
Load "glx"
EndSection

Section "InputDevice"

# generated from default
Identifier "Mouse0"
Driver "mouse"
Option "Protocol" "auto"
Option "Emulate3Buttons" "no"
Option "ZAxisMapping" "4 5"
EndSection

Section "InputDevice"

# generated from data in "/etc/sysconfig/keyboard"
Identifier "Keyboard0"
Driver "kbd"
Option "XkbLayout" "us"
Option "XkbModel" "pc105"
EndSection

Section "Monitor"
Identifier "Monitor0"
VendorName "BenQ"
ModelName "G2220HD"
DisplaySize 1920 1080
Option "DPMS"
EndSection

Section "Monitor"
Identifier "Monitor1"
VendorName "BenQ"
ModelName "G2220HD"
DisplaySize 1920 1080
Option "DPMS"
EndSection

2009年6月27日土曜日

BP Study22 memo

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
走り書き
scala/lift関係はtwitterで#BP22をどうぞ。

発表者:佐藤一憲(スティルハウス)
事実上フリー。

http://www.sth.co.jp


アジェンダ
ご都合ドットコム
GAEのサーバ構成とスケーラビリティ
BigtableとDatastore

おまけ
- Smalltable


tmatsuoさんが会場にいる。

GAEのすごいところ。
無償で使える。
bigtableが簡単に使える
サーバ構築不要、デプロイ簡単


GWにご都合どっとこむを作った。
2000UU


FLEXクライアント
GAE/J
BlazeDS <- AirとJavaをつなぐミドルウェア
ビジネスロジックのクラス
Entity クラス

5日間で作れた。設計・実装テスト・ドキュメント


BlazeDSを動かすには?
iMartinzoldano.blogstop.com 200904 appengine-adboe blazeds


ki
gaenogennjou
8万人以上がしよう

140M PV/day

GAEの特徴
スケーラブルなアプリを構築するための慣習を促すための制限
ここのリクエストが使える処理時間(30秒)とリソースは制限されている。
statelessが強要される
Datastoreによるパーティション化されたデータモデルの利用

スケーラビリティをもつクラスタ環境を利用できる。
アプリ間の隔離性を維持。

使い手ががんばらなくていい。


GAE Stack の構成
[絵]

App Master
deploy managment,version managment


FrontEnd
HTTP req/res
clientにいちばん近いgoogle DCに到着
リクエストは10MBまで
コンテンツは、スタティックとダイナミックは別途ハンドルされる。

App Server
隔離性


APIのサーバ、DataStore Memcache, Mail, URL Fetch, Image, Taskqueue, Users, XMPP(To be added)

Queueはparallelに処理することもできる。workerしだい。


Client VM

App Server
Stateless, fieldをもてない。
make distributed and fail over easy.

session info are shared in DataStore
need to clean up with cron or TaskQueue

state
maybe we can put it into memcache. they will spill (LRU) or expire.
memcache is coherent cache, not storage.


API Proxy ThreadLocal
API callをフックしている。

30<


Dependency Injection
Aspect J Sprint AOP

Web frameworks
google web toolkit, tapestry, Blaze DS(Flex)
Grails

Alternate JVM Lang


GAE Scale out
On High load longed around 50min, new App server will be added.
even very light weighted app are distributed in 2 or 3 instances

There are safety limit. Ask for unlimit


Open For Questions
google moderator.
100k questions 3.6 million
700 queries per second

out of box GAE google has no work for it.

around deadline there are 700 submissions/second.
(queries to datastore)

Java. vs. Python
not big difference

No comet, no steaming

Bigtable

distributed datastore for structure data
able to handle PByte.

7manyear to build it.
production from 2005

Google uses more than 60

distributed multi dimension sorted map.
each cell is versioned, but not used in datastore.

bigtable is HUUUGe key-value store

kys are sorted in dictinary order

single low is atomically changed.
multi lows are not atomically changed.


key based crud
key based scan(prefix or/adn range)
they are sorted.

value based can NOT be done.

bigtqble cluster:
388 cluster
24500 tablet server(slave)


shceduler master
chubby (distributed lock server)
GFS master
bigtable master


Tablet 100~200MB
single server hold 100 tablets
they are replicated

bigtable master controls load balance among tablet server.


it is like DNS hiarchy
chubby file -> root tablet -> Meta data tablet -> tablet

they are cached, in ave 100ms < to find tablet

memcache -> commit log
||
\/
cache (mem table)
||
\/
SSTable (on disk, GFS)

on dist data are sorted immutable map
major compaction, GC.

GFS
more than 2 server folds (replication)
local GFS chunk server + non local lack.


Why need to have counter?


What is Datastore?
GAEにおけるデータ保存用API、ビッグテーブルで保存
エンティティグループ単位でACID
クエリ JDOQLまたはGQL

GAE/JでのAPI
JDO 永続化API (一番ドキュメントされている
JPA ORMなAPI
低水準API (Java doc only) Performanceがほしいとき使う。
JDOだとbatchのputができない(matsuo)

DataNucleausベース

PersisitenceManagerをcloses

kind
entity
propery
key


entity table
read/write with key
entity has property(s)
properys are serialized in single column



キー
アプリID、パス、エンティティID

パス
entity group のルートエンティティまでのパス

/Grandparent:Alice/Parent:Sam
~~~~~~~~~~~~
kind

protocol bufferでserializeされている。

property
entityごとにpropertyがもてる。schema less
entityごとに

クエリ
name="Foo"
とすると、プロパティ内にマッチするものがあればヒットする。

max 1000items to retrieve

range requestして1200-1500はできない。
1200番目がわからない。

1000番目のkeyを覚えておいて、そこから1000個とるとか。
先にproperty上に連番を振ってしまう。


python pagingではuserland paging できる

100件ずつ表示では100+1とってくる。
1は次のhead keyにつかう。

user landのpropertyでは注意が必要。
#キーとproperty

query is implemented with index and scan
need to create index on property


query つかったら負け?
crudがおそくなる。リストプロパティは要注意

index explosion
list with 1000item in property
query にlistが含まれているとだめ。

5000 index per entity (quota)


composit index.


entity group and transaction

entity has hiarchy. this hiarchy is NOT class hiarchy.

JDO "owned" relation <-- not eq --> Relation(RDB)


CAP theorem
Consistency
Availablity
Partition

optimistic lock
time stamp based check

in race
auto matic retry(python)
Java : user must implement it for loop


make small entity group
... lock size

a. message index root entity
b. timestamp + userid + message hash etc.

Entity
Entity update : 1~ 10 times/sec

distributed entity group

no table join
de normalize , prejoin them

no aggrigation function.
there is no group by, count, max, min,

function, stored proceedure.

no full text search
pre-process text


big application.
open social
buddy poker
giftal?


だめだということはない。

off by one error

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
Python~組み込みデータ型①より

a[○:□] で、○と□の指定の仕方をインデックスに統一しないのか?が疑問・・・です。


off by one errorというやつです。

2009年6月26日金曜日

DualHead(写真)

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
送信者 DualHead

VRARXR

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

私がなぜPythonを使うか?

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

私がなぜPythonを使うか?



私にとってプログラムを書くことは手段なので、効率がよく作業負荷が少ないものがよい。



3つの評価軸



プログラミング言語の方向性は3つあると思っている。



  • ハードウエアに優しい。

  • 計算に優しい。

  • 人に優しい。



「ハードウエアに優しい」とは



一言でいうと、アセンブリが該当します。これがうれしい状況は、コンピュータが起動した直後でなにも初期化されていない状況、ハードウェアの性能を極限まで引き出す必要な状況でしょう。
具体的には、boot loaderの実装とか、DSPでcodecのdecoderを実装しているときとか、CPUパワーが極端に制限されているとき、callスタックを直接操作してセキュリティホールを突きたい時、などでしょう。



「計算に優しい」とは



Lisp系の言語とか、純粋関数型言語とか、です。
メリットは計算そのものを表現する能力が高いこと、計算を表現するときに特殊な制限をかけることで自動変換可能になることなどが挙げられます。



「人に優しい」とは



まず、抽象度がそれなりに高いことが必須で、というのは「一定時間でかけるコードの行数は言語によらず一定である」という知見の存在があげられます。次にPEPの中にも出てきますが、コードはかかれる回数よりも読まれる回数が多いという点です。また、言語としてのコーディングスタイルが定まっているという点もあげられます。
「コーディングスタイルが定まっている」が何を指しているかというと、そうでなくて無為に使われた時間を挙げるとわかってもらえると思います。C系の言語の{}をどうindentするかという宗教論争にどれだけの時間が割かれたか?とか、C++のメンバ関数の中でメンバ変数にアクセスするときにthisを省いてよいがメンバ変数のm_をつけるとか何とかでしょう。



もっともミクロな項目を挙げるなら、メモリ破壊・メモリ管理だろう。うっかりでぶっ壊したメモリがめぐりめぐって引き起こすバグの原因を特定するのにかかる時間と労力、メモリをリークしないように気にしながら書く労力と時間、メモリリークのデバッグによって消耗される労力と時間を想像してみよう。それだけでぞっとする。



それから標準的な環境を構築するために必要なコスト、実際に作業するために必要なライブラリの入手コストも挙げられるだろう。Linuxのディストリビューションにどれだけ標準で入っているか?、Mac OS Xに入っているか?、windowsでbinaryのインストーラがあるか?などだ。後者はPerlでCPANの中からライブラリを適切に選ぶことはちょっと難があるケースがあるが、Pythonなら標準ライブラリがあるし、PyPI や setuptools / easy_install もある。



すぐに試せるinteractive shellがあることも大事だ。objectとの会話が許されない系はちょっとどうかと思う。
サプライズがないことも挙げられるだろう。phpの==やsortの話とか検索すれば山盛り出てくる。C++で純粋仮想関数を定義するときの構文、void foo() = 0;とかもどうかと思う。



どの評価軸を重要視すべきか?



用途限定されていればその状況をみればよいのですが、もうちょっと高い視点で考えてみましょう。Mooreの法則によりどんどん性能は上がってきました。これからもマルチコア等によって上がり続けるでしょう。何らかの企画から始まって最終的に消費者に届くまでの過程を考えると、プログラムを設計する過程はしゃれにならないコストがかかっていて、一番生産性の向上が低い部分だろう。ネットワークもCPUもメモリもディスクも常に進歩し続けていて、対数グラフでプロットされるわけだから。
とはいえ、AWSやGAEのおかげで、一人で世界を相手にするサービスを作ることは可能になっている。パワーを稼ぐことに労力をかけることよりも潜在的な競争相手に先んじて何かを作り上げることが大事で、その場合はスピードが肝になり、それは人に対する優しさに行き着くと思う。もちろんこれからもアセンブリ等の需要はなくなることはないし、計算すること自体が大変なジャンルは存在し続けるだろう。この辺はどこに強みをおくかと、だれとくむか(ハードウェア製造業者か?AWSか?)ということにかかってくる。



よくある意見に対する私の見解



indentでブロックはキモイ



code golferの方ですね、わかりますよ。というのは冗談として、pythonがstatemnetな言語である以上ブロック構造を作らなければならず、インデントが宗教論争を引き起こしてきたことを考えれば、reasonableな落としどころだと思っています。なにかうまい方法があるなら教えてください。きっと住めば都です、いい意味で。



''.joinキモイ



どこぞで盛り上がっているらしいですが、ぶっちゃけどうでもいいかな、というのが私の意見です。
ただ+=でつなぐのだけはない。パフォーマンスが理由ではないです(Jythonだと遅くなるらしい)。
",".join(xs)をforと+=を使って書くと「植木算」をすることになりますが、これがよくない。joinを使って書けば、どのようにつなぐかを記述する必要がない。命令的な何かを減らすだけでバグは減る。こんなコードにバグを入れるなという人もいるかもしれないが、それはマッチョだと思う。手段としてのプログラミングは、「ひろゆき」的低きに流れるにあるべきだ。
「低きに流れる」は悪いことだとは思わない。上善水の如し。とはいうものの、泳げるくらいにきれいな水であってほしい。



個人的には",",join(xs)ではなくてstr.join(",", xs)でもいいのだが、Array.join(",", xs)はできてくるobjectのtypeと作り手のtypeがマッチしないのが好きじゃない。str.joinだとタイプ量が多いので横着したととらえれば許せる範囲かな。str.joinだと思っている理由はstrのコンストラクタだととらえているからだ。

2009年6月15日月曜日

ISBN

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
wikipediaを参考にvalidatorを書いてみた.感想としては画面が広いと作業しやすい.コードが一度にたくさん見ることができるのは有利.参考資料もすべて開いておける.しかし,やってみると,使いきることができるものだ.もう広さを感じなくなりつつある.


import sys
import re

class ISBN:
pass


class ISBN10(ISBN):
pattern = re.compile('\d{9}(\d|X)')
@classmethod
def isvalid(cls, s):
"""
>>> ISBN10.isvalid('foobar')
False
>>> ISBN10.isvalid('4101092052')
True
>>> ISBN10.isvalid('4101092053')
False
"""
mo = cls.pattern.match(s)
if mo is None:
return False
parity = 0
for i, d in enumerate(s[:9]):
parity += int(d) * (10 - i)
return s[9] == ('0123456789X'[(11 - parity % 11 )])

class ISBN13(ISBN):
pattern = re.compile('\d{13}')
@classmethod
def isvalid(cls, s):
"""
>>> ISBN13.isvalid('foobar')
False
>>> ISBN13.isvalid('9784101092058')
True
>>> ISBN13.isvalid('9784101092057')
False
"""
mo = cls.pattern.match(s)
if mo is None:
return False
parity = 0
for i, d in enumerate(s[:12]):
parity += int(d) * (1+2*(i%2))
return (10 - parity % 10 ) == int(s[12])


def main():
for line in sys.stdin:
pass

if __name__ == '__main__':
import doctest
doctest.testmod()


追記:
既存のものにはこういうのがある.JANコードの意味とかが分かるらしい.

DualHead configuration

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
I'm using one geforce 7600 gs video card and two BenQ G2220HD displays. Here is my xorg.conf.

# Xorg configuration created by system-config-display

Section "ServerLayout"
Identifier "Multihead layout"
Screen 0 "Screen0" 0 0
Screen 1 "Screen1" rightOf "Screen0"
InputDevice "Keyboard0" "CoreKeyboard"
InputDevice "Mouse0" "CorePointer"
Option "Xinerama" "on"
Option "Clone" "off"
EndSection

Section "Files"
FontPath "unix/:7100"
EndSection

Section "Module"
Load "dbe"
Load "extmod"
Load "type1"
Load "freetype"
Load "glx"
EndSection

Section "InputDevice"

# generated from default
Identifier "Mouse0"
Driver "mouse"
Option "Protocol" "auto"
Option "Device" "/dev/psaux"
Option "Emulate3Buttons" "no"
Option "ZAxisMapping" "4 5"
EndSection

Section "InputDevice"

# generated from data in "/etc/sysconfig/keyboard"
Identifier "Keyboard0"
Driver "kbd"
Option "XkbLayout" "us"
Option "XkbModel" "pc105"
EndSection

Section "Monitor"

### Comment all HorizSync and VertSync values to use DDC:
### Comment all HorizSync and VertSync values to use DDC:
Identifier "Monitor0"
VendorName "BenQ"
ModelName "LCD Panel 1920x1080"
### Comment all HorizSync and VertSync values to use DDC:
HorizSync 31.5 - 67.0
VertRefresh 56.0 - 65.0
Option "DPMS"
EndSection
Section "Monitor"

### Comment all HorizSync and VertSync values to use DDC:
### Comment all HorizSync and VertSync values to use DDC:
Identifier "Monitor1"
VendorName "Monitor Vendor"
ModelName "LCD Panel 1920x1080"
### Comment all HorizSync and VertSync values to use DDC:
HorizSync 31.5 - 67.0
VertRefresh 56.0 - 65.0
Option "dpms"
EndSection

Section "Device"
Identifier "geforce7600gs0"
Driver "nvidia"
VendorName "NVIDIA Corporation"
BoardName "nVidia Corporation G70 [GeForce 7600 GS]"
BusID "PCI:1:0:0"
Screen 0
EndSection

Section "Device"
Identifier "geforce7600gs1"
Driver "nvidia"
VendorName "Videocard Vendor"
BoardName "nVidia Corporation G70 [GeForce 7600 GS]"
BusID "PCI:1:0:0"
Screen 1
EndSection

Section "Screen"
Identifier "Screen0"
Device "geforce7600gs0"
Monitor "Monitor0"
DefaultDepth 16
SubSection "Display"
Viewport 0 0
Depth 16
Modes "1680x1080"
EndSubSection
SubSection "Display"
Viewport 0 0
Depth 16
EndSubSection
EndSection

Section "Screen"
Identifier "Screen1"
Device "geforce7600gs1"
Monitor "Monitor1"
DefaultDepth 16
SubSection "Display"
Viewport 0 0
Depth 16
Modes "1680x1080"
EndSubSection
EndSection

2009年6月7日日曜日

starting zope/plone on CentOS

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
ラーニングカーブを改善するブログエントリを目指します。

特にバージョンをこだわらないなら、

yum install plone

とすればOK。ただしrepositoryにepelを追加する必要アリ。ちょっとでかいので待たされます。


/var/lib/zope/bin

にrunzopeがはいるので、

%sudo /var/lib/zope/bin/runzope

をやると、Zopeが実行され、ブラウザでhttp://localhost:8080を見に行くとZopeの管理画面(ZMI)が見える。

少しでもサーバ運用している人なら、unix root以外で実行したいと思うのは当然で、そのためにはzopeの設定をいじる必要がある。(yumから入れるとuser zopeが作られ、その権限で実行するようにconfが書かれる)

/var/lib/zope/etc/zope.conf

の中で

# effective-user chrism

effective-user zope

が設定されていると、権限がuser zopeに落ちる。

さてploneだが、pull donwからPlone Siteを選んでidを適切に選んでAdd Plone Siteするとplone instanceが作られる。このとき/に居ないとinstanceを作れないので注意。作れられるとZMIのlistの中にploneのiconとともにつけたidのitemが現れる。そしたら

http://localhost:8080/

にアクセスすると、ploneの画面が表示される。メデタシ。

この先、何か間違えてやり直したくなったら、zopeのデータを蓄えているデータベースの実体であるData.fs(/var/lib/zopev/varにある)を消すのでは無くZMIからPlone instanceを消すのが正解。

注意事項としては、スキンはパッケージが壊れていると、ただしく消せない(!)のでploneのインスタンスを消してやり直すことになる。

この辺はrpmとは違うらしい。rpmだとfilesセクションがあるからまあまずやり直しが利く。
rpmと違って困ったところ。eggじゃなくてrpmじゃいけない理由はあまりないだろうが、eggにしておけば、プラットフォームを選ばないのだろう。zopeに限ったことではないが、pythonのpackage管理とplatformの提供するpackageの関係が微妙に思えることはよくある。

ploneで日本語がいい人はploneのページの右上の設定から変更すればメニューが日本語表示になります。フォルダーとかを新規作成して慣れましょう。publishするのも忘れずに。キモとしてはフォルダーがネストできる、イベントを貼るとカレンダーがクリックできるようになる、ニュースを作るとナビゲーションに追加されるなどでしょうか。


Productsを入れる。
大抵はdlして解凍したものを/var/lib/zope/Productsに入れればよい

pixiをいれてみた
http://nagosui.org:8080/Nagosui/COREBlog2/plone-skin-pixi-0.5
レイアウトが破壊されて操作ができない・・・壊れているので入れないように。

適切なproductを選ぶのが肝のようだ

次回は「ZClassを作って何か表示するまで」がやりたい。勉強用のproductがあったはずなのでそれをいじってみようと思います。

2009年6月6日土曜日

zope をipythonで触る。

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
あー、IPythonはインストール済みだとします。
CentOS 5.2でyum installしたZope/Ploneのお話です。(epelからインストールされるはず)

http://wiki.zope.org/zope2/DebuggingWithIPythonAndOtherTips
を参考に。
Centos 5.2でyumを用いてinstallすると、~zopeは/usr/lib64/zopeになる。
まずはzope userでipythonが動くようにするために~zopeに.ipythonを作る。適当にコピーで可。ただしownershipに注意。zopeで読み書きできること。

nori@asama]~zope% ls -ltra
total 96
drwxr-xr-x 3 root root 4096 Jun 6 17:08 lib
drwxr-xr-x 2 root root 4096 Jun 6 17:08 bin
drwxr-xr-x 127 root root 69632 Jun 6 17:08 ..
drwxr-xr-x 10 root root 4096 Jun 6 17:08 skel
drwxr-xr-x 6 root root 4096 Jun 6 23:41 .
drwxr-xr-x 3 zope zope 4096 Jun 6 23:42 .ipython
[nori@asama]~zope% pwd
/usr/lib64/zope

こんな感じ。

sudo -u zope -H zopectl debug

して、ずらずらずら~といろいろ出るが、最後にpythonのプロンプトになるので、あとはリンクにあるのと同じようにimport IPythonして立ち上げればよし。

さて何をみていけばいいのかな?

2009年6月2日火曜日

google wave bof memo

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
google wave bofに行ってきた。

まだサービスとして形が見えていない。

waveはプラットフォームであって、アプリではない。

ターゲットは微妙。現状ではgeek対象。
少数がコラボレーションするにはよいツールになるのではないだろうか。
#中の人が便利に使っている?
IRCとwikiを使っているグループが該当するだろう。

twitterのもっているいい加減さは持っていない。
#一方的にfollowするとか

以下、メモ:

wave自体が不安定なので待つかもしれない。
くる直前にversionがあがったらしい

3カラム構成
左 navigation
中央 list
右 コンテンツ

wavesandbox.com
アカウントが足りていない。リソースの問題と思われる

編集モードと閲覧モードをC-eで行き来
C-6でitemize key bindはappsと同じ。

C-rで返信
1つはblipといってC-Rで

閲覧モードでC-Rすると文に対して返信ができる
ドキュメント自体の構造がちょっと違う

イメージをdrag & dropすると張り込むことができる
アップロードは非同期的に行われる(バーが絵の下にでる)

クリックするとスライドショー
またされる→ビーチボールを表示

すぐにあきらめる。ブラウザが固まることはない。
・・・Safari固まる。ということはマシン自体が固まる

参加者(participants)を追加すると、追加された人は編集可能になる
同時に編集されて気持ち悪い。カーソルに名前がつく。
→推敲が全部見える。
draftボタンがあるがまだ実装されていない。
#実装されていないものだらけ

ごみ箱から元に戻せない

UIの競合がある
リストから拾って捨てようとしたときに新itemがくると、新着itemが

線形にしか履歴が持てない。
branchできるがマージできない。
diffはとれない。

なんか落書きしている。これはなに?

サーチ結果を貼り付けることができる
地図を出すこともできる。→他人のスクロールが見える。
#マップを消せない
ある種のマルチポインタ環境

操作性はよいとはいえない。荒削り。

gmailのcontactsと共有されている。
google apps
wave側には編集インターフェースがない。

オンラインマーク
グループアドレスが作れる

gmailでも複数のメールを見ながらかきたいときがあるが、
ただクリックすると右のpaneの中身が変わってしまう
cmd keyを押しながらクリックするとと複数見ることができる。

マップをはるとめちゃくちゃ重い
メールを送るとgmailにいってしまう
現状はgatewayは自作するしかない

spam対策もすでにある。
navigationはgmailと同じ
tagがあるがsearchの対象にならない・・・

deleteもすぐに反映される。


API編
documentがあるので参照のこと

2つカテゴリがある
Extension
- Robot/Gadget
Embeded

wave participants

wavelet
Blip
Creatro
Contributors
Annotation
Blip
Blip

root blipが存在する
# private blip == wavelet ?

viewerがほしいなぁ

Eventlist
変化を拾う。
waveletができた、keyがおされた、blipがどうのこうの。


robotのデモ

botは1 domain 1 bot .c.f. app engineは10個

インスタンスはみんなが使える。セキュリティ的に・・・


rosy (rosetta stoneから)
リアルタイム翻訳、値域の言語を指定する
ボットが起動するとそのblipが登場する

結構まとも、インクリメンタル翻訳する

日本語を入力するにはsafariは問題あり

iconはpathが指定できる。


tweety(twitter robot)
検索

andoさんのガジェット
キーボード押すと音がでる。複数人で演奏できる。

wave.getState().submitDelta({...)
が肝。
音も再現できる。
js. css. htmlでできる。

何人でshareできるのかな?
60人は大丈夫だが・・・

遅延はたくさんのる。音楽の演奏は不可能
格闘ゲームはどうなっているのか?
共同編集シーケンサも存在

フラッシュを埋め込むこともできる

waveはossでサーバを建てることができる。
自分で専用サービスも可能


bloggy
appspot(中身django)
waveの中身を編集すると、blogger上のwidgetに反映される(動的に書き換わる)

絵を貼ることもできる

逆も可能


disconnectedすると編集した内容は現状では消えてしまう。
application名のスクワッティングが可能?

deploy


Debug bot
発生したイベントが見える。

blip単位で既読になる?
削除でもversionがあがる


iconがないとだれがだれだかわからん
3つじゃないとコラボじゃない


ブラウザに負荷がかかるのでは?
CPUはそんなにかかってない→100%


20人以下のコラボレーションではハッピー。
IRCをreplaceできそう。

gmailのかわりになる面はある。新しい人に教えるには作ったものを共有すればいい。
新しい人はplay backすればいい。

細かいセキュリティは自分でがんばる

iPhoneアプリは?
いちおう見ることができる。

$は?
速いサーバを提供する。現状中央サーバがある。
課金
「コミュニケーションを集約したい」

polly
投票・アンケートボット

blipに関しては権限管理がない。

2009年6月1日月曜日

fdatasync

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
今月のカーネルウオッチでfdatasyncが出てきたのでpythonでどうなっているか見てみることにした。

そもそもfdatasyncってなにさ?

man page of fsyncより

fsync() は、ファイル記述子 fd で参照されるファイルの内部で持っているデータ (つまりバッファキャッシュページ) のうち修正されたデータを、そのファイルが属するディスクデバイス (またはその他の永続ストレージデバイス) に転送 (「フラッシュ」) する。この呼び出しは転送が終わったとデバイスが報告するまでブロックする。またファイルに結びついたメタデータ情報 (stat(2) 参照) もフラッシュする。

fsync() の呼び出しは、ファイルが存在しているディレクトリのエントリがディスクへ書き込まれたことを保証するわけではない。保証するためには明示的にそのディレクトリのファイル記述子に対しても fsync() する必要がある。

fdatasync() は fsync() と同様であるが、メタデータの扱いが異なる。 fdatasync() は、それ以降のデータ読み込みを正しく扱うためにそのメタデータが必要にならない限り、変更されたメタデータをフラッシュしない。例えば、 st_atime や st_mtime (それぞれ最終アクセス時刻、最終修正時刻; stat(2) 参照) の変更はフラッシュを必要としない。なぜならこれらはそれ以降のデータ読み込みを正しく扱うために必要ではないからである。一方、ファイルサイズ (ftruncate(2) では st_size) の変更はメタデータのフラッシュが必要である。 fdatasync() の狙いは、全てのメタデータをディスクと同期する必要のないアプリケーションに対して、ディスクアクセスを減らすことである。


データベースを作っている人は気にするし使います。


まずは標準ライブラリだが、osモジュールにはちゃんとfdatasyncがある。posixmodule.cを覗くとなかで読んでいるのがわかる。

fdatasync(fd)
ファイル記述子 fd を持つファイルのディスクへの書き込みを強制します。メタデータの更新は強制しません。利用できる環境: Unix

かなり昔からあるみたいで、2.3のときにfsyncとfdatasyncは別々に調べなきゃ駄目よbugがあった。


で、次にどんなアプリが使っているか?なのだが、ソースコード検索してみる。

mved-1.0
mved - An editor-focused multiple file move utilityだ、そうな。

tmpfd, tmpfilename = mkstemp()
try:
for name in oldnames:
write(tmpfd, '%s\n' % name)
fdatasync(tmpfd)
except IOError, e:
giveup("%s: %s", (tmpfilename, str(e)))

なにやらfile systemを読み書きするものらしい。

def fsync(self, isfsyncfile):
self._fflush()
if isfsyncfile and hasattr(os, 'fdatasync'):
os.fdatasync(self.fd)
else:
os.fsync(self.fd)

あまり引っかからない。file objectのflushでも読んだほうがいいのだろうか?そう思ってObjects下をgrepするも成果なし。

とまあ、ほとんどのpython userには縁がなさそうでした。大体os.fsyncとか使わないだろうし。fobj.flushはよくあるだろうけど。

あとはdbを使うときに間接的に影響を受けるケース。

MySQLのinnoDBの設定とか。

nnodb_flush_method

もし fdatasync (デフォルト)に設定すると、InnoDB はデータとログ ファイルの両方をフラッシュする為に fsync() を利用します。もし O_DSYNC に設定すると、InnoDB はログ ファイルをオープン、フラッシュする為に O_SYNC を利用しますが、データ ファイルをフラッシュする為には fsync() を利用します。もし O_DIRECT が指定されると(GNU/Linux バージョン上で有効)、InnoDB はデータ ファイルをオープンする為に O_DIRECT を利用し、データとログ ファイルの両方をフラッシュする為に fsync() を利用します。InnoDB は fdatasync() の代わりに fsync() を利用する事、また様々な種類の Unix 上で問題があった為、デフォルトで O_DSYNC は利用しないという事に注意してください。この変数は Unix に対してだけ関連があります。Windows 上では、フラッシュの方法は毎回 async_unbuffered で、変更する事はできません。

この変数の異なる値は InnoDB performance 上で著しい影響を持ちます。例えば、InnoDB データとログ ファイルが SAN 上に位置するいくつかのシステム上では、innodb_flush_method を O_DIRECT に設定する事は、3つの要因によってシンプルな SELECT ステートメントの性能を劣らせる可能性があるという事が発見されました。

なんか変だと思うのは気のせい?

先日読んだheystack話もメタデータがNFS上にあっておせーというのがモチベーションでしたね。

remember the milk

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
smart listを多用してプロジェクト単位にtaskを切り分けた。2つのプロジェクトに所属するtaskも作れる。日程管理はgoogle カレンダーでの連携でこなす。取りあえずスケジュールが破綻するかどうかこれで様子を見る。

2009年5月31日日曜日

Tsudaったー対応

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
世界で一番簡単な対応 with tweetdeck.
「group: tsuda」をつくる

2009年5月28日木曜日

本棚

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
送信者 0528


送信者 0528

本棚を組み立てた。これで床に積まれている本を収容できるはず。

matrixぽくないか、これ

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

フォントの色を蛍光緑にしてみるか。pixelの使い道かとしてどうなのさ、これは。

2009年5月23日土曜日

MAKE Tokyo Meeting 03

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

Google App Engineの開発環境を作るメモ

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
python 2.4以降が必要です。2.5以降が望ましいです。

まずGoogle App Engine(以下、GAE)の開発環境本体のダウンロード
http://code.google.com/intl/ja/appengine/downloads.html

次にwsgirefをインストールする(2.4な人)、2.5以降の人はそのまま進んでください
pypiから入手
http://pypi.python.org/pypi/wsgiref
私はrpm/yumで管理する派なのでpython setup.py bdist_rpmします。

そのほかの依存
PIL、python-imaging-library(GAE stubの実装が依存)
http://www.pythonware.com/products/pil/


お薦めのコンボ
webtest、テスト用のアプリを書くために必要
http://pypi.python.org/pypi/WebTest/1.2

nose、テストツール
http://somethingaboutorange.com/mrl/projects/nose/0.11.1/

NoseGAEはnoseのpluginで、GAEの環境を再現してくれます。http://code.google.com/p/nose-gae/

covoerはnoseのpluginで、unittestでどれだけの範囲を叩いたかを調べることができます(最新のnoseには含まれている模様)。http://somethingaboutorange.com/mrl/projects/nose/0.11.0/plugins/cover.html


プロジェクトを始めるには、googleから持ってきたものを解凍したdirにいってtemplateをコピーしてみましょう。細かい話はgoogleのドキュメントを読みましょう。

google_appengine% cp new_project_template sample
google_appengine% chmod -R +w sample/*

そのままではread onlyなので変更

google_appengine% nosetests --with-gae --gae-lib-root=. --gae-application=sample --with-coverage --cover-package=main sample

とするとnoseでunittesができて、かつcoverageの情報が得られます。

2009年5月22日金曜日

XMPP/AMQP @ BPStudy

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
VoluntasさんのBPStudyの発表を観に行った。
以下メモ。


XMPP xml base
AMQP binary


Erlang
Open Telecom Platform プロセスを監視できるこれが一番大きい。(実際に作るとなると並列、分散はどうでもいい)
まあ、エリクソンが作って使っている集大成だから。

メジャーアプリ。
Facebook Online Chat
AWS imple DB
Apcache CouchDB IBMが力をいれているC++から移行。
分散ハッシュDB Jai /Scalaris gooをpowerしている。Amazaon Key Value Storage実装

higempon 20090509/1241863278
このエントリのせいでErlang

情報処理学会に出ている2009/3のErlangの解説記事


XMPPとは
XMLベースのプロトコル
RFCで
Jabber -> XMPP
Google Talkが採用(完全準拠?)
動きはMail serverと同じ
TCPコネクション張りっぱなし


仕様はがちがち
拡張もいっぱい、まあXMLですから



基本:Client同士がMessageを直接やりとりする。
しかしportがつぶれていると

googleのライブラリはHole panchingしている。
すげー力業 10万行のC++

状態をXMPP Serverが状態を配る。

message サーバは1 domainを担当する。
google じゃなくて自前もできる。

Serverがコネクションをリレーしてくれる。
日本では流行っていないが、海外では1ユーザ月額課金のサービスがある。


接続
XMPP Serverにログイン
XMPP ServerにIDとIPを伝える
XML目っ正ー時
別のXMPPサーバに転送
別サーバはDNS検索

セキュリティ
SSL/TLSによる通信を暗号化
DNSでドメイン名を逆引き確認
SASLによるチャレンジ型検証

SASL RFC2222

XMPPの未来
googleがさいようしたのは大きい
プッシュベースのアプローチは大事
非同期メッセージは必要
ソリューションという形が進みそう
OpenFireという「製品」がある→チャットルームが作れる。ただしクライアント側が対応していないといけない。

同時接続クライアントは?
10KはOKでしょう。
 そもそもにスケールを前提に仕様が作られている
クラスターベースでやる

ejabberd
XMPP
Erlang
Unbutuならapt-get

Ejabberd "cloud Edition alpha"
データベースをS3に配置
将来的にはSQSを使うようだ


AWS import/export
HDDをアマゾンへ送る(!、ハードのスペックが指定されている、重量等
アマゾン側でS3にインポートする

1TByteでupで$100,
日本のクレジットが通ったが、アメリカに郵送。
帯域の問題でFedexの方がやすい。時間を買っている。


AMQP

Advanced Message Queue Protocol
MQの保湯順規格を目指すプロトロコる
メッセージ指向ミドルウェア
アプリケーション菅野通信プロト古老
言語や環境に関係なく相互接続を実現
今年中に1.0が公開されるはず

バイナリプロトコル
PubSub型
ストア・アンド・フォワード
TCPであることを利用した信頼転送
非同期なのにトランザクション、コールバックしない(これがメリット)。
マルチキャスト


Publish
Exchangeがqueueにひたすら突っ込む


Direct Exchange Type
ルーティングキーがきも

funout
ルーティングキーすらなし。
さらのキー。ただひたすら他得られる


パターンを使用したルーティングキー
a.b.c.dといったキーパターン
#や*のワイルドカードが使用可能
AMQP 0.8まで実装済み

Rabbit MQ
130万request/s (1つのサーバで!)・・・他の部分が持たない?
10K line
ただし、Erlangのundocumentedな機能を多用なので、VMのコードを読まないとダメ。

金融機関とかが使うらしい。
ニュースの配信、電話会社等。

XMPP gatewayやSTOMP gateway

作っている会社はL shiftはこれで食っている


Kay App Engine / Python 専用フレームワーク
kayはtmatsuoさんの息子の名前

非同期と純関数は計算としてはうれしいのだが、人間にやさしくない。

とんがったパーツなのだが、クライアントが手書き。
clientの実装作業を受注しているのではないだろうか。

金がかかっている。AMQPは。


GAE上でXMPPを使えるようになるらしい。
googl
e IOで発表されるかも


XMPP
ルームチャットはN:Nになる??
その負荷を面倒を見たくないからgoogleはgroup chatなし(googleはstar型になっている)

SQSがアマゾンにある

rabittmqはqueueのバックエンドはmnesiaを使っている。
2Gの制限はぶった切ることで対応、基本全てメモリ。
基本的に永続化しない。

mnesiaはよく使われているのか?微妙
 ただ分散dbなので設定ファイルを蒔くのに使う
 制限がきついのが痛い→wrapperを書くことになる。
tokyo cabinetを後ろにつないだひとがいるらしい。でもなんかメモリリークしてる。

gihyoで記事書きました

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
ここです。
お目汚し失礼。

AR Magicを見て思った

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク


配線の変更、パンチカード、CUI、GUIと進歩してきたが、次はAR UIだろう。
いま、UIはタイプ速度に支配されている。ARやカメラ・マイク・GPSを賢く使えば、もっと速い速度でもっと細かいニュアンスを拾ってコンピュータを賢く振舞わせることが出来るだろう。ハードよりもソフトとアイディアと$の問題だと思う。

冷蔵庫の扉に液晶を貼ってネットショッピングさせるより、冷蔵庫の中でARして、無いものを買うことが出来るほうが使い勝手がいいだろう。靴箱に液晶を貼るより、ARで新製品を立体表示したほうが楽しいだろう。コンピュータの前に座って何を買うかを指定するより、場所で買うものが必然であるほうがいい。

でも冷蔵庫の中が温まりそうだな、この仕組み。

2009年5月21日木曜日

githubをはじめた

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
Gravatorもはじめた。
GravatorとかOpenID、GAEを見ると、「ちょっとしたものだがuserに対して気遣いのあるwebapp」を作る労力が減っているのがわかる。

本が届いた。

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
amazonから注文していた本が届いた。

  • キャパシティプランニング

  • CDNプロトコル入門

  • Interconnections第2版

  • アクセスログ解析の教科書

  • 集合知インアクション

  • ThoughtWorksアンソロジー

  • Release It!

  • 未来のモノのデザイン


キャパシティプランニングは、「ハイパフォーマンスウェブサイト」(犬本)と「サーバ負荷分散技術」とあわせて読むといい感じです。でかいweb site構築三連星。たぶんスケーラブルウェブサイト(魚本)も取り合わせとしてよいだろう。

原因は

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
statusのセットしもれ。明示的にセットする必要がある。
headerは明示的に消さなければならない。


def relay_response(self, src, status):
assert status
self.response.set_status(status)
for key in src.headers:
self.response.headers[key] = src.headers[key]

if status in ENTITYLESS_STATUS:
for key in PROHIBTED_IN_ENTITYLESS:
del self.response.headers[key]
else:
self.response.out.write(src.content)
for key in PROHIBTED:
del self.response.headers[key]

httplibで叩いてみた

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
まずはサーバ側の出力が正しいこと+gae stubの実装に使われているhttplibが正しいことを検証。
コード。

import httplib

PATH = '/image?format=png&gnubgid=4HPwATDgc%2FABMA%3AMAAAAAAAAAAA&height=300&width=400&css=minimal'
HOST = 'image.backgammonbase.com'
ADDR = '192.168.2.64'

conn = httplib.HTTPConnection(ADDR)
conn.request("GET", PATH, headers={'host':HOST})

r = conn.getresponse()
print r.status
print r.getheaders()
etag = r.getheader('etag')
print etag
conn.close()

conn = httplib.HTTPConnection(ADDR)
conn.request("GET", PATH, headers={'host':HOST, 'If-None-Match':etag})

r = conn.getresponse()
print r.status
print r.getheaders()
conn.close()

実行結果

[nori@asama]~/Desktop/study/python/httplib% python test.py
200
[('content-length', '17877'), ('age', '102'), ('expires', 'Thu, 21 May 2009 01:39:27 GMT'), ('server', 'Apache/2.2.3 (CentOS) mod_python/3.2.8 Python/2.4.3 DAV/2 SVN/1.6.2 mod_wsgi/2.1-BRANCH'), ('etag', 'code:6bf600612d854254f2d17b68682de576620b5257+css:c484f9e5d8c595e9c0d36f7889d651e21f06e4f7'), ('cache-control', 'public'), ('date', 'Thu, 21 May 2009 00:41:09 GMT'), ('content-type', 'image/png')]
code:6bf600612d854254f2d17b68682de576620b5257+css:c484f9e5d8c595e9c0d36f7889d651e21f06e4f7
304
[('date', 'Thu, 21 May 2009 00:41:09 GMT'), ('cache-control', 'public'), ('etag', 'code:6bf600612d854254f2d17b68682de576620b5257+css:c484f9e5d8c595e9c0d36f7889d651e21f06e4f7'), ('expires', 'Thu, 21 May 2009 01:39:27 GMT'), ('server', 'Apache/2.2.3 (CentOS) mod_python/3.2.8 Python/2.4.3 DAV/2 SVN/1.6.2 mod_wsgi/2.1-BRANCH')]

ヘッダをつけ間違えたかな?

2009年5月20日水曜日

bug found

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

200 OK
HeaderDict([('Content-Type', 'text/html; charset=utf-8'), ('date', 'Wed, 20 May 2009 10:50:11 GMT'), ('server', 'CherryPy/2.3.0'), ('cache-control', 'public'), ('Content-Length', '0')])

げー。200を返してContent-Length 0ってなんだよ。ハァ。

- - "GET /image?gnubgid=4HPwATDgc%2FABMA%3AMAAAAAAAAAAA&height=300&width=400&css=minimal&format=jpeg HTTP/1.1" 200 16036 "" ""
- - "GET /image?gnubgid=4HPwATDgc%2FABMA%3AMAAAAAAAAAAA&height=300&width=400&css=minimal&format=png HTTP/1.1" 200 17877 "" ""
- - "GET /image?gnubgid=4HPwATDgc%2FABMA%3AMAAAAAAAAAAA&height=300&width=400&css=minimal&format=png HTTP/1.1" 304 - "" ""
- - "GET /image?gnubgid=4HPwATDgc%2FABMA%3AMAAAAAAAAAAA&height=300&width=400&css=minimal&format=png HTTP/1.1" 304 - "" ""
- - "GET /image?gnubgid=4HPwATDgc%2FABMA%3AMAAAAAAAAAAA&height=300&width=400&css=minimal&format=jpeg HTTP/1.1" 200 16036 "" ""
- - "GET /image?gnubgid=4HPwATDgc%2FABMA%3AMAAAAAAAAAAA&height=300&width=400&css=minimal&format=png HTTP/1.1" 200 17877 "" ""
- - "GET /image?gnubgid=4HPwATDgc%2FABMA%3AMAAAAAAAAAAA&height=300&width=400&css=minimal&format=png HTTP/1.1" 304 - "" ""
- - "GET /image?gnubgid=4HPwATDgc%2FABMA%3AMAAAAAAAAAAA&height=300&width=400&css=minimal&format=png HTTP/1.1" 304 - "" ""

サーバ側は304してる。

GAE app 'reverse proxy'のunittestで

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
WebTestをインストールしてテストを書いていたが、

response = self.app.get('/image'
'?gnubgid=4HPwATDgc%2FABMA%3AMAAAAAAAAAAA'
'&height=300'
'&width=400'
'&css=minimal'
'&format=png')
assert response.status == '200 OK'
print response.headers

とかしたら

HeaderDict([('Cache-Control', 'no-cache'), ('Content-Type', 'image/png'), ('Content-Length', '17877')])

とか出力されて萎えた。no-cacheはどこが原因だ?

NoseGAE

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
rootとappの指定の仕方で戸惑った。rootは見ての通り。appを指定しないと設定ファイルが無いのでテストできない。

[nori@asama]~/Desktop/work/gae/google_appengine% nosetests --with-gae --gae-lib-root="/home/nori/Desktop/work/gae/google_appengine" --gae-application=reverse_proxy reverse_proxy/test.py
WARNING:root:Could not read datastore data from /tmp/nosegae.datastore
WARNING:root:Could not read datastore data from /tmp/nosegae.datastore.history

----------------------------------------------------------------------
Ran 0 tests in 0.000s

OK

2009年5月19日火曜日

reverse proxy on GAE

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
本体をローカルで動かしてなぜGAE上でアプリを作らないのは、PILが使えないとか、いろいろ。注意点はurllib.urlopenがsocketを使うので、GAE上では使えない。そのため、urlfetchを使う。あとは、ハンドラで.*を指定してリクエストを全部持ってくること。

普通のproxyもつくれるね。もう作った人がいるだろうけど。
#!/usr/bin/python

import urlparse
import wsgiref.handlers

from google.appengine.ext import webapp
from google.appengine.api import urlfetch

cache_related = ('if_match', 'if_modified_since', 'if_none_match', 'if_range', 'if_unmodified_since')

NETLOC = 'image.backgammonbase.com'
SCHEME = 'http'

debug = False

class ReverseProxyHandler(webapp.RequestHandler):
def get(self):
scheme, netloc, path, query, fragment = urlparse.urlsplit(self.request.url)
t = urlparse.urlunsplit((SCHEME, NETLOC, path, query, fragment))
if debug:
self.response.out.write(t)
else:
response = urlfetch.fetch(t)
self.response.headers['Content-Type'] = response.headers['Content-Type']
self.response.out.write(response.content)

def main():
application = webapp.WSGIApplication([('.*', ReverseProxyHandler)],
debug=True)
wsgiref.handlers.CGIHandler().run(application)

if __name__ == '__main__':
main()

GAEはじめた

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
自分のサーバにrequestを出してみた。
決め打ちのurlの代わりになにか別のものを割り当てないとね。

class MainHandler(webapp.RequestHandler):
def get(self):
response = urlfetch.fetch('http://image.backgammonbase.com/image'
'?gnubgid=4HPwATDgc%2FABMA%3AMAAAAAAAAAAA'
'&height=300'
'&width=400'
'&css=minimal'
'&format=png')
self.response.headers['Content-Type'] = response.headers['Content-Type']
self.response.out.write(response.content)

2009年5月18日月曜日

ついでなのでサーバ負荷を見てみた

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
初回のリクエスト時。がんばって画像を生成しているので負荷が高い。


mem_cacheされた画像をネットワークに書き出しているだけなので、ネットワークだけが重い。

メインテナンス終了

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
メンテナンス内容:

  • 内部清掃

  • REX SATAの配線

2009年5月16日土曜日

Wolfram|Alpha

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

ここより

気づいた点:
水平をちゃんとだしてますね。

エンクロージャ:PowerEdge 4210 でしょうか? 42Uです。
なかみ:1台2Uでしょうね(1Uが1.75インチ(約44.5mm)に相当))。前面3.5inch HDDのラックがが12台はいるなぁ、これは一体どういうことだ?on lineで見ても8台って書いてあるがこれはボードのSATAの口が8個っていう意味なのか?サーバ屋ではないのでわかりませぬ。

2Uの1台で最低4~5k$とかかな?エンクロージャ1台で200K$とかかなぁ?エンクロージャ6台とネットワークのコストを含めると1~2M$かな。私にとってはほとんど妄想の世界。マシン台数は120台。gのコンテナの1/10。もっとも、wolframの場合はHDDにかなり偏っているように見える。

2009年5月15日金曜日

MySQLの後継?

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
MySQLがフォークか、オープンアライアンスが誕生

ウィデニウス氏は、すでにMySQL互換の「MariaDB」をコミュニティベースで開発している。MariaDBの公式ページによれば、MariaDBはMySQLの「ブランチ」と表現されている。MySQLはコアになるストレージエンジンが入れ替え可能という特徴があるが、 MariaDBはMySQLをベースに、Mariaストレージエンジン、PBXTというエンジンを搭載。Mariaストレージエンジンをデフォルトとしたものだという。ほとんどのケースでMariaDBはMySQLと同じ挙動を示し、すべてのコマンド、ライブラリ、APIなどを備えているという。

各言語でのbindingとかはどうなっているのだろう?対応はそれほどタフでは無いだろうが。

2009年5月13日水曜日

okyuu.comとfriend feed/twitter

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
http://okyuu.com/ja/の新着のrssってどこ?
あと思ったのだが、わざわざPostするより、ハテぶしたりblogに書いたりしてfriendfeed/twitterにそれが流れて御仕舞いというのがこれからの情報の流れだと思う。とここ数ヶ月での自分の変化を振り返って思った。ただ、よりナマな編集がすくない密度の低い情報になる傾向があるとすると、そこにおいて技術はどういう役割があるのかなぁ思ったり。

emobile 速度測定

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
よくわからね。測定結果がころころ変わる。帯域割り当てがかなり動的なのかもしれない。


■速度.jp スピードテスト 高機能版 回線速度測定結果
http://zx.sokudo.jp/ v3.0.0
測定時刻 2009/05/13 04:29:47
回線種類/線路長/OS:光ファイバ/-/Linux/東京都
サービス/ISP:-/その他
サーバ1[N] 2.34Mbps
サーバ2[S] 2.11Mbps
下り受信速度: 2.3Mbps(2.34Mbps,292kByte/s)
上り送信速度: 390kbps(393kbps,49kByte/s)


きになったのででかいファイルを落としてみた。平均速度が先の計測結果を上回っているので、使っているとより帯域が割り当てられるのではないだろうか。

[nori@kongoh]~/Desktop/bearoffdb% time wget http://bd.backgammonbase.com/gnubg_twoside_6x11.bd
--04:34:16-- http://bd.backgammonbase.com/gnubg_twoside_6x11.bd
bd.backgammonbase.com をDNSに問いあわせています... 124.155.113.117
bd.backgammonbase.com|124.155.113.117|:80 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 200 OK
長さ: 1225323048 (1.1G) [application/octet-stream]
Saving to: `gnubg_twoside_6x11.bd'

100%[====================================================================================================>] 1,225,323,048 484K/s in 51m 46s

05:26:04 (385 KB/s) - `gnubg_twoside_6x11.bd' を保存しました [1225323048/1225323048]

wget http://bd.backgammonbase.com/gnubg_twoside_6x11.bd 4.26s user 22.20s system 0% cpu 51:47.80 total

googleを騙るspam

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

Google Online Promotions

詳細を表示 1:51 (4分前)


返信

Follow up message
From Google Online Promotions
返信先 mrf.henson@8u8.com
To
日付 2009/05/13 1:51
件名 Google Online Promo © 2009
送信元 youseepost.dk

GOOGLE GIVE-AWAY WINNING NOTIFICATION!!!
This E-mail is to inform you that your e-mail emerged as a winner of £500,000.00 GBP (Five Hundred Thousand British Pounds) in our online Give-away draws. GoogleUK has successfully organized for the second time a Cash Give-Away in the UK. Over £20,000,000.00 (Twenty Million British pounds) is to be given out for this Anniversary Draws. No purchases of tickets were required. Participants for the draws were randomly selected from a world wide range of web searchers who use the Google search engine (Googler) and other Google ancillary services. Google is now the biggest search engine worldwide and in an effort to make sure that it remains the most widely used search engine, Google is running an e-mail beta test.

Your email address was linked with our Computer Generated Profile Numbers(CGPN) and attached to the following details: Computer Generated Profile Numbers (CGPN):7-22-71-00-66-12, Ticket number: 00869575733664, Serial numbers:/BTD/8070447706/06, Lucky numbers: 12-12-23-35-40-41(12), was picked among our lucky winners to receive £500, 000.00 British pounds. Winners were selected randomly through a computer ballot system from worldwide users of the Google search engine.

YOUR WINNING DETAILS ARE AS FOLLOW:
Computer Generated Profile Numbers (CGPN):7-22-71-00-66-12
Ticket number: 00869575733664
Serial numbers: / BTD/8070447706/06
Lucky numbers: 12-12-23-35-40-41(12)

To claim your give-away prize, send the following
Your full names................. , sex...............................,
Location............................
Alternate e-mail address..................Your winning details.................

To your processing agent (Mr. Francis Henson) who have been assigned to handle your winning file and payment processing.

Your Processing Agent contact:
Mr. Francis Henson,
Email: giveaways.promoonline02@gmail.com

We wish you the best of luck as you spend your good fortune. Thank you for using Google.

Sincerely,
Mrs Susan Johnson.

2009年5月9日土曜日

UI

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
ファミコンはこうして生まれた
試すこと。

十字ボタンでいけると確信していた沢野は,ゲーム&ウォッチからリード線を引っぱり出してファミコンの試作機につなぎ,開発スタッフに操作してみるように促した。真っ先に試したのは中川だった。驚くほど手に馴染み,なんの違和感も感じなかったという。

UIの出来はきわめて重大

操作に忠実に反応しないゲーム機は,ユーザからそっぽを向かれることは開発スタッフの全員が身にしみていた。

簡単らしい

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
超簡単な問題を朝食後にやってみた。13:39。。。遅い!!しかもpythonというよりlisperが好みそうな答えだ。しかしtest caseの書き間違いとn==0のケースで時間を無駄にした。


def deal(n, deck):
'''
>>> deal(3, '123123123')
('111', '222', '333')

>>> deal(4, '123123123')
('12', '23', '31', '12')

>>> deal(6, "012345012345012345")
('000', '111', '222', '333', '444', '555')

>>> deal(4, "111122223333")
('123', '123', '123', '123')

>>> deal(1, "012345012345012345")
('012345012345012345',)

>>> deal(6, "01234")
('', '', '', '', '', '')
>>> deal(2, "")
('', '')
>>> deal(0, "")
()
'''
if n < 1:
return ()
if len(deck) < n:
return ('',) * n
xs = deck[:n]
ys = deal(n, deck[n:])
return tuple((xs[i] + ys[i] for i in range(n)))

if __name__ == '__main__':
import doctest
doctest.testmod()

OpenID

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
tcの記事

普及はいまいちみたいね。OAuthとか出てきちゃったし。こういうのって技術的問題じゃなくて、「政治的」問題だからなぁ。

2009年5月8日金曜日

速度測定

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
また違う場所ではかってみた。
おっっせー。でもどういうわけだか体感速度は速い。レイテンシがちいさいようだ。

■速度.jp スピードテスト 高機能版 回線速度測定結果
http://zx.sokudo.jp/ v3.0.0
測定時刻 2009/05/08 19:08:39
回線種類/線路長/OS:モバイル回線/-/Linux/東京都
サービス/ISP:-/-
サーバ1[N] 1.67Mbps
サーバ2[S] 621kbps
下り受信速度: 1.6Mbps(1.67Mbps,209kByte/s)
上り送信速度: 360kbps(369kbps,46kByte/s)

emobile 速度測定

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
http://zx.sokudo.jp/

■速度.jp スピードテスト 高機能版 回線速度測定結果
http://zx.sokudo.jp/ v3.0.0
測定時刻 2009/05/08 11:50:13
回線種類/線路長/OS:モバイル回線/-/Linux/東京都
サービス/ISP:-/-
サーバ1[N] 2.00Mbps
サーバ2[S] 2.29Mbps
下り受信速度: 2.2Mbps(2.29Mbps,286kByte/s)
上り送信速度: 370kbps(378kbps,47kByte/s)

2009年5月7日木曜日

テクノロジではなく流通。

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
Kindle版書籍の売上げ数は印刷版書籍の35%に達している

iTune/iPodのような成功のpathに入りかけているのかもしれない。iPodがなくてもなんらかの音声ファイルをポータブルな機器に入れることは別にできたが、コンテンツの流通の観点からはなにも新しいことは無かった。

電子ブックリーダは死屍累々だという認識ですが、ついにキャズムを超えられそうな製品がでたといえるでしょう。アマゾンは書籍を売るサイトから、物販のサイトという方向に進化していたが、印刷物という「ドリル」が提供する書籍という「穴」をkindleという別の方法で提供することができたことを、成功したフィールドでルールを買えるようなことに柔軟な取り組みができたことに驚かないのは変だろう。

QR code生成

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
ちょっと検索してみた。まあ、google chartのapiを使うのが一番自然で、クオリティとスピード、大量リクエストへの対応能力が一番期待できるでしょう。

http://chart.apis.google.com/chart?cht=qr&chld=H&chs=100x100&chl=jPPgACbYzsEBIQ:cAn1ACAACAAA

をimgで呼びます。



backgammonbaseのentryでもprinter friendlyな出力にはqrcodeを埋め込みたいですね。

ところで、qrcodeを返すサーバを実装している人はネット上に山盛りいるのですが、どういうわけだかjpegで画像を返すサーバがいます。こういうのを見つけると、なんか頭が痛いのは僕だけ?

2009年5月5日火曜日

でかいキンドル

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
でっかいキンドルが出るらしい。

アマゾンはデジタル書籍の流通を支配するのだろうか?キンドルに情報を流す仕組みは解放される日が来るのだろうか・・・。

2009年5月3日日曜日

あったらいいシェルの機能

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

  • 複数の端末で、シェルの履歴を共有

  • 補完を履歴から拾う

  • レイテンシ隠蔽のためにリモートの補完をローカルで計算する

2009年5月2日土曜日

cname

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
ちょっと投げるqueryの回数が気になったが多分1回だろう。

[nori@asama]~% dig @192.168.2.64 www.tonic-water.com

; <<>> DiG 9.3.4-P1 <<>> @192.168.2.64 www.tonic-water.com
; (1 server found)
;; global options: printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 11004
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 1, ADDITIONAL: 1

;; QUESTION SECTION:
;www.tonic-water.com. IN A

;; ANSWER SECTION:
www.tonic-water.com. 86400 IN CNAME tonic-water.com.
tonic-water.com. 86400 IN A 124.155.113.117

facebook needle

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
haystack @ facebook engineering blogを読んだときのメモ。


The Photos application is one of Facebook’s most popular features. Up to date, users have uploaded over 15 billion photos which makes Facebook the biggest photo sharing website. For each uploaded photo, Facebook generates and stores four images of different sizes, which translates to a total of 60 billion images and 1.5PB of storage. The current growth rate is 220 million new photos per week, which translates to 25TB of additional storage consumed weekly. At the peak there are 550,000 images served per second. These numbers pose a significant challenge for the Facebook photo storage infrastructure.


needle以前の構成

  • * Upload tier receives users’ photo uploads, scales the original images and saves them on the NFS storage tier.
    アップロードを受け取ってNFSに書き込む層

  • * Photo serving tier receives HTTP requests for photo images and serves them from the NFS storage tier. HTTPリクエストを受け取ってNFSから画像を読み出して返す層

  • * NFS storage tier built on top of commercial storage appliances. 一般商用ストレージの上に構築されたNFS層。


NFSのmetaデータ読み出しがbottle neckになった。対策としてはCDNを使ったり、NFSのfile handleをcacheしたりしていた。

で、新しいheystackはどういう構成かというと

The new photo infrastructure merges the photo serving tier and storage tier into one physical tier. It implements a HTTP based photo server which stores photos in a generic object store called Haystack. The main requirement for the new tier was to eliminate any unnecessary metadata overhead for photo read operations, so that each read I/O operation was only reading actual photo data (instead of filesystem metadata). Haystack can be broken down into these functional layers

Haystackという汎用objectサーバを用意した。メタデータは読まない。リクエストしたらデータ自体を返す。

5つの機能からなる。

  • HTTP server

  • Photo Store

  • Haystack Object Store

  • Filesystem

  • Storage



Storage


10TBの容量が手に入る。2U storage blade。ハード構成なので割愛。

* 2 x quad-core CPUs
* 16GB – 32GB memory
* hardware raid controller with 256MB – 512MB of NVRAM cache
* 12+ 1TB SATA drives

raid6. raidカードのcacheはwrite用に使う。hddのキャッシュは殺してある。

File System


XFSだそうだ。extent baseなFile Systemはブロックを連続配置しやすいので、保存のためにブロックを複数必要とする画像ばっかりもつような用途では、有利ということらしい。

haystack



Haystack is a simple log structured (append-only) object store containing needles representing the stored objects. A Haystack consists of two files – the actual haystack store file containing the needles, plus an index file. The following figure shows the layout of the haystack store file:

Haystack = index file + needle file
needleは物理的に上書きされない。論理的に上書きされる。(同じkeyを持つneedleがappendされるとそちらが見えるようになる)


The main purpose of the index is to allow quick loading of the needle metadata into memory without traversing the larger Haystack store file, since the index is usually less than 1% the size of the store file.

index fileはメモリ上に持っておく。実体にはoffsetでアクセス。

データ書き込みは、データを同期で書き込んで、indexをあとから非同期で書き込む。indexは時々hddに書き込んであげる。クラッシュしたときはlast valid needle(推定するにまともにindexが保持されている範囲)まで、needle fileを読み進んでそこからindexに対して非同期書き込みを再開する。

空き領域はコンパクションをして回収。コンパクションとはdeleteやduplicatedな領域をskipしながらcopyすること。

Photo Store


needleのidをon memoryでもっている。scale済みを持つようにしている。

HTTP server


I/Oバウンドなので特になし。

gnubg configure

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

  • configureで渡すpathがbinaryに埋め込まれる.

  • そのpathは絶対path.

  • そのpathから起動に必要なデータを読み込む

  • rpmbuildしたい


なので

--datadir=${RPM_BUILD_ROOT}%{prefix}/share \

とかするとRPM_BUILD_ROOTがハードコードされてちまうんでこまったものだ。
fileをrpmbuild時に配置するpathと、埋め込みのために渡すpathを別々に渡したいんだよね~。

2009年5月1日金曜日

デジカメ 高解像度に意味が無い?

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
ここより

個人的には別の視点から高解像度に意味は無いと思っていた。
1. 暗くなりすぎ。(素子が小さいと感度が下がる、S/N比が悪化する)
2. データが重い。
3. jpegカラーでしか紙に焼けない。

300万画素以上だとfilmを超えているといわれていたが、そこの領域ではfilmと同じメカにはなんの保障も無かったとも言える。逆に言うと新しいメカが必要なのかもしれない。3に関しては高解像度な出力システムがほしい。

2009年4月29日水曜日

どのくらいエラーが起こるか?

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
WSDM09 key note.より
Sort 1 TB of data without parity: ends up "mostly sorted"とのこと。1999年の時点で1TBをソートする必要があったらしい。

pixivのslider

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

pixivではpage一覧をスクロールすることができる。この青いやつがスクロールだ。普通ならページへのジャンプをカチカチやっていく必要があるのだが、googleの検索結果と違ってpixivでは順位に意味が無いので、必須であろう。

第30回 スクローリングの小細工を思い出した。

カテゴリわけするなら、「取り扱う全体の量が多くひとつの範囲指定ウィジットではまかないきれないケースを取り扱うための工夫」といえるだろう。

git

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
gitでremoteのbranchを持ってきたり、remoteにbranchを持っていったり。効率的かどうかは知りませんが。

もっていく場合:

% git push <remote-repo> <local-branch>

持ってくる場合:

% git fetch <local-branch> <remote-repo:remote-branch>

2009年4月28日火曜日

体感速度

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク


この絵の出所はここpixivのロードの速さに逝きそうになった。

facebookは、重いとかいうレベルじゃない。ブラクラ級。いったいどうなってんじゃ。
はてな:重い。スターとかコメントのイメージのロードが遅いんだよ。ダサい。しかもよくとまってるし。
mixi: 若干重い。でもとまることは珍しい。
google: ほんとに海の向こうにあるのか?!

よく見ると、pixivではすべての画像が読み込まれるのはちょっと時間がかかっている。でもレイアウトが変わらないから重さを感じさせないのかもしれない。

googleさんに尋ねてみました。

ライブドアとGのサーバランニングコスト

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
[JOB BOARD] ライブドア社にてWebサービスを基盤から支える、とんがった技術者を募集

今は何人ぐらいでどれくらいのサーバを見られているのでしょうか

勤務は三交代制で、朝、昼、夜になっています。これは常に変わらないので、私の場合は朝の勤務を続けています。各チームは10名前後なので、全体では30人くらいのチーム体制になります。サーバは全部で7,800台となっています。

google コンテナ7台か。もちろん、誰のコンテンツをおいているかによって顧客対応の有無があるので単純比較できません。サクラが1万台ホストしている話の時もそうでしたが。

月にマシン1台あたり2万円の売り上げだと考えると20K x 7.8k = 160m, 1億6千万の売り上げ。まあ、台数が多ければもうちょっと安くなるとしても100mはくだらないだろう。だとすると3m/人月。2m/人月で仕事を請ける開発系より給料負荷比がよさそうですね。

しかし20k jpy/per machineの売上って、8k/per machineのコストだよね。diskはすべてのマシンに1Tはないだろうし、いくらなんでも80Gはありそう。一番高いケースで1Gあたり800jpy、まあありそうなのは200jpyとかか?。正確な数値と出典を忘れたけどgoogleは1Gあたり$1を切っていたと思うから、一人当たりの台数がそのまま利いているのだろう。土地代も安いだろうし。電気代はよくわかりません。

ステルス田代砲

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
techcrunchの記事「Time Magazine、4Chanによる乗っ取り行為を華麗にスルー」

内容を紹介しているブログによると、

time.comが投票に使っているurlは

http://www.timepolls.com/contentpolls/Vote.do
?pollName=time100_2009&id=1883924&rating=1

をhttp getする仕組みで、なーんの認証もかかっていなかったらしい。

そこで

http://fun.qinip.com/gen.php?id=1883924
&rating=1&amount=160

というurlをspamとしてどっかのページに埋め込み、踏んだ人が最低レーティングの1を160回投票するように仕向けた。

ratingは1~100の%だったのだが、値の範囲チェックが行われておらず(!)、そのうちマイナスのratingをvoteするようにした。その結果mootは300%をもらって、ほかの候補者には全部マイナスを投票。さすがにtime.comも気づいて、md5sumをつけるようにした。

Shortly afterward, Time.com changed the protocol to attempt to authenticate votes by requiring that a key be appended to the poll submission URL that consisted of an MD5 hash of the URL + a secret word (AKA ‘the salt’).


でもすぐにそのsaltが投票用のflashアプリの中にハードコードされていることがばれてしまい、自動投票botは再び機能し始めた。

shortly afterward, one of the members discovered that the ’salt’, the key to authenticating requests, was poorly hidden in Time.com’s voting flash application and could be extracted.


Mooterのscreen shot。ちゃんとguiがあるよ。

これを使って10,000,000票を投じたらしい。
先のspam linkを踏んだクラインといるIP1つから300票投票でき、また「串」を経由することでその数を増やした。

2009年4月27日月曜日

名前の秘密

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
昔、新卒さんに(関数だか、ファイル名だかで)「かっこいい名前無いですか?」と聞かれて、それは質問がよろしくないと諭したが、無視されたことを思い出した。

tsurezuregusa.comより


徒然草 第百十六段 

寺院の号、さらぬ万の物にも、名を付くる事、昔の人は、少しも求めず、たゞ、ありのまゝに、やすく付けけるなり。この比は、深く案じ、才覚をあらはさんとしたるやうに聞ゆる、いとむつかし。人の名も、目慣れぬ文字を付かんとする、益なき事なり。

何事も、珍しき事を求め、異説を好むは、浅才の人の必ずある事なりとぞ。


■ 現代語訳 

 お寺の名前や、その他の色々な物にも名前を付けるとき、昔の人は、何も考えずに、ただありのままに、わかりやすく付けたものだ。最近になって、よく考えたのかどうだか知らないが、小細工したことを見せつけるように付けた名前は嫌らしい。人の名前にしても。見たことのない珍しい漢字を使っても、まったく意味のないことである。

 どんなことでも、珍しいことを追求して、一般的じゃないものをありがたがるのは、薄っぺらな教養しかない人が必ずやりそうなことである。

2009年4月25日土曜日

Web + DBは森田さん特集?

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
Web + DB森田さん特集かと一瞬思った。ダンコガイのインタビューはあるし、連載は始めているし。

kindleをamazonが出したのは、amazonだからインパクトがでかいのでしょう。著作物の流通経路を持っているという意味で。ほかの会社のハードはどうでもいいです。注目は、iPod/iTuneの関係にkindle/amazonがなるかどうかです。

2009年4月24日金曜日

扇風機の季節

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
RAIDの乗っているマシンに扇風機の風を直撃するようにしたら温度が10度下がった。そして静かになった。

2009年4月22日水曜日

自動生成のunittestの力を感じるとき

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
サンプルを大量に持っていてfileのvalidatorを書くとき。

こんな感じでサンプルを集積してあるdirからテストケースを生成。どんなにアドホックなことをしても、このテストを通れば、正しいサンプルを必ずpassするvalidatorであることが確信できる。あとはこれにfuzzingしてあげればかなりのqualityを持つことになる。

#!/usr/bin/python
if __name__ == '__main__':
header = '''\
#!/usr/bin/env python
# -*- coding: us-ascii -*-
# vim: syntax=python
#
# Copyright 2006-2009 Noriyuki Hosaka bgnori@gmail.com
#


#WARNING!
#DO NOT EDIT THIS FILE.
#THIS FILE IS AUTO GENERATED.

import unittest
from bglib.record.snowietxt import Validator

class SnowietxtTest(unittest.TestCase):
'''
t = '''\
def test_%s(self):
f = open('%s')
v = Validator(f)
h = v.validate()
self.assertEqual(h.hexdigest(),
'%s')
'''

import sys
import tempfile
from subprocess import call

f = tempfile.TemporaryFile()
try:
call('sha1sum bglib/record/snowietxt/*.txt', shell=True, stdout=f)
f.seek(0)
xs = [line.split() for line in f.readlines()]
finally:
f.close()

print header
for i, x in enumerate(xs):
print t%(i, x[1], x[0])

2009年4月21日火曜日

後始末

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
方針が決まったのであとはただ作業。

普通に考えて、プロセス間通信でもしない限りmemory上のキャッシュはプロセス単位で閉じたものになる。ここにもこう書いてある。

each process builds up its own in-memory cache.

httplibで304と200が混じったのは、cacheに中身が入ったapache instanceに処理してもらえたかどうかなのだろう。

mpm.conf of /etc/httpd/conf.d
TheardLimitを1000にするのは怖くてできない。fileがそこまでたくさん作れる保証が無い。kernelの.configをいじればいいのだろうけど。

<IfModule worker.c>
StartServers 1
MinSpareThreads 16
MaxSpareThreads 32
MaxRequestsPerChild 0
ThreadLimit 512
ThreadsPerChild 512
MaxClients 512
</IfModule>


結果。
測定中にロードグラフを眺めると、CPU負荷はほとんど上がらずにNetworkのsentだけが100%の状態になる。

20%くらい改善したかな?

-c 300なら大丈夫。

[nori@asama]~/Desktop/work/srvtest% ab -n 100000 -c 300 "http://image.backgammonbase.com/image?gnubgid=4HPwATDgc%2FABMA%3AMAAAAAAAAAAA&height=300&width=400&css=minimal&format=png"
This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/

Benchmarking image.backgammonbase.com (be patient)
Completed 10000 requests
Completed 20000 requests
Completed 30000 requests
Completed 40000 requests
Completed 50000 requests
Completed 60000 requests
Completed 70000 requests
Completed 80000 requests
Completed 90000 requests
Finished 100000 requests


Server Software: Apache/2.2.3
Server Hostname: image.backgammonbase.com
Server Port: 80

Document Path: /image?gnubgid=4HPwATDgc%2FABMA%3AMAAAAAAAAAAA&height=300&width=400&css=minimal&format=png
Document Length: 17877 bytes

Concurrency Level: 300
Time taken for tests: 158.133125 seconds
Complete requests: 100000
Failed requests: 0
Write errors: 0
Total transferred: 1828222590 bytes
HTML transferred: 1789024272 bytes
Requests per second: 632.38 [#/sec] (mean)
Time per request: 474.399 [ms] (mean)
Time per request: 1.581 [ms] (mean, across all concurrent requests)
Transfer rate: 11290.32 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 3 94 84.1 93 3106
Processing: 113 378 18.2 379 1060
Waiting: 2 93 10.4 95 405
Total: 120 473 86.5 473 3956

Percentage of the requests served within a certain time (ms)
50% 473
66% 474
75% 474
80% 474
90% 474
95% 474
98% 474
99% 475
100% 3956 (longest request)

350にすると破綻の兆しでてくる。とはいえ、変更前の312よりはマシ。

[nori@asama]~/Desktop/work/srvtest% ab -n 100000 -c 350 "http://image.backgammonbase.com/image?gnubgid=4HPwATDgc%2FABMA%3AMAAAAAAAAAAA&height=300&width=400&css=minimal&format=png"
This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/

Benchmarking image.backgammonbase.com (be patient)
Completed 10000 requests
Completed 20000 requests
Completed 30000 requests
Completed 40000 requests
Completed 50000 requests
Completed 60000 requests
Completed 70000 requests
Completed 80000 requests
Completed 90000 requests
Finished 100000 requests


Server Software: Apache/2.2.3
Server Hostname: image.backgammonbase.com
Server Port: 80

Document Path: /image?gnubgid=4HPwATDgc%2FABMA%3AMAAAAAAAAAAA&height=300&width=400&css=minimal&format=png
Document Length: 17877 bytes

Concurrency Level: 350
Time taken for tests: 158.20219 seconds
Complete requests: 100000
Failed requests: 0
Write errors: 0
Total transferred: 1827205440 bytes
HTML transferred: 1788094492 bytes
Requests per second: 632.83 [#/sec] (mean)
Time per request: 553.071 [ms] (mean)
Time per request: 1.580 [ms] (mean, across all concurrent requests)
Transfer rate: 11292.10 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 4 119 245.5 102 9104
Processing: 121 426 78.2 410 1831
Waiting: 2 103 26.2 102 719
Total: 128 545 262.3 512 10024

Percentage of the requests served within a certain time (ms)
50% 512
66% 513
75% 514
80% 514
90% 516
95% 716
98% 821
99% 1025
100% 10024 (longest request)

2009年4月20日月曜日

ボトルネックは?

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
ばかもん・・・。すげー時間の無駄をした。

100BASE-TXでの最高速度は理論値では100Mbp、バイトにすると100/8=12.5MByte/s、つうことは、

Transfer rate: 11299.41 [Kbytes/sec] received

より早くなりようが無い。もはや100Mbpsでは帯域が足りない。逆に帯域が太くなることは無いから、自宅に箱をおいている間は回線速度に合わせて設定するのが正しいでしょうね。

gyaoでの測定結果、まあくだりだけなんですけど。

32.699Mbps
38.55Mbps


sokudo.jp

下り受信速度: 38Mbps(38.0Mbps,4.76MByte/s)
上り送信速度: 39Mbps(39.5Mbps,4.9MByte/s)

画像ファイル1枚30KByteと見込むと、150request/sしか捌けないので、それ以上にサーバを設定しようとすることは無駄! 200request/s捌ければ十分でしょう。200 request/sしても99%までフラット。ということは、これで最低限の目標はクリアできている。あとは負荷を小さくしたり、レスポンスタイムを短くしたり、メモリ消費を減らしたりかな。mem_cacheとforkの関係をはっきりさせておかないとね。

[nori@asama]~/Desktop/work/srvtest% ab -n 100000 -c 200 "http://image.backgammonbase.com/image?gnubgid=4HPwATDgc%2FABMA%3AMAAAAAAAAAAA&height=300&width=400&css=minimal&format=png"
This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/

Benchmarking image.backgammonbase.com (be patient)
Completed 10000 requests
Completed 20000 requests
Completed 30000 requests
Completed 40000 requests
Completed 50000 requests
Completed 60000 requests
Completed 70000 requests
Completed 80000 requests
Completed 90000 requests
Finished 100000 requests


Server Software: Apache/2.2.3
Server Hostname: image.backgammonbase.com
Server Port: 80

Document Path: /image?gnubgid=4HPwATDgc%2FABMA%3AMAAAAAAAAAAA&height=300&width=400&css=minimal&format=png
Document Length: 17877 bytes

Concurrency Level: 200
Time taken for tests: 157.993912 seconds
Complete requests: 100000
Failed requests: 0
Write errors: 0
Total transferred: 1827335546 bytes
HTML transferred: 1788205609 bytes
Requests per second: 632.94 [#/sec] (mean)
Time per request: 315.988 [ms] (mean)
Time per request: 1.580 [ms] (mean, across all concurrent requests)
Transfer rate: 11294.78 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 2 66 15.3 66 3043
Processing: 36 248 137.6 239 9197
Waiting: 1 116 137.7 111 9067
Total: 40 315 137.7 312 9225

Percentage of the requests served within a certain time (ms)
50% 312
66% 320
75% 325
80% 336
90% 351
95% 359
98% 362
99% 363
100% 9225 (longest request)

キャパの2分探索

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
いろいろパラメータを変えてみて気づいた点は、リクエストが多いと遅くなることは避けられない。ただ、requestの50%と99%が同じ時間でserveされないのはまずいだろう。

[nori@asama]~/Desktop/work/srvtest% ab -n 100000 -c 500 "http://image.backgammonbase.com/image?gnubgid=4HPwATDgc%2FABMA%3AMAAAAAAAAAAA&height=300&width=400&css=minimal&format=png"
This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/

Benchmarking image.backgammonbase.com (be patient)
Completed 10000 requests
Completed 20000 requests
Completed 30000 requests
Completed 40000 requests
Completed 50000 requests
Completed 60000 requests
Completed 70000 requests
Completed 80000 requests
Completed 90000 requests
Finished 100000 requests


Server Software: Apache/2.2.3
Server Hostname: image.backgammonbase.com
Server Port: 80

Document Path: /image?gnubgid=4HPwATDgc%2FABMA%3AMAAAAAAAAAAA&height=300&width=400&css=minimal&format=png
Document Length: 17877 bytes

Concurrency Level: 500
Time taken for tests: 157.941379 seconds
Complete requests: 100000
Failed requests: 0
Write errors: 0
Total transferred: 1827475512 bytes
HTML transferred: 1788411849 bytes
Requests per second: 633.15 [#/sec] (mean)
Time per request: 789.707 [ms] (mean)
Time per request: 1.579 [ms] (mean, across all concurrent requests)
Transfer rate: 11299.41 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 1 254 1150.4 68 45071
Processing: 17 526 477.7 394 17148
Waiting: 2 401 476.2 261 17019
Total: 28 781 1270.6 464 46283

Percentage of the requests served within a certain time (ms)
50% 464
66% 716
75% 722
80% 724
90% 735
95% 3239
98% 3471
99% 4502
100% 46283 (longest request)

[nori@asama]~/Desktop/work/srvtest% ab -n 100000 -c 250 "http://image.backgammonbase.com/image?gnubgid=4HPwATDgc%2FABMA%3AMAAAAAAAAAAA&height=300&width=400&css=minimal&format=png"
This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/

Benchmarking image.backgammonbase.com (be patient)
Completed 10000 requests
Completed 20000 requests
Completed 30000 requests
Completed 40000 requests
Completed 50000 requests
Completed 60000 requests
Completed 70000 requests
Completed 80000 requests
Completed 90000 requests
Finished 100000 requests


Server Software: Apache/2.2.3
Server Hostname: image.backgammonbase.com
Server Port: 80

Document Path: /image?gnubgid=4HPwATDgc%2FABMA%3AMAAAAAAAAAAA&height=300&width=400&css=minimal&format=png
Document Length: 17877 bytes

Concurrency Level: 250
Time taken for tests: 157.889007 seconds
Complete requests: 100000
Failed requests: 0
Write errors: 0
Total transferred: 1827087422 bytes
HTML transferred: 1788003384 bytes
Requests per second: 633.36 [#/sec] (mean)
Time per request: 394.723 [ms] (mean)
Time per request: 1.579 [ms] (mean, across all concurrent requests)
Transfer rate: 11300.75 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 2 68 42.9 68 3070
Processing: 24 325 53.9 329 4198
Waiting: 2 194 54.3 199 4062
Total: 30 393 69.7 401 6914

Percentage of the requests served within a certain time (ms)
50% 401
66% 401
75% 401
80% 401
90% 401
95% 401
98% 401
99% 401
100% 6914 (longest request)

[nori@asama]~/Desktop/work/srvtest% ab -n 100000 -c 175 "http://image.backgammonbase.com/image?gnubgid=4HPwATDgc%2FABMA%3AMAAAAAAAAAAA&height=300&width=400&css=minimal&format=png"
This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/

Benchmarking image.backgammonbase.com (be patient)
Completed 10000 requests
Completed 20000 requests
Completed 30000 requests
Completed 40000 requests
Completed 50000 requests
Completed 60000 requests
Completed 70000 requests
Completed 80000 requests
Completed 90000 requests
Finished 100000 requests


Server Software: Apache/2.2.3
Server Hostname: image.backgammonbase.com
Server Port: 80

Document Path: /image?gnubgid=4HPwATDgc%2FABMA%3AMAAAAAAAAAAA&height=300&width=400&css=minimal&format=png
Document Length: 17877 bytes

Concurrency Level: 175
Time taken for tests: 157.923406 seconds
Complete requests: 100000
Failed requests: 0
Write errors: 0
Total transferred: 1827328929 bytes
HTML transferred: 1788230915 bytes
Requests per second: 633.22 [#/sec] (mean)
Time per request: 276.366 [ms] (mean)
Time per request: 1.579 [ms] (mean, across all concurrent requests)
Transfer rate: 11299.78 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 1 66 4.2 67 73
Processing: 18 209 33.4 207 4130
Waiting: 2 75 34.2 73 3994
Total: 22 275 33.4 274 4187

Percentage of the requests served within a certain time (ms)
50% 274
66% 277
75% 279
80% 281
90% 284
95% 286
98% 287
99% 289
100% 4187 (longest request)
[nori@asama]~/Desktop/work/srvtest% ab -n 1000 -c 10 "http://image.backgammonbase.com/image?gnubgid=4HPwATDgc%2FABMA%3AMAAAAAAAAAAA&height=300&width=400&css=minimal&format=png"
This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/

Benchmarking image.backgammonbase.com (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Finished 1000 requests


Server Software: Apache/2.2.3
Server Hostname: image.backgammonbase.com
Server Port: 80

Document Path: /image?gnubgid=4HPwATDgc%2FABMA%3AMAAAAAAAAAAA&height=300&width=400&css=minimal&format=png
Document Length: 17877 bytes

Concurrency Level: 10
Time taken for tests: 1.582884 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Total transferred: 18307218 bytes
HTML transferred: 17914922 bytes
Requests per second: 631.76 [#/sec] (mean)
Time per request: 15.829 [ms] (mean)
Time per request: 1.583 [ms] (mean, across all concurrent requests)
Transfer rate: 11294.57 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 3 0.9 3 6
Processing: 7 11 1.4 12 16
Waiting: 0 3 1.1 3 6
Total: 7 15 0.6 15 19

Percentage of the requests served within a certain time (ms)
50% 15
66% 15
75% 15
80% 15
90% 15
95% 16
98% 16
99% 17
100% 19 (longest request)