2012-04-01 59 views
1

我在GAE memchace中存儲了大約20k條目的地圖。每個條目大約1Kb。 我收到以下錯誤。是否有限制?在我理解的1Mb的限制中,對於放入內存緩存的每個實體,並不是整個批次。Google App Engine java OutOfMemoryError當putAll在memcache上時

java.lang.OutOfMemoryError: Java heap space 
at com.google.appengine.repackaged.com.google.protobuf.AbstractMessageLite.toByteArray(AbstractMessageLite.java:34) 
at com.google.appengine.api.memcache.MemcacheServiceApiHelper.makeAsyncCall(MemcacheServiceApiHelper.java:104) 
at com.google.appengine.api.memcache.AsyncMemcacheServiceImpl.doPutAll(AsyncMemcacheServiceImpl.java:521) 
at com.google.appengine.api.memcache.AsyncMemcacheServiceImpl.putAll(AsyncMemcacheServiceImpl.java:564) 
at com.google.appengine.api.memcache.MemcacheServiceImpl.putAll(MemcacheServiceImpl.java:112) 
[...] 

我的代碼如下所示:

final HashMap<EntityToStoreKey, EntityToStore> map = new HashMap<EntityToStoreKey, EntityToStore>(); 
for (EntityToStore entityToStore : entitiesToStore) { 
    index.add(entityToStore); 
    map.put(EntityToStoreKey.key(entityToStore.getId(), false), entityToStore); 
} 
entityToStoreCache.putAll(map, portalCacheTimeout); 

而問題只發生在一個督促的環境,而不是在本地。

任何幫助/提示?

+0

這似乎並非是一個'memcache'問題。在將數據提供給memcache之前,它將被序列化,那就是當你超出堆的大小時。如果你的實體的大小是1K,這是令人驚訝的。物質內是否有周期性的參考? – cheeken 2012-04-01 19:42:23

回答

1

您使用的是Appstats嗎?我發現將Appstats使用大的內存塊,見我的問題在這裏: How to reduce the memory usage of Appstats on Google App Engine Java

我試圖立刻,大小和你類似的裝載大約20,000條目時經歷的OutOfMemoryError。現在我分批加載它們,當時是1000個。下面是使用錫耶納的示例代碼(但它應該很容易移植到其他的ORM):http://groups.google.com/group/siena-discuss/msg/cd874589ef7aaa66

我覺得使用起來得心應手的方法List.subList(),其次是List.remove()或List.clear()

[更新]

我發現,限制堆棧跟蹤的大小無證參數:

<filter> 
    <filter-name>appstats</filter-name> 
    <filter-class>com.google.appengine.tools.appstats.AppstatsFilter</filter-class> 
    <init-param> 
     <param-name>maxLinesOfStackTrace</param-name> 
     <param-value>16</param-value> 
    </init-param> 
</filter> 
2

memcache的大小是GAE中的一個總黑盒子。不要相信它是任何東西。你是對的,沒有一個實體可以大於1MB,但你沒有想法你的總內存容量有多大,你也不知道驅逐策略是什麼。

GAE的最新版本似乎給了我們對memcache的一些可見性,但到目前爲止它確實是一個黑匣子。我建議不要做你想做的事。如果您需要預熱緩存,請在一個循環中進行,只加載最相關的內容。

1

您正在收到異常,因爲您的Java servlet容器內存不足,而不是因爲與memcache相關的任何內容。

如果您嘗試在單個請求中設置20,000個memcache密鑰,但是,我懷疑您做錯了。

+0

1kb的20k個實體使其最大爲20Mb,我認爲這不是那麼大。是嗎 ?我無法在memcache中使用它嗎? – 2012-04-02 15:23:10

+0

@planadecu當然,你可以,但你仍然在討論在單個請求中寫入_20,000_條記錄。這不僅僅是總大小。 – 2012-04-02 16:18:16