2011-07-13 47 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