分散関数呼び出し
Posted feedbacks - Python
とりあえずPython使ってCGIサーバを立てて見ました。
http://blueeye.bne.jp:7777/cgi-bin/discount.py?2000&33
↑のアドレスにアクセスすると、次のように帰ってきます。
> 販売価格 1340円(定価2000円から33%引き)
以下の記事を参考にしてHTTPサーバを走らせて、その上で下にあるコードを走らせています。
http://coreblog.org/ats/python-de-cgi
今日一日くらい、鯖を立てておきますので遊びたい方はご自由に。
スレッドプールもないようなHTTP鯖なので、それなりに遅いと思いますが、速度測定はそのうちやります。
(ネットゲームのサーバが動いているので、正確な速度測定は難しいと思います)
http://blueeye.bne.jp:7777/cgi-bin/discount.py?2000&33
↑のアドレスにアクセスすると、次のように帰ってきます。
> 販売価格 1340円(定価2000円から33%引き)
以下の記事を参考にしてHTTPサーバを走らせて、その上で下にあるコードを走らせています。
http://coreblog.org/ats/python-de-cgi
今日一日くらい、鯖を立てておきますので遊びたい方はご自由に。
スレッドプールもないようなHTTP鯖なので、それなりに遅いと思いますが、速度測定はそのうちやります。
(ネットゲームのサーバが動いているので、正確な速度測定は難しいと思います)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | # -*- coding: utf-8 -*-
#-------------------------以下サーバー側コード
import sys
if(len(sys.argv) == 2):
(price,discount) = sys.argv[1].split("&")
price = int(price)
discount = int(discount)
print "Content-Type: text/plain"
print ""
print "販売価格 %d円(定価%d円から%d%%引き)" % (int(price * (100.0-discount)/100.0 ), price, discount)
else:
print "Content-Type: text/plain"
print ""
print "引数エラー"
# -*- coding: utf-8 -*-
#------------------------以下呼び出し側コード
import urllib
def pricestring(price, discount):
return urllib.urlopen("http://blueeye.bne.jp:7777/cgi-bin/discount.py?%d&%d" % (price, discount)).read()
print unicode(pricestring(2000,20), "utf8")
|
何なんだこの遅さは。 直列で100回実験したら18秒強。 10個のスレッドで、並列に10回ずつ取りに行ったら6.5秒。 多分コンソール周りのPrintに時間食っているのかなぁ。 コンソールを表示しなければ、早くなるのか? まぁ、裏でネットゲームの鯖が動いているところで、実験ってのが無茶な話ですが。 鯖のPCのスペックはこんな感じ。 Pen4 2.8GHz HT RAM 512MB OS XP so-net ADSL12M線 ネットゲームのサーバプログラムがCPUパワーの80%を常時消費 測定したクライアントPC sinetに接続されている某大学のPC Pen4 3.2GHz HT RAM 2GB OS XP
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | # -*- coding: utf-8 -*-
import urllib
import time
import threading
def pricestring(price, discount):
return urllib.urlopen("http://blueeye.bne.jp:7777/cgi-bin/discount.py?%d&%d" % (price, discount)).read()
t1 = time.time()
for x in xrange(100):
print unicode(pricestring(x * 1000, 20),"utf8")
t2 = time.time()
class TEST_THREAD(threading.Thread):
def __init__(self, price, discount):
threading.Thread.__init__(self)
self.price = price
self.discount = discount
def run(self):
for x in xrange(10):
print unicode(pricestring(self.price, self.discount + x),"utf8")
threadList = []
for x in xrange(10):
threadList.append(TEST_THREAD(x * 1000 , 20))
threadList[-1].start()
for t in threadList:
t.join()
t3 = time.time()
print "series time",t2 - t1
print "pararells time",t3 - t2
|
pythonの標準ライブラリに含まれているXML-RPCを 使ってみました。 とはいっても、参考にしたIBMのサイトに乗っているサンプル そのもののような気がしないでもない。 実は数値のコンマ区切りの方が大変でした。 測定環境 同一マシン上で実行 Athlon XP 1700+ 512MB python 2.5 実行時間 画面出力を行う 64秒 画面出力を行わない 112秒
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | #
# server.py
#
# -*- coding: utf-8 -*-
import SimpleXMLRPCServer
class PliceString:
def plicestring(self, p, d):
def f(i):
s = str(i)
n = len(s)
return ','.join([s[i<0 and -n or i:i+3] for i in range(n-(n+2)/3*3, n, 3)])
return '販売価格 %s円 (定価%s円から%d%%引き)' % (f(int(p*(1-d*0.01))), f(p), d)
ps = PliceString()
sv = SimpleXMLRPCServer.SimpleXMLRPCServer(('localhost', 8888))
sv.register_instance(ps)
sv.serve_forever()
#
# client.py
#
# -*- coding: utf-8 -*-
import xmlrpclib
import time
sv = xmlrpclib.ServerProxy('http://localhost:8888/')
t0 = time.time()
for i in range(10000):
sv.plicestring(2000, 20)
# print sv.plicestring(2000, 20)
print time.time() - t0
|
Twisted のPerspectiveBroker使ってみました。 ---- # 1 Client: OS: OpenBSD CPU: SUNW,UltraSPARC-IIi (rev 1.2) @ 299.768 MHz Python: 2.5 (r25:51908, Mar 11 2007, 13:48:09) \n[GCC 3.3.5 (propolice)] Twisted: 2.5.0 Server: OS: FreeBSD release-6.2 CPU: Intel Celeron (634.78-MHz 686-class CPU) RAM: 254MB Python 2.4.4 (GCC3.4.6 FreeBSD 20060305) Twisted: 2.5.0 経路は100Base-TX 89.23s user 8.78s system 86% cpu 1:53.92 total ---- # 2 上記 Client環境、同一ホスト内 94.81s user 23.25s system 53% cpu 3:42.37 total ---- # 3 同一ホスト内 OS: CentOS CPU: Intel(R) Xeon(R) 2.66GHz RAM: 2GB Python: '2.5.1 (r251:54863, Jul 28 2007, 19:05:07) \n[GCC 3.4.6 20060404 (Red Hat 3.4.6-8)] Twisted: 2.5.0 2.95s user 0.25s system 52% cpu 6.133 total
see: http://www.artima.com/weblogs/viewpost.jsp?thread=156396
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | # ※ 文字コード等は、各環境に合わせて下さい。
## commify.py
# 参考: http://pleac.sourceforge.net/pleac_python/numbers.html
# Putting Commas in Numbers
def simple_glue(*funcs):
"glue functions: simple_glue(f, g, h) -> lambda arg: h(g(f(arg)))"
return lambda arg: reduce(lambda n,m:m(n), funcs, arg)
def digits_div_by(num):
return lambda xs: reduce(lambda (n,m),i: (n+[xs[m:i]],i),
reversed(xrange(len(xs),0,-num)),
([],0))[0]
commify = simple_glue(str, digits_div_by(3), ",".join)
##############################
# サーバー
# -*- coding: euc-jp -*-
from twisted.spread import pb
from twisted.internet import reactor
from commify import commify
PORT = 10800
FORMAT = u"販売価格%(price)s円 (定価 %(original_price)s円から%(discount)d%引き)"
class PriceStringService(pb.Root):
def remote_pricestring(self, original_price, discount):
price = commify(int(original_price * ((100.0 - discount) / 100.0)))
original_price = commify(original_price)
return FORMAT % vars()
if __name__ == '__main__':
reactor.listenTCP(PORT, pb.PBServerFactory(PriceStringService()))
reactor.run()
##############################
# クライアント
# ホスト・アドレス、ポート番号を指定して実行。
# -*- coding: euc-jp -*-
import sys
import itertools
from twisted.spread.pb import PBClientFactory
from twisted.internet import reactor
if __name__ == '__main__':
host = sys.argv[1]
port = int(sys.argv[2])
def failure(_):
reactor.stop()
def connected(perspective):
counter = itertools.count()
def callloop():
d = perspective.callRemote("pricestring", 2000, 20)
d.addCallbacks(success, failure)
def success(result):
print result.encode("euc-jp")
if counter.next() < 10000:
callloop()
else:
reactor.stop()
callloop()
factory = PBClientFactory()
reactor.connectTCP(host, port, factory)
factory.getRootObject().addCallbacks(connected, failure)
reactor.run()
|
OS: Windows XP sp2 CPU: Intel Celeron 1.4GHz RAM: 480MB Python: 2.5 PyRO: 3.7 同一サーバー内。実行時間 20秒
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | #### Server
# -*- coding: utf-8 -*-
from Pyro.core import ObjBase, Daemon, initServer
def calc_sales_price(price, discount):
return int(price * (1-discount*0.01))
def commify(amount, num=3, sep=","):
def _commify(s):
a,b = s[:-num],s[-num:]
return commify(a)+sep+b if a else b
return _commify(str(amount))
class PriceString(ObjBase):
def pricestring(self, price, discount):
FORMAT = u"販売価格%(sales_price)s円 (定価 %(price)s円から%(discount)d%引き)"
sales_price = commify(calc_sales_price(price, discount))
price = commify(price)
return FORMAT % vars()
if __name__ == '__main__':
initServer()
daemon = Daemon()
daemon.connect(PriceString(), "pricestring")
daemon.requestLoop()
#### Client
from Pyro.core import getProxyForURI
if __name__ == '__main__':
remote = getProxyForURI(r"PYROLOC://localhost:7766/pricestring")
for _ in xrange(10000):
print remote.pricestring(2000, 20)
|
Rpyc (Remote Python call) による実装です。 OS: Windows XP CPU: Celeron 1.4GHz RAM: 480MB Python: 2.5 Rpyc: 2.6 同一サーバー内でテスト。 実行時間: 約12秒
see: Remote Python Call
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | # -*- coding: utf-8 -*-
# ./pricestring.py
# サーバーj実行時のsys.pathの通ったところに置く。
# サーバーの実行は、
# > python -m Rpyc.Servers.simple_server.py
def Y(f):
"simple Y-combinator"
_f = lambda v: f(_f, v)
return _f
def commify(v, num=3, sep=","):
return Y(lambda f,s:(lambda a,b:(f(a)+sep+b if a else b))(s[:-num],s[-num:]))(str(v))
def calc_sales_price(price, discount):
return int((price/100.0) * (100-discount))
def pricestring(price, discount):
sales_price = commify(calc_sales_price(price, discount))
price = commify(price)
return u"販売価格%(sales_price)s円 (定価%(price)s円から%(discount)d%%引き)" % vars()
#### クライアント
from time import sleep
from Rpyc import SocketConnection, Async
connection = SocketConnection("localhost")
pricestring = Async(connection.modules.pricestring.pricestring)
for _ in xrange(10000):
c = pricestring(2000,20)
while not c.is_ready:
sleep(0.1)
print c.result
|
お題とは関係ないけど、commify関数に使ってる、 Y-combinatorの表記の手続きなし版。
1 2 3 4 5 6 7 8 | def Y(f):
return (lambda g: lambda arg: f(g(g),arg))((lambda g: lambda arg: f(g(g),arg)))
# デコレータとしての利用例
@Y
def fact(f, n):
return 1 if n == 0 else n*f(n-1)
|
Thrift使ってみました。release-20070401版です。
サーバ/クライアント共にPython。
初めてなので、Thriftの作法等は、まだよく解ってません。
※注意点: サーバー・クライアントのスクリプト 共に、
gen-py以下をモジュール探索対象のPATHに含めること。
PYTHONPATHに設定、もしくはモジュールのインポート前に、下のコードを追加。
import sys
sys.path.append("./gen-py")
※ メモ
C++のTNonblockingServerがlibeventを利用してるので、
kqueueやepollが使える環境だと、パフォーマンス向上が期待できそうです。(未計測)
Thriftは、言語以外にも各言語毎にserverやprotocllも組み合わせて使うことが出来るみたいなので、
C++/TNonblockingServer/boost.Pythonもやってみようかな。
see: Facebook Developers | Thrift
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | ##############################
# pricestring.thrift
service PriceStringService {
string pricestring(1:i32 price, 2:i32 discount)
}
##############################
# Server
from locale import format
class PriceStringHandler:
def pricestring(self, price, discount):
calc_sales_price = lambda n,m: n*(1-(m*0.01))
commify = lambda n: format("%d", n, grouping=True)
template = u"販売価格%s円 (%s円から%s%引き)"
return (template % (commify(calc_sales_price(price,discount)), commify(price), discount)).encode('utf-8')
if __name__ == '__main__':
from locale import setlocale, LC_NUMERIC
setlocale(LC_NUMERIC, '')
from pricestring import PriceStringService
from thrift.transport.TSocket import TServerSocket
from thrift.server.TServer import TSimpleServer
handler = PriceStringHandler()
processor = PriceStringService.Processor(handler)
server = TSimpleServer(processor, TServerSocket(9090))
server.serve()
##############################
# Client
# データはutf-8 で渡ってきます。< client.pricestring
# 端末に表示する時など、文字コードは適切なものにエンコードしてください。
if __name__ == '__main__':
from pricestring import PriceStringService
from thrift import Thrift
from thrift.transport.TSocket import TSocket
from thrift.transport.TTransport import TBufferedTransport
from thrift.protocol.TBinaryProtocol import TBinaryProtocol
transport = TBufferedTransport(TSocket("localhost", 9090))
protocol = TBinaryProtocol(transport)
client = PriceStringService.Client(protocol)
transport.open()
for _ in xrange(10000):
print client.pricestring(2000, 20).decode('utf-8')
transport.close()
|




沢渡 みかげ
#3401()
Rating0/0=0.00
[ reply ]