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