2012-04-13 144 views
3

我使用:的Java IO性能問題

PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("test.txt"),1024*1024*500)) 

寫一個大文件(大約2GB)。寫入需要26秒。但是,當我用10/20替換500時,需要19秒。

here,我瞭解的是緩衝給出更好的性能。如果是這樣,那麼爲什麼會發生?我通過每次運行5次來檢查它,所以系統/ IO負載不是問題。

+1

可能的重複[如何確定使用FileInputStream時的理想緩衝區大小?](http://stackoverflow.com/ question/236861/how-do-you-determine-the-ideal-buffer-size-when-file-fileinputstream) – 2012-04-13 15:24:05

+0

非常相似的問題,非常相似的答案:http://stackoverflow.com/a/237495/1315900 – 2012-04-13 15:19:50

回答

2

正如我在前面的問題中所說的那樣,存在一個最佳緩衝區大小(通常大約爲32 KB),並且當您使緩衝區大於此值時,速度會變慢而不會更快。默認緩衝區大小爲8 KB。

順便說一句:你的L2/L3 CPU緩存有多大? (我懷疑大約10 MB)您的主L1緩存大約是32 KB?

通過使用適合最快緩存的緩衝區,可以使用最快的內存。通過使用僅適用於主內存的緩衝區,您使用最慢的內存(速度慢10倍)


回答您的問題。

我所做的是假設ISO-8859-1編碼,即(byte) ch,並一次寫入一個字節到一個ByteBuffer,可能是內存映射。

我有寫/讀longdouble從ByteBuffer方法沒有創建任何垃圾。

https://github.com/peter-lawrey/Java-Chronicle/blob/master/src/main/java/vanilla/java/chronicle/impl/AbstractExcerpt.java

使用這種方法,您可以登錄每秒約5萬線到磁盤。

+0

另一個很好的答案。謝謝。你可以通知PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(「compresedchr1.txt」),32KB)); out.print(char) - 哪個nio函數替代了這個?那個更快嗎?或者任何其他方式來寫字符? – Arpssss 2012-04-13 15:23:57

+0

看我的編輯... – 2012-04-13 15:35:04

1

1024*1024*500是500兆字節,給予或採取smidgen。你基本上是迫使JVM分配500MB的連續內存塊,JVM可能需要做一個GC循環。

+0

不,我有16 GB的內存。 JVM分配5/6 GB。我認爲沒有GC循環。 – Arpssss 2012-04-13 15:25:33

1

非常大的緩衝區(500 MB)也不好,因爲操作系統對於那個巨大的字節緩衝區的內存管理會更困難。

將它與在你的房子中移動一張桌子比較,而不是移動一個框。但是如果你的盒子變得太小,你將不得不多次去。

不要忘記分配內存是O(n)操作。

+0

謝謝。我知道了。 – Arpssss 2012-04-13 15:26:53

2

緩衝區過大會降低性能。堅持到32-64 kb IMO

1

首先你真的不需要一個大的緩衝區。通常64K甚至低至8K就足以獲得下降IO性能。任何更大的,你只是浪費內存和CPU,因爲當你獲得越來越大的緩衝區時,它會在IO層花費更多時間寫入大量數據。因此,在等待IO和寫入內存之間進行折衷(如果您瞭解微積分,則爲最小 - 最大值)。由於IO設備具有內部固定大小的緩衝區,因此無法將巨大緩衝區推送到IO設備。重點是儘可能地嘗試和匹配它,但意識到這樣做相對不可能,因爲你不知道其他處理正在做什麼。最好的辦法是嘗試低8K-16K,運行它,測量它。加倍緩衝區32K等,運行它,測量它。如果你獲得了速度提升,那就再做一次。一旦你停止獲得速度提升除以2,並停止。

因此,如果您在26s中寫入2GB數據,那麼吞吐量爲76MB/S或650Mbit/s。您可以通過將緩衝區大小降低到合理值來改善它。

+0

謝謝。我知道了。 – Arpssss 2012-04-13 15:28:08

1

緩衝你的I/O通過減少系統調用的次數來提高性能。但系統調用並不是那麼昂貴(可能是一毫秒左右),而過大的緩衝區可能會在其他方面造成問題。例如:

  • 500 MB緩衝區使用大量內存,並可能增加GC開銷或增加系統的尋呼負載。

  • 如果您在單次寫入調用中寫入500 MB字節,寫入操作可能會使系統的緩衝區緩存飽和,並且壓倒其在應用程序級別與其他事物重疊寫入磁盤的能力。

只是嘗試使用(顯着)較小的緩衝區。 (我個人不會使用大於8kb的緩衝區,而不進行特定於應用程序的調整。)