Re: [問題] PipedInputStream 相關疑問

作者: willy69wu31 (小小吳)   2014-04-25 23:34:42
※ 引述《lovdkkkk (dk)》之銘言:
: 有理,
: 不過 by this case...
: 先說一下關於 Apache POI,
: 如果沒有自己 handle Streaming Usermodel,那它本身就非常吃記憶體,
: 詳情請自行估狗 "Apache POI Footprint" or "Apache POI OutOfMemory",
: 最近是有改善但有限。
: 所以真的怕大檔吃 memory 的話,其實就...
: pipe 或什麼其它的 stream 讓你 GG 之前,
: Apache POI 會先讓你 GG XDD。
把 Apache POI 和原本的讀檔程式用 pipe 接起來,最高吃 1.1 GB 記憶體
純跑原版讀檔程式則 800 MB,好像還好(?)
附帶一提,我有 8G RAM,用 64 位元 Java 跑,所以目前記憶體使用量暫時不是問題
: 寫一個 byte 讀一個 byte 其實也有點...奇怪?
: 因為用 Apache POI 我沒會錯意的話,
: 應該是要靠它拿 cell 裡的值然後自己加逗號,
: 特地對後來建出的字串一個一個 byte 處理...
: 不知道該怎麼說 "0rz
: 前面 Apache POI 應該已經吃掉
: 比你把資料全讀出來組好的 String 還多 n 倍的 memory 了,
: 這裡真的要搶回 memory 的話盡快把資料讀完,
: 讓 HSSF/XSSF workbook 設為 null 給 GC 最有效,
: 不然都有種 "省小條、開大條" 的感覺 @@"。
不小心讓各位會錯意了,真抱歉
我是出於好奇,認為 pipe 會 block 很奇怪,
為了想問出會 block 的原因,才舉個讀寫 1 byte 的例子 XD
實際上的程式是 PrintWriter→OutputStreamWriter→PipedOutputStream
再來讀取是 PipedInputStream→BufferedInputStream→Scanner
(BufferedInputStream 是原本為了讀 File 準備的,轉成 PipedInputStream 後沒拿掉)
: 至於簡單,用 pipe input/output 互接看起來是有一點麻煩,
: 不過寫檔也一樣要讀出資料、加逗號再存成 CSV,
: 那或許可以考慮用簡單一點的 PrintStream,
: (是說它也可以寫檔就是)
: 只要一直讀出來 append... append...,
: 讀完再拿 byte array 轉 input stream 就好,
: 這樣也是都在 memory 裡做掉,不過還是很簡單。
如上段回應,PrintWriter→OutputStreamWriter→PipedOutputStream
不需要自己解決 byte array
用 PrintWriter 不用 PrintStream 的理由是需要固定用 UTF-16LE 編碼
: ※ 引述《popcorny (畢業了..@@")》之銘言:
: : 讀寫檔比memory慢,這個是絕對的
: : 但是回到原po說的
: : 他想要寫一個byte讀一個byte
一樣很抱歉讓你誤解了 XD
: : 然而producer是apache poi 而consumer是已經寫好的程式
: : 所以要這樣"Flow Control"應該很難寫吧...
: : 如果要我寫可能選三個方法
: : 1. 開兩個thread. 中間開pipe
: : 兩邊一起跑,這是最完美的做法。
: : 就跟unix like的command line pipe一樣的行為
↑我目前的解法
: : 2. producer寫到ByteArrayOutputStream
: : 寫完把bytes拿出來放到ByteArrayInputStream去讀
: : 免開thread. 也夠快.. 但是缺點就是檔案大吃太多memory
: : 3. producer寫到temp file
: : consumer從temp file讀
: : 免開thread.. 也不怕檔案大
: : 但選擇方案的時候我會有三個考量點要考量
: : a. 效率
: : b. 最大Memory使用量 (memory footprint)
: : c. 程式碼簡單,流程單純。
: : 如果你的效能是你很大的考量。
: : 而且你的檔案有可能會很大。
: : 那我建議你選1的方案。也算是大多數情況最好的解。
: : 唯一的缺點就是流程復雜點,程式碼比較難懂。
其實弄清楚那兩個 pipe 類別之後,我覺得看起來很好懂 XD
或許跟我程式的流程有關,然後就是 Excel 檔有四張試算表,
總列數 18,000 上下,欄數平均約 25
: : 退而求其次,如果今天你已經確定資料量不會太大
: : 也許2是最好解。簡單,快速,易懂。
: : 如果效能不會是太大考量。
: : 也許你的程式你久久才跑一次這段程式
: : 而每次跑也只是0.1秒跟0.001秒的差別。
: : 那寫檔會是最簡單,不吃memory的做法
我目前程式規則還有幾次變動的可能,常需要重跑
: : 寫程式本來很多都是trade off
: : 你必須要有能力可以評估
: : 雖然效能差距1000倍
: : 但是你的程式在這邊本來就不佔0.01%的時間
: : 不是performance bottleneck
: : 或是你的程式根本就久久才用一次這段code
: : 那我們當然選擇一個易懂不易出錯很容易maintain的版本
相當認同
作者: lovdkkkk (dk)   2014-04-25 23:44:00
可以看看原本 Excel 檔多大, 讀進程式後變胖幾倍 @@

Links booklink

Contact Us: admin [ a t ] ucptt.com