2012-04-12 36 views
10

我通过boto测试dynamodb,发现它基于hashkey,rangekey条件查询检索数据集的速度惊人地慢。我已经看到一些关于导致ssl(is_secure)比非ssl快6倍的奇怪事件的讨论,我可以证实这一发现。但即使使用ssl,我也会用1-2秒的时间在相当小的数据集上使用hashkey /范围键条件(少于1K条记录)检索300条记录。Python Boto Dynamodb对范围键上的小记录集检索性能非常低

正在运行profilehooks profiler我看到很多额外的时间花在ssl.py到20617次调用的次序以检索300条记录。即使在每次录制10个电话时,它仍然是我预期的6倍。这是在一个中等的实例 - 虽然在微型实例上也会出现相同的结果。 500次读取/秒1000次写入/秒供应,不记录任何节流。

我已经看过要做批量请求,但无法使用范围键条件为我消除了该选项。

任何想法,我失去了时间将不胜感激!

144244 function calls in 2.083 CPU seconds 

排序:累计时间,内部时间,来电数

ncalls tottime percall cumtime percall filename:lineno(function) 
    1 0.001 0.001 2.083 2.083 eventstream.py:427(session_range) 
    107 0.006 0.000 2.081 0.019 dynamoDB.py:36(rangeQ) 
    408 0.003 0.000 2.073 0.005 layer2.py:493(query) 
    107 0.001 0.000 2.046 0.019 layer1.py:435(query) 
    107 0.002 0.000 2.040 0.019 layer1.py:119(make_request) 
    107 0.006 0.000 1.988 0.019 connection.py:699(_mexe) 
    107 0.001 0.000 1.916 0.018 httplib.py:956(getresponse) 
    107 0.002 0.000 1.913 0.018 httplib.py:384(begin) 
    662 0.049 0.000 1.888 0.003 socket.py:403(readline) 
20617 0.040 0.000 1.824 0.000 ssl.py:209(recv) 
20617 0.036 0.000 1.785 0.000 ssl.py:130(read) 
20617 1.748 0.000 1.748 0.000 {built-in method read} 
    107 0.002 0.000 1.738 0.016 httplib.py:347(_read_status) 
    107 0.001 0.000 0.170 0.002 mimetools.py:24(__init__) 
    107 0.000 0.000 0.165 0.002 rfc822.py:88(__init__) 
    107 0.007 0.000 0.165 0.002 httplib.py:230(readheaders) 
    107 0.001 0.000 0.031 0.000 __init__.py:332(loads) 
    107 0.001 0.000 0.028 0.000 decoder.py:397(decode) 
    107 0.008 0.000 0.026 0.000 decoder.py:408(raw_decode) 
    107 0.001 0.000 0.026 0.000 httplib.py:910(request) 
    107 0.003 0.000 0.026 0.000 httplib.py:922(_send_request) 
    107 0.001 0.000 0.025 0.000 connection.py:350(authorize) 
    107 0.004 0.000 0.024 0.000 auth.py:239(add_auth) 
3719 0.011 0.000 0.019 0.000 layer2.py:31(item_object_hook) 
    301 0.010 0.000 0.018 0.000 item.py:38(__init__) 
22330 0.015 0.000 0.015 0.000 {method 'append' of 'list' objects} 
    107 0.001 0.000 0.012 0.000 httplib.py:513(read) 
    214 0.001 0.000 0.011 0.000 httplib.py:735(send) 
    856 0.002 0.000 0.010 0.000 __init__.py:1034(debug) 
    214 0.001 0.000 0.009 0.000 ssl.py:194(sendall) 
    107 0.000 0.000 0.008 0.000 httplib.py:900(endheaders) 
    107 0.001 0.000 0.008 0.000 httplib.py:772(_send_output) 
    107 0.001 0.000 0.008 0.000 auth.py:223(string_to_sign) 
    856 0.002 0.000 0.008 0.000 __init__.py:1244(isEnabledFor) 
    137 0.001 0.000 0.008 0.000 httplib.py:603(_safe_read) 
    214 0.001 0.000 0.007 0.000 ssl.py:166(send) 
    214 0.007 0.000 0.007 0.000 {built-in method write} 
3311 0.006 0.000 0.006 0.000 item.py:186(__setitem__) 
    107 0.001 0.000 0.006 0.000 auth.py:95(sign_string) 
    137 0.001 0.000 0.006 0.000 socket.py:333(read) 
+2

感谢您的数据。这是我最近一直在研究的内容。至少可以说,HTTP和HTTPS之间的差异令人费解。这是来自EC2实例吗?该表的预配置吞吐量是多少? – garnaat 2012-04-12 13:46:02

+1

在亚马逊EC2介质实例上以500次读取/秒和1000次写入进行调配。我尝试过增加和减少吞吐量,也尝试不同大小的实例,结果没有实质性变化。减少返回的属性(从10到2)的影响很小。 – jaredmsaul 2012-04-12 13:56:33

+1

我看到这些信息都在您的原始文章中。抱歉。如果您没有看到任何节流事件(并且您不应该处于该配置级别),那么问题全部在客户端。你有没有尝试做更多的请求(例如10K左右)。这将预热高速缓存并将更好地表示潜在的吞吐量。然而,很显然httplib中有一些奇怪的事情发生。我正在调查,看看我是否可以追查。 – garnaat 2012-04-12 14:11:55

回答

12

这不是一个完整的答案,但我认为这是值得在这个时候发布它。

在过去的几周里,我听到过几个这样的消息。我能够重现HTTPS的异常比HTTP快得多,但无法追踪它。似乎这个问题对Python/boto来说是独一无二的,但事实证明,在C#/ .Net上发现了同样的问题,并且调查发现底层问题是在Python和.Net库中使用了Nagle's algorithm。在.Net中,很容易将其关闭,但不幸的是,在Python中并不容易。

为了测试这个,我编写了一个简单的脚本,在循环中执行了1000个GetItem请求。正在获取的物品非常小,远低于1K。在美国东-1区域的m1.medium实例上的Python 2.6.7运行由此产生的结果:

>>> http_data = speed_test(False, 1000) 
dynamoDB_speed_test - RUNTIME = 53.120193 
Throttling exceptions: 0 
>>> https_data = speed_test(True, 1000) 
dynamoDB_speed_test - RUNTIME = 8.167652 
Throttling exceptions: 0 

注意,有在表中,以避免该服务的任何节流足够的供应能力和HTTP和HTTPS之间意想不到的差距很明显。

接下来我跑了相同的测试在Python 2.7.2:

>>> http_data = speed_test(False, 1000) 
dynamoDB_speed_test - RUNTIME = 5.668544 
Throttling exceptions: 0 
>>> https_data = speed_test(True, 1000) 
dynamoDB_speed_test - RUNTIME = 7.425210 
Throttling exceptions: 0 

所以,2.7似乎已经解决了这个问题。然后,我在2.6.7中对httplib.py应用了一个简单的补丁。该补丁只是设置与HttpConnection的对象关联的插座TCP_NO_DELAY财产,像这样:

self.sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) 

我再重新运行测试的2.6.7:

>>> http_data = speed_test(False, 1000) 
dynamoDB_speed_test - RUNTIME = 5.914109 
Throttling exceptions: 0 
>>> https_data = speed_test(True, 1000) 
dynamoDB_speed_test - RUNTIME = 5.137570 
Throttling exceptions: 0 

更妙的是,尽管仍然是一个HTTPS预计比HTTP更快。很难知道这种差异是否显着。

所以,我正在寻找方法来编程地配置HTTPConnection对象的套接字以正确配置TCP_NO_DELAY。在httplib.py中获取它并不容易。如果可能的话,我现在最好的建议是使用Python 2.7。

+0

+1进行详细分析并发布,确实令人困惑 - 真是太感谢了! – 2012-04-14 15:51:43