我在GAE记忆中存储了大约20k个条目的地图。每个条目大约1Kb。 我收到以下错误。有限制吗?根据我的理解,1Mb的限制是你在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);
问题只发生在prod环境中,而不是本地环境。
任何帮助/提示?
答案 0 :(得分:2)
内存缓存的大小是GAE中的一个黑盒子。不要相信它是什么。你是对的,没有一个实体可以大于1 MB,但你没有IDEA你的总memcache有多大,你也不知道驱逐政策是什么。
GAE的最新版本似乎让我们对memcache有了一些了解,但到目前为止,它确实是一个黑盒子。我建议不要做你想做的事。如果您需要加热缓存,请在循环中执行此操作,并仅加载最相关的内容。
答案 1 :(得分:1)
你得到一个异常是因为你的Java servlet容器内存不足,而不是因为与memcache相关的任何内容。
如果你试图在一个请求中设置20,000个memcache密钥,我怀疑你做错了。
答案 2 :(得分:1)
您使用的是Appstats吗?我发现Appstats使用了大量内存,请在此处查看我的问题: How to reduce the memory usage of Appstats on Google App Engine Java
我尝试一次加载大约20,000个条目时遇到OutOfMemoryError,与您的大小相似。现在我分批加载它们,当时是1000。以下是使用Siena的示例代码(但应该很容易移植到其他ORM):http://groups.google.com/group/siena-discuss/msg/cd874589ef7aaa66
我觉得使用方法List.subList()后跟List.remove()或List.clear()
是很方便的[更新]
我发现了一个未记录的参数,它限制了StackTrace的大小:
<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>