2011-07-13 49 views
2

亲爱StackOverflowers量有限的环境中,智能缓存与内存的Java

我在写这从一个二进制文件排序一个巨大的整数量的应用程序的过程。我需要尽快完成,主要的性能问题是磁盘访问时间,因为我做了大量的读取操作,它显着减慢了算法的速度。

这样做将是填补〜可用存储器的50%与某种类型的缓冲对象(的BufferedInputStream等),然后转移,从缓冲的对象的整数成整数的阵列(可能需要的标准方式剩余空余空间)并对数组中的整数进行排序。将已排序的块保存回磁盘,重复此过程,直到将整个文件拆分为已排序的块,然后将块合并在一起。 由于数据本质上是重复的(50%用于缓存,50%用于存储相同数据的数组),排序块的策略只利用50%的可用内存。

我希望我可以通过编写自己的缓冲类来优化算法(排序块)的这个阶段,该类允许将数据直接缓存到int数组中,以便数组可以占用所有的可用空间而不是只有它的50%,这会使这个阶段的磁盘访问次数减少2倍。事情是我不知道从哪里开始。

编辑: 本质上,我想找到一种方法来填充一个整数数组,通过只执行一个读取文件。另一个限制是数组必须使用大部分空闲内存。

如果任何我的发言是错误的,或者至少看起来是请大家指正,

任何帮助表示赞赏,

问候

+0

你可以提供一些有关数据的信息。这些只是整数/只有正整数/是否有任何重复等,等等...... – peshkira

+0

不幸的是,没有关于数据的信息可据我可以告诉文件可以包含任意整数任何 –

+0

*“......可以包含任意整数任何” - 什么是整数的最大值,是比他们更大的' Integer.MAX_VALUE'?由于您立即将它们复制到另一个数据结构中,因此还有一个大于默认缓冲区的“InputStream”缓冲区并不会显示性能提升。配置文件具有不大于磁盘扇区大小的缓冲区,并将它们直接读入阵列。 –

回答

2

当你说的限制,如何限制... < 1MB < 10MB < 64MB?

它是有区别的,因为如果在大多数情况下,大多数情况下默认值为8192(JDK 1.6)就足够了并且增加并不会带来太大差别,您实际上不会获得太多好处。

使用较小的BufferedInputStream应该留给你几乎所有的堆,以便在将每个块写入磁盘之前创建和排序每个块。

+0

我事先不知道,我只能在运行时才能得到它。有一个小的缓冲对象的问题是,我将不得不访问磁盘多个时间来填补我的数组,这是非常不可取的,因为它会减慢整个事情很多。 –

+0

它来访问磁盘多次任何如何..底层的操作系统通常块中的IO反正...进行测试,看看......你可能会对结果 –

+0

感谢惊讶,我会尝试测试它 –

1

你不提供很多提示。但我脑海中有两件事。首先,如果你有很多整数,但没有那么多独特的价值,斗式排序可能是解决方案。

其次,一个字(好的术语),当我听到我的头时尖叫:外部磁带排序。在早期的计算机时代(即石器时代),数据依赖于磁带,并且很难将数据分散到多个磁带上。这与你的情况非常相似。实际上,合并排序是那些日子里最常用的排序方式,据我所知,Knuths TAOCP有一个很好的章节。关于缓存,缓存和类似的大小可能有一些好的提示。

+0

你是对的,这被称为“外部排序”,但是我遇到的问题与算法无关,它是Java特定的,即我不知道如何一次性填充整数数组(在一次磁盘访问中),尽可能我知道它可以通过填充一个字节数组,然后假装它是一个int数组在C++中完成。 正如你已经正确地指出归并排序是这个程序非常有用,我就准备用在合并阶段归并排序块已被排序后。 PS,你会喜欢什么样的信息,我提供帮助? –

+0

@ user843442:该提示,这种外部排序是一个很好的研究问题,也许RAM的贵50%/ 50%分布不是最佳的,但也有可能更好的战略。 – flolo