Es stellt sich heraus, dass das Abrufen von Datenspeichereinheiten auf niedriger Ebene, in denen Memcache gespeichert ist, äußerst langsam ist. Da Objekte als Entity-Typ des Datenspeichers der unteren Ebene objektiviert werden, führt dies zu einer schlechten Leistung beim Abrufen vieler Entitäten aus Memcache mithilfe von "objectify".Langsame Deserialisierung beim Abrufen von Datenobjekten auf niedriger Ebene Entitätsobjekte aus Memcache
Die eigentliche Frage ist, warum es langsam ist, den Entity-Typ aus Memcache zu deserialisieren? Ich habe ein Beispielprojekt zusammengestellt, um die Unterschiede beim Abrufen von Entitäten aus Memcache gegenüber einfachen Strings oder einer einfachen Map zu demonstrieren.
Hier ist der Code:
https://github.com/aleemstreak/perftest oder die entsprechende Datei: https://github.com/aleemstreak/perftest/blob/master/src/com/rewardly/perftest/PerftestServlet.java
Auch ich entfaltet es, so dass Sie, wie groß ein Unterschied sehen kann dies in der Produktion ist: aleemsandbox.appspot.com/perftest. Es ist ein naives Profiler, aber es zeigt eine enorme Ungleichheit in der Leistung. Aktualisieren Sie die Seite einige Male, um den Unterschied zu sehen. Hier einige Beispiel-Ausgabe:
Storing String Data Test
-------------------------
generateData: 0ms
storeData: 10ms
fetchData: 9ms
Storing Map Data Test
-------------------------
generateData: 0ms
storeData: 21ms
fetchData: 92ms
Storing Entity Data Test
-------------------------
generateData: 69ms
storeData: 24ms
fetchData: 792ms
Der erste Abschnitt zeigt die Zeit, die 1000 Strings in memcache zu speichern nimmt und dann holen rechts zurück. Das nächste Beispiel macht dasselbe für 1000 Map-Objekte und schließlich speichert das letzte Beispiel 1000 Low-Level-Entity-Typen. Sie können die enorme Zeit erhöhen, um Entity-Typen abzurufen.
Irgendwelche Ideen, warum Entitäten langsam aus Memcache deserialisieren könnten?
UPDATE 1
einen Vorschlag in einer der Antworten Folgen, ich protokolliert auch die kumulative Größe der Objekte, um sie in memcache und die Ergebnisse kein Ausdruck gespeichert werden. Ich habe auch einen anderen Testfall hinzugefügt - anstatt eine Entity direkt zu speichern, serialisiere ich die Entity zuerst auf ein Byte [] und speichere sie dann in Memcache. Hier sind die Ergebnisse:
StringBenchmark
----------------
Average Fetch Time: 40.16ms
Fetch Size: 24.41KB
MapBenchmark
----------------
Average Fetch Time: 27.36ms
Fetch Size: 102.54KB
EntityBenchmark
----------------
Average Fetch Time: 1029.88ms
Fetch Size: 463.87KB
EntityPreSerializedBenchmark
----------------
Average Fetch Time: 218.82ms
Fetch Size: 490.23KB
Was hier interessant ist, sind die letzten beiden Ergebnisse. Obwohl sie ungefähr die gleiche Größe haben, dauert es etwa 1/5, um das Byte [] manuell abzurufen und zu deserialisieren.
Der Code im Github Repo wurde aktualisiert und die bereitgestellte Beispiel-App enthält auch den neuesten Code. Sie können diesen Test also dort ausführen und die Ergebnisse sehen.
Eine Sache, die ich vergessen habe zu erwähnen, ist, dass dieser Code auch mit appstats profiliert wird und alle Abrufe von Memcache <10ms sind. Das bedeutet, dass die restliche Zeit damit verbracht wird, die Objekte zu deserialisieren. – aloo
Können Sie für EntityPreSerializedBenchmark auch angeben, wie lange die Serialisierung dauert und wie viel Zeit noch benötigt wird? – Nick
Entschuldigung durch Abrufzeit meinst du die Abrufzeit zu aktuellem Memcache wie von Appstats aufgelistet? – aloo