conn = pymongo.Connection('localhost', 27017)
db = conn['perform']
coll = db['test']
testdata = []
def init_testdata():
for i in xrange(1000):
s1 = ''.join([random.choice(string.hexdigits) for j in xrange(16)])
s2 = ''.join([random.choice(string.letters) for j in xrange(200)])
testdata.append((s1, s2))
init_testdata()
def insert_mongo():
for s1, s2 in testdata: coll.insert({'_id': s1, 'content': s2})
def find_mongo():
for s1, s2 in testdata:
s = coll.find_one({'_id': s1})
def testfunc(funcname, times = 1000):
from timeit import Timer
t = Timer("%s()" % funcname, "from __main__ import *")
print 'funcname: %s used %f' % (funcname, t.timeit(times) / times)
if __name__ == '__main__':
# os.fork()
# os.fork()
init_testdata()
testfunc('insert_mongo', times = 100)
testfunc('find_mongo', times = 100)
这个代码,在直接执行的情况下,获得结果是这样的。
funcname: insert_mongo used 0.179303
折合成iops,也就是5500req/s的样子。打开os.fork后,结果变成了这样。
funcname: insert_mongo used 0.516131
funcname: insert_mongo used 0.526213
只有3850req/s左右,我靠,比单进程慢那么多?打开四个进程试试?
funcname: insert_mongo used 1.039754
funcname: insert_mongo used 1.058093
funcname: insert_mongo used 1.058598
funcname: insert_mongo used 1.059101
基本稳定下来了,差不多4000req/s的样子。而且,通过top发现,最关键的问题不在于io和内存,而是mongodb这货只有一个进程,最高吃到100%的CPU——也就是——无法利用多核。
幸好,在读取测试中,情况不是那么糟糕。在单进程下是下面这样子
funcname: find_mongo used 0.350096
2850req/s,双进程就变成了这样子。
funcname: find_mongo used 0.220384
funcname: find_mongo used 0.221446
9000req/s!不但性能有所上升,而且更为惊喜的是,在top中检测发现,主要CPU消耗都放到了python这端。而分布系统的常识告诉我们,客户端的压力(就是应用服务器的压力)是可以很容易的通过添加服务器来解决的。在贝壳当前这台双核的机器上是无法进行进一步测试了,不过按照目前的状况预估,查询时即使只能使用单核,也可以支持10000req/s以上的性能。
又是一个典型的高读低写数据库呐。也罢也罢,nosql中也就mongo的各种特性比较接近sql数据库,用来跳过ORM层直接做系统比较合适。如果使用memcache或者redis,性能倒是上去了,用起来就未免太蛋疼了一点。不过偷偷的透露一点,贝壳估计,使用redis后,性能还能上去5倍。