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

时间:2012-04-12 12:59:12

标签: python performance boto amazon-dynamodb

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

运行profilehooks profiler我看到在ssl.py中花费了大量无关的时间到20617 ncalls的顺序来检索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)

1 个答案:

答案 0 :(得分:12)

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

在过去的几周里,我听到过几个人的报道。我能够重现HTTPS的异常比HTTP快得多,但无法跟踪它。似乎这个问题对于Python / boto来说是独一无二的,但事实证明在C#/ .Net上发现了同样的问题,并且调查发现潜在的问题是在Python和Python中使用Nagle's algorithm。网络图书馆。在.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

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