2012-04-01 62 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