来自用 @Stringify 标记的大型 Map 的 java.lang.OutOfMemoryError

标签 java google-app-engine objectify

如何解决 Map 属性的“java.lang.OutOfMemoryError:Java 堆空间”timeseries这显然太大而无法从 Google App Engine 数据存储中检索?当我尝试使用 Objectify load() 从数据存储中读取包含大 map 的实体时,会发生错误。操作。

这是包含大 map 的实体:

@com.googlecode.objectify.annotation.Entity
public class Insight {
    @com.googlecode.objectify.annotation.Id 
    public Long id;

    @Stringify(com.netbase.model.DateStringifier.class)
    public Map<Date, Double> timeseries;
}

这是字符串生成器的实现:

public class DateStringifier implements Stringifier<Date> {

    @Override
    public String toString(Date obj) {
        return Long.toString(obj);
    }

    @Override
    public Date fromString(String str) {
        long timestamp_long = Long.parseLong(timestamp);
        Date date = new Date(timestamp_long);
        return date;
    }    
}

我已经尝试在具有最大内存大小的 Google 模块中运行此程序(实例类 B8,如 https://cloud.google.com/appengine/docs/java/modules/ 中所述)。

我也尝试过使用游标,认为在游标刷新后会发生垃圾收集。但实际上我在第一个光标上遇到了异常,光标大小为 1,这表明单个 Map 本身太大。

我不知道我一开始是如何能够保存这么大的 map 的,但它发生在几周前,现在日志已经丢失了。构建 map 是一项昂贵的操作,因此我想看看是否仍然可以检索它。

由于它是通过 Objectify 持久保存的,所以我不确定如何使用底层数据存储来读取它。任何有关如何解决此问题的建议将不胜感激。

================================================== =============

更新:我设法通过将数据分段导出来将数据从 Google App Engine 中取出。当最初的问题看起来会阻止我时,我不确定我是如何做到这一点的。

无论如何,我想向大家通报最新情况,让大家知道数据总量为 23.5 MB。它大约有 6K 个实体,每个实体都有 Map<Date, Double> timeseries 。这意味着每个实体拥有大约 3.9 MB 的数据。根据 @stickfigure 在他下面的解决方案中的说法,这大约是实体大小的限制。因此,我必须找到某种方法将实体分解为更小的实体,并在单独的 session 中处理数据。我有点失望,因为我认为 Google App Engine 会给我更多的资源。我想,如果我可以在 Excel 文件中保存 23.5 MB,并且本地计算机上的 Excel 可以毫无问题地处理这么多数据,那么 Google App Engine 应该能够处理更多倍的数据。

最佳答案

这里还发生了其他事情。 GAE实体不能大于1MB;即使允许多个 X 扩展因子(您的 POJO 和 native 低级实体同时存在于 RAM 中,字符串形式加日期形式等),任何单个实体也不能代表超过几兆字节。

您可能正在堆的边缘运行,而这个几兆字节的操作恰好是将您推到堆的边缘。问题是为什么,特别是如果您已经在使用 B8。我将使用分析器在本地运行您的应用程序。

一个好的候选者是在单个 session 中对大量实体进行批量迭代。如果需要,您可以在迭代时调用 ofy().clear() 。您可以在 session caching documentation 中阅读更多内容.

关于来自用 @Stringify 标记的大型 Map 的 java.lang.OutOfMemoryError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28240421/

相关文章:

对象化如何为父键赋值

java - 为什么使用网络安全字符串来访问谷歌端点框架中的数据?

java - 在适用于 Eclipse 的 Google Cloud 工具上运行 Objectify 时出现 "projectId must match the following pattern"异常

java - try-catch 语句在捕获异常时不返回 try block

java - 如何使用来自多个模块的依赖项构建 Uber jar

java - 使用 https 访问我的应用程序时无法运行我的应用程序

python - App Engine 的用户名和密码登录?

java - 在 Microsoft IIS 7 中部署 War 文件

java - 从android(Flatbuffers)中的url获取字节[]数组中的二进制数据

python - Google Appengine 数据存储区何时可以返回过时数据?