我正在开发工具,它接受Java代码并生成代码,用于获取基本块,循环和方法的执行时间的估计。在执行了一些块后,我们将时间放在我们的工具上。程序模型存储在下一个表示
中static Hashtable<String, Hashtable<Integer, Hashtable<String, pair>>> method2Data = new Hashtable<String, Hashtable<Integer, Hashtable<String, pair>>>();
static Hashtable<String, Vector<String>> class2Method = new Hashtable<String, Vector<String>>();
由方法推出的时间
public static void addBlock(int id, double time, String meth, String thread);
但我有下一个问题。每次调用 addBlock 时,我们都会从 method2data 中获取一些内容。因为我们可以有像
这样的代码for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
for (int k = 0; k < n; k++) {
addBlock(0,...);
addBlock(m,...);
}
我们将很多时间称为 addBlock 。 不幸的是,经过我们的claster工作一段时间后,程序才停止工作。它仍然看起来像进程,但不采取任何CPU。我发现,如果我删除了从 method2data 获取内容的代码,那么一切正常。所以,我想,访问Hashtable存在一些问题。有什么好主意吗?
感谢所有人,似乎在并发访问的情况下我有一个死锁,并且在没有并发事件时可能会耗尽内存。
答案 0 :(得分:3)
如果您使用的是Java5或更高版本,则不应使用Hashtable
,而应使用ConcurrentHashMap
,它通过锁定条带提供更好的可伸缩性,因此可以立即解决问题(如果您有死锁或饥饿问题,这可能是基于你的 - 不完整 - 描述)。在同一行,请不要使用Vector
,而是使用一些List
实现。 Hashtable
和Vector
都是同步的旧集合实现,在此Vector的情况下可能是不必要的。
[更新] 正如@finnw正确指出的那样,即使ConcurrentHashMap 似乎提供帮助,也无法确定根本原因是否真的得到了解决。需要进行彻底的分析和测试,以确定您的代码是否实际上是线程安全的。如果没有看到addBlock()
中的代码,我们就不能对此作出结论。的 [/更新] 强>
另外,正如其他人所说,将配置文件数据保存在内存中并不适合大型程序,因为这可能会影响您尝试测量的性能特征,甚至可能会耗尽内存。
答案 1 :(得分:3)
只是一个随意的想法:你可能没有记忆吗?
尝试使用-Xmx512m启动应用程序以允许512 MB的堆空间。
内存不足通常会使进程变慢,直到看起来什么都不做为止,因为它在每个其他指令之后调用了垃圾回收。
答案 2 :(得分:3)
Java中的Hashtables可以在GC中触发令人讨厌的行为,特别是当它们长寿和大的时候。 HashMap也是如此。要确定是否适合您,请检查进程需要多少CPU。如果需要大量CPU,则GC正在运行。如果它不需要任何CPU(只是挂起),那么你就会陷入僵局。
要查找死锁的原因,请创建一个线程转储并对其进行分析。如果您正在使用Eclipse,则可能需要查看Lockness。
答案 3 :(得分:1)
我不太明白你的自制的分析机制是如何运作的。但看起来它正在你正在检查的程序中完成,并且它在该程序中耗尽了大量内存。
除此之外,你在HashMap中使用Vector
。向量是同步的,因此比ArrayList
s慢一些。你可以从改变它中获得一点点性能。
回到主要问题。其他分析工具采用不同的方法:它们不是构建结果的内存数据结构,而是将所有内容记录到文件中。之后,一旦原始程序运行,另一个程序将读取,摘要和分析日志文件。事实证明,写入缓冲文件比在时间/内存使用方面更加一致且不那么干扰,而不是将仪器移植到程序中。
答案 4 :(得分:-1)
它看起来非常像死锁。尝试从Hashtable
切换到ConcurrentHashMap
或调查您的应用程序并添加其他锁以解决死锁问题。