【发布时间】:2015-05-24 19:22:32
【问题描述】:
你好,
我目前正在使用 Java 进行单词预测。 为此,我使用的是基于 NGram 的模型,但我有一些内存问题...
我第一次有这样的模型:
public class NGram implements Serializable {
private static final long serialVersionUID = 1L;
private transient int count;
private int id;
private NGram next;
public NGram(int idP) {
this.id = idP;
}
}
但这需要很多内存,所以我认为我需要优化,我想如果我有“hello the world”和“hello the people”,而不是得到两个 ngram,我可以保留一个保留“Hello the”然后有两种可能:“people”和“world”。
更清楚地说,这是我的新模型:
public class BNGram implements Serializable {
private static final long serialVersionUID = 1L;
private int id;
private HashMap<Integer,BNGram> next;
private int count = 1;
public BNGram(int idP) {
this.id = idP;
this.next = new HashMap<Integer, BNGram>();
}
}
但似乎我的第二个模型消耗了两倍的内存......我认为这是因为 HashMap,但我不知道如何减少这个?我尝试使用不同的 Map 实现,例如 Trove 或其他,但它并没有改变任何东西。
给你一个想法,对于一个 9MB 的文本,有 57818 个不同的单词(不同,但不是单词的总数),在 NGram 生成之后,我的 javaw 进程消耗了 1.2GB 的内存...... 如果我用 GZIPOutputStream 保存它,它会占用大约 18MB 的磁盘空间。
所以我的问题是:我怎样才能使用更少的内存?我可以用压缩(作为序列化)制作一些东西吗? 我需要将此添加到其他应用程序中,因此我需要减少内存使用之前...
非常感谢,抱歉我的英语不好......
ZiMath
【问题讨论】:
-
您是否尝试分析您的内存消耗?例如。使用 jvisualvm?
-
我目前正在使用 Java 任务控制来获取有关内存消耗的更好信息。
-
我不熟悉 n-gram 问题,链表(您的第一个解决方案)是推荐的方法吗?
-
每个对象至少消耗 32 个字节,可能是 48 个字节,具体取决于 JVM。字符串实际上是两个对象(当然,字符也会占用空间)。 HashMap 条目是另一个对象。对于像您这样的应用程序,减少内存消耗的最佳方法是使用数据库来保存大量数据。
-
LinkedList 不是推荐的方法,因为它降低了预测的性能(HashMap 很快,因为 get(...) 操作很快,所以 NGram 与 HashMap 在时间上非常有效)。我知道每个对象都会消耗内存,这就是为什么我不存储单词(在字符串中)而是在 int 中。您对嵌入式数据库有想法吗?我尝试了 H2,但它也消耗了大量内存!
标签: java performance memory hashmap