2012-04-12 5 views
10

Ich teste Dynamodb über Boto und habe festgestellt, dass es überraschend langsam beim Abrufen von Datensätzen basierend auf Hashschlüssel, rangekey Zustand Abfragen. Ich habe einige Diskussionen über die Seltsamkeit gesehen, die bewirkt, dass ssl (is_secure) ungefähr 6x schneller als nicht-ssl ausführt, und ich kann dieses Finden bestätigen. Aber selbst wenn ich ssl benutze, sehe ich 1-2 Sekunden, um 300 Datensätze mit einer Hashkey-/Bereichsschlüsselbedingung für einen ziemlich kleinen Datensatz (weniger als 1K Datensätze) abzurufen.Python Boto Dynamodb sehr langsam Leistung für kleine Datensatz-Retrieval auf Bereich Schlüssel

Laufender ProfilHooks Profiler Ich sehe eine Menge überflüssiger Zeit in ssl.py in der Reihenfolge 20617 nCalls, um die 300 Datensätze abzurufen. Es scheint, als ob es sogar bei 10 Anrufen pro Platte immer noch 6x mehr gibt, als ich es erwarten würde. Dies ist auf einer mittleren Instanz - obwohl die gleichen Ergebnisse auf einer Mikroinstanz auftreten. 500 Lesevorgänge/Sek. 1000 Schreibvorgänge/Sek. Provisioning ohne protokollierte Drosseln.

Ich habe versucht, eine Stapelanforderung zu machen, aber die Unfähigkeit, Bereichsschlüsselbedingungen zu verwenden, beseitigt diese Option für mich.

Alle Ideen auf, wo ich Zeit verlieren würde sehr geschätzt werden !!

144244 function calls in 2.083 CPU seconds 

Auftraggeber: Dies ist keine vollständige Antwort kumulative Zeit, interne Zeit, rufen Sie

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

Danke für die Daten. Dies ist etwas, das ich kürzlich untersucht habe. Das Delta zwischen HTTP und HTTPS ist verwirrend, um es gelinde auszudrücken. Geht das von einer EC2-Instanz? Wie hoch ist der bereitgestellte Durchsatz für die Tabelle? – garnaat

+1

Bereitstellung mit 500 Lese-/s und 1000 Schreibvorgängen pro Sekunde auf einer Amazon EC2-Medium-Instanz. Ich habe versucht, den Durchsatz zu erhöhen und zu verringern und auch Instanzen unterschiedlicher Größe ohne wesentliche Änderung der Ergebnisse. Das Verringern zurückgegebener Attribute (von beispielsweise 10 bis 2) hat einen kleinen Effekt. – jaredmsaul

+1

Ich sehe, dass info alles in Ihrem ursprünglichen Beitrag war. Es tut uns leid. Wenn keine Drosselungsereignisse auftreten (und Sie nicht auf dieser Bereitstellungsebene sein sollten), liegt das Problem auf der Clientseite. Haben Sie versucht, viel mehr Anfragen (z. B. 10k oder so) zu tun. Dies wird die Caches aufwärmen und den möglichen Durchsatz besser darstellen. Es ist jedoch klar, dass in httplib etwas Seltsames vor sich geht. Ich untersuche, ob ich es aufspüren kann. – garnaat

Antwort

12

zählen, aber ich dachte, es wert war zu diesem Zeitpunkt der Veröffentlichung.

Ich habe solche Berichte von ein paar Leuten in den letzten Wochen gehört. Ich war in der Lage, die Anomalie von HTTPS zu reproduzieren, die erheblich schneller als HTTP ist, aber nicht in der Lage war, es aufzuspüren. Es schien, als ob dieses Problem für Python/Boto einzigartig war, aber es stellte sich heraus, dass das gleiche Problem in C#/.Net gefunden wurde und dass das zugrunde liegende Problem die Verwendung der Nagle's algorithm in den Python- und .Net-Bibliotheken war. In .Net ist es einfach, das auszuschalten, aber in Python ist es leider nicht so einfach.

Um dies zu testen, schrieb ich ein einfaches Skript, das 1000 GetItem Anforderungen in einer Schleife durchgeführt. Der Gegenstand, der abgerufen wurde, war sehr klein, deutlich unter 1K. Das Ausführen dieses auf Python 2.6.7 auf einer m1.medium Instanz in der us-east-1-Region produzierten diese Ergebnisse:

>>> 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 

Beachten Sie, dass es in der Tabelle ausreichend bereitgestellten Kapazität ist jede Drosselung aus dem Dienst zu vermeiden und Die unerwartete Lücke zwischen HTTP und HTTPS ist klar.

Ich lief neben den gleichen Test in 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 

So, 2.7 dieses Problem behoben zu haben scheint. Ich habe dann in 2.6.7 einen einfachen Patch auf httplib.py angewendet. Der Patch setzt einfach die TCP_NO_DELAY Eigenschaft der Buchse mit dem Httpconnection-Objekt zugeordnet ist, wie folgt aus:

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

ich dann den Test auf 2.6.7 wieder lief: besser

>>> 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 

Auch wenn noch ein erwarteter schneller Zeit mit HTTPS als HTTP. Es ist schwer zu wissen, ob dieser Unterschied signifikant ist oder nicht.

So suche ich nach Möglichkeiten, den Socket für HTTPConnection-Objekte programmgesteuert zu konfigurieren, TCP_NO_DELAY richtig konfiguriert zu haben. In httplib.py ist das nicht einfach.Mein bester Rat ist im Moment, wenn möglich Python 2.7 zu verwenden.

+0

+1 für die detaillierte Analyse und posten es schon, ein Rätselrätsel in der Tat - vielen Dank! –