如何通过在Java中压缩我的对象来减少总内存占用?

时间:2009-12-02 13:25:23

标签: java performance design-patterns caching map

我有一个包含大约20列的表,其中大部分由varchars和decimal组成。该表有近1.5M行。但是很少有东西是常见的,比如column1只包含100个不同的字符串,column2几乎有1000个,column3几乎有500个。

现在,我将所有这些列值存储在一个地图中,其中Key为前5列,Data为其余列。我的任务是这样的,我需要在任务开始时初始化所有这些。

我应该使用什么模式(如Flyweight等)或数据结构来最小化我的对象存储?

为什么我需要预加载所有数据?

假设桌子的整个数据为树,受害者可以在任何树叶,树干或根部。因此,对于每个条目[来自不同的地方],我需要查看树中是否有任何匹配。

3 个答案:

答案 0 :(得分:2)

内化不是最好的选择。从PermSpace收集垃圾是可能的,但VM没有优化。

您可以实现由共享char []数组支持的 CharSequence 实现。

使用CharSequence实现,您将能够实现基本的共享语义,如内化字符串或更复杂的字符串,并考虑子字符串和其他预测。

自定义CharSequence实现也可以优化为执行更少的内存分配,而不是复制char []的String类(出于安全原因,如果你有支持char []则不需要在你完全控制下)。即使new String("..").intern()也会实例化一个快速垃圾收集的新String实例(char []数组)。

答案 1 :(得分:1)

我的第一个问题是,你的任务计划与表中的数据一起做什么?将完整的表预加载到内存中并不总是最好的方法,例如保持当前设置但按需加载可能是更好的解决方案。您可能想要调查一段时间未使用的刷新数据,即一种最近使用的地图。

你能否详细说明你的任务试图通过地图中缓存的所有数据来实现什么?

“受害者”识别部分是对象的关键部分还是部分?如果是对象的一部分,如何选择选择所需对象的键?换一种说法;听起来你试图重现数据库非常擅长的功能。

如果您的问题是您的表内容不能轻松地映射到树状结构上,您可以通过数据库界面以可用的方式添加该信息。

答案 2 :(得分:0)

如果你的数据加载过程可以支持它,那么在没有GC permgen副作用的情况下实现像String.intern()这样的东西并不太困难。

对于任何hashable数据元素,您只需Map<T,T>查找预先存在的实例即可。所以对于String:

Map<String,String> stringCache = new HashMap<String,String>();
...
String sharedValue = stringCache.get(loadedValue);

从任何地方加载数据的过程仍将创建临时字符串,但这些将快速GC。如果不了解数据来源的具体细节,就很难评论这些临时对象是否必要......尽管我很难找到解决方法。无论如何,它们会在装载过程中迅速回收。