簡體   English   中英

從Memcache中獲取低級別數據存儲區實體對象時,反向串行化較慢

[英]Slow deserialization when fetching low level datastore Entity objects from Memcache

事實證明,檢索存儲內存緩存的低級數據存儲實體非常緩慢。 由於objectify將實體緩存為低級數據存儲區實體類型,因此當使用objectify從memcache中獲取許多實體時,這會導致性能不佳。

真正的問題是為什么從memcache反序列化實體類型的速度慢? 我整理了一個示例項目來演示從memcache與普通字符串或簡單Map中檢索實體的差異。

這是代碼:

https://github.com/aleemstreak/perftest或相關文件: https//github.com/aleemstreak/perftest/blob/master/src/com/rewardly/perftest/PerftestServlet.java

此外,我部署了它,因此您可以看到它在生產中有多大差異:aleemsandbox.appspot.com/perftest。 它是一個天真的探測器,但它確實表現出巨大的性能差異。 刷新頁面幾次以查看差異。 這是一些示例輸出:

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

第一部分顯示了在memcache中存儲1000個字符串然后立即獲取它所需的時間。 下一個示例對1000個Map對象執行相同操作,最后一個示例存儲並檢索1000個低級實體類型。 您可以看到檢索實體類型的時間增加。

任何想法為什么實體可能很慢從memcache反序列化?

更新1

根據其中一個答案中的建議,我還記錄了存儲在memcache中的對象的累積大小,結果沒有打印出來。 我還添加了另一個測試用例 - 而不是直接存儲實體,而是首先將Entity序列化為byte [],然后將其存儲在memcache中。 結果如下:

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

這里有趣的是最后兩個結果。 盡管它們的大小大致相同,但手動獲取和反序列化byte []需要大約1/5的時間。

github repo中的代碼已更新,部署的示例應用程序也有最新代碼,因此可以隨意在此處運行此測試並查看結果。

也許我挑選你的措辭,但所有更高級別的API(JDO,JPA和Ofy)都使用低級API,因此所有實體都是LL API實體。 因此,您注意到“Objectify將實體緩存為低級數據存儲區實體類型”,但是並非所有更高級別的數據存儲區API都這樣做(假設它們已被指示使用此類緩存)? 所以我不認為這與你有任何關系。

繼續前進,你的第三次測試比其他測試需要更長的時間似乎很自然 - 實體類型相對於簡單的String甚至Map類型增加了相當大的開銷。 我有點驚訝,它需要更長的時間,但退后一步,你獲取1000個實體,所以每個實體仍然<1毫秒。

我想你應該再增加一個測試。 有一個java API可以獲取實例內存的大小(無法記住它)。 確定測試中使用的實體的內存大小,然后更改字符串測試以使用相同大小的對象。 這樣我們可以隔離這是否與Entity類型本身有關,或者僅僅是第三次測試中緩存的對象大小相當大的結果。


更新以響應新的測試結果......有趣。 這似乎證實了你的理論,即由memcache代碼完成的序列化導致了減速。 這很奇怪 - 但是memcache不會簡單地以與你正在做的非常類似的方式序列化對象嗎?

也許這篇文章有助於:
AppEngine數據存儲對象的手動序列化/反序列化


用於獲取Entity對象的memcache接口是:

java.lang.Object get(java.lang.Object key)

https://developers.google.com/appengine/docs/java/javadoc/com/google/appengine/api/memcache/MemcacheService#get(java.lang.Object)

因此,它不是采用可預測的方式,而是按照自己的方式序列化,它可能是使用內省。 這可以解釋為什么'EntityPreSerializedBenchmark'比'EntityBenchmark'快得多。

結果是appengine sdk中的一個bug。 他們知道這個問題並且大概是在修理。

序列化性能的這種回歸在App Engine 1.9.5 SDK中得到了修復。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM