java - 磁盘上的磁盘读取速度非常慢,存储的是 java HashMap

  显示原文与译文双语对照的内容
63 1

我有一个存储外部 uid,然后存储为给定uid设置的不同id的HashMap 。

例如

  • 123 。345.432=00001
  • 123 。354.433=00002

通过uid检查映射,以确保使用相同的内部 id 。 如果应用程序中存在某些问题。

DICOMUID2StudyIdentiferMap定义如下:


private static Map DICOMUID2StudyIdentiferMap = Collections.synchronizedMap(new HashMap());



但是加载将覆盖它,如果我们成功加载,否则它将使用默认的空 HashMap 。

它通过执行以下操作从磁盘读取:


FileInputStream f = new FileInputStream( studyUIDFile ); 


ObjectInputStream s = new ObjectInputStream( f );



Map loadedMap = ( Map )s.readObject();


DICOMUID2StudyIdentiferMap = Collections.synchronizedMap( loadedMap );



使用以下方法将HashMap写入磁盘:


FileOutputStream f = new FileOutputStream( studyUIDFile );


ObjectOutputStream s = new ObjectOutputStream( f );



s.writeObject(DICOMUID2StudyIdentiferMap);



我的问题是,在 Eclipse 性能的本地运行是很好的,但当应用程序正常运行在一台机器上时。 一旦加载,也需要很长的时间来检查以前的值,看看 dicomuid2studyidentifermap 。( ) 。 。将返回一个值。

我在两种情况下加载相同的地图对象,它是 ~400kb 文件。 它包含的HashMap有 ~3000 key-value 对。

为什么在一台机器上如此缓慢,但在 Eclipse 中却如此缓慢?

这个机器是一个运行XP的虚拟机,它最近开始缓慢地读取 vxml,所以 400kb 不是很大。

欢迎大家欢迎 TIA

时间: 原作者:

76 5

不确定serialising的地图是否最佳选项。 如果映射是基于保存的磁盘,为什么不使用为磁盘设计的lib? 请看 Kyoto 。 它实际上是用 C++ 编写的,但是有一个 javaapi 。 我已经用了几次,很容易使用,非常快,可以缩小到大尺寸。

这是我为东京 cabinet cabinet cabinet cabinet的一个例子,但它基本上是相同的。


import tokyocabinet.HDB;



....



String dir ="/path/to/my/dir/";


HDB hash = new HDB();



//open the hash for read/write, create if does not exist on disk


if (!hash.open(dir +"unigrams.tch", HDB.OWRITER | HDB.OCREAT)) {


 throw new IOException("Unable to open" + dir +"unigrams.tch:" + hash.errmsg());


}



//Add something to the hash


hash.put("blah","my string");



//Close it


hash.close();



原作者:
138 1

作为 @biziclop 注释,你应该首先使用探查器来查看应用程序在哪里花费的时间。

如果这没有给你任何结果,这里有一些理论。

  • 可能你的应用程序正接近耗尽堆。 由于JVM接近堆,它可以花费几乎所有的时间垃圾收集来继续进行。 这将在启用GC日志记录时显示。

  • 有可能ObjectInputStream和ObjectOutputStream正在做大量的小读取系统调用。 尝试用缓冲流包装文件流,看看它是否能显著提高性能。

为什么在一台机器上如此缓慢,但在 Eclipse 中却如此缓慢?

"完全堆"理论可以解释。 Eclipse的默认堆大小比使用 java.. .的应用程序大于没有堆大小选项的应用程序大。

原作者:
...