Python Boto Dynamodb对范围键上的小记录集检索的性能非常慢

jar*_*aul 10 python performance boto amazon-dynamodb

我正在通过boto测试dynamodb,并发现基于hashkey,rangekey条件查询检索数据集的速度非常慢.我已经看到一些关于导致ssl(is_secure)执行速度比非ssl快6倍的奇怪性的讨论,我可以确认找到.但是,即使使用SSL我看到1-2秒检索300条记录使用一个相当小的数据集(小于1K记录)一个hashkey /范围键条件.

运行profilehooks探查我看到很多在ssl.py花的20617个ncalls的顺序检索300条记录无关的时间.看起来即使每次记录10个电话,它仍然比我预期的多6倍.这是在一个中型实例上 - 尽管在微型实例上会出现相同的结果.500次读取/秒1000次写入/秒配置,不记录任何节流.

我已经看过做批处理请求但是无法使用范围键条件为我省去了这个选项.

任何关于我失去时间的想法都将不胜感激!

  144244 function calls in 2.083 CPU seconds
Run Code Online (Sandbox Code Playgroud)

订购方式:累计时间,内部时间,通话次数

  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)
Run Code Online (Sandbox Code Playgroud)

gar*_*aat 12

这不是一个完整的答案,但我认为此时值得发布.

在过去的几周里,我听过几个人的报道.我能够重现HTTPS的异常比HTTP快得多但无法跟踪它.似乎这个问题是Python/boto独有的,但事实证明在C#/ .Net上发现同样的问题,并且调查发现潜在的问题是在Python和.Net库中使用Nagle算法.在.Net中,很容易将其关闭但不幸的是,它在Python中并不那么容易.

为了测试这个,我编写了一个简单的脚本,在一个循环中执行了1000个GetItem请求.正在获取的项目非常小,远低于1K.在us-east-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
Run Code Online (Sandbox Code Playgroud)

请注意,表中有足够的预配置容量可以避免服务的任何限制,并且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
Run Code Online (Sandbox Code Playgroud)

所以,2.7似乎已经解决了这个问题.然后我在2.6.7中对httplib.py应用了一个简单的补丁.补丁只是设置与HTTPConnection对象关联的套接字的TCP_NO_DELAY属性,如下所示:

self.sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
Run Code Online (Sandbox Code Playgroud)

然后我重新运行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
Run Code Online (Sandbox Code Playgroud)

甚至更好,尽管HTTPS的预期时间比HTTP更快.很难知道这种差异是否显着.

所以,我正在寻找以编程方式为HTTPConnection对象配置套接字以正确配置TCP_NO_DELAY的方法.在httplib.py中获取它并不容易.我目前最好的建议是尽可能使用Python 2.7.