b********8 发帖数: 153 | 1 我先是读取一个一个文本文件,每行15字符,文件的行数可能有几十万。然后需要把每
一行连起来。本来是用的
string s = "";
s = s + stringtoadd;
问题是这个东西特别慢,后来我查了下可以用StringBuffer,用它的append方法,每次
调用sb.append(stringtoadd)
这个速度比String+要快多了。可是又出现了新问题,总是提示:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Unknown Source)
at java.lang.AbstractStringBuilder.expandCapacity(Unknown Source)
at java.lang.AbstractStringBuilder.append(Unknown Source)
at java.lang.StringBuffer.append(Unk |
h*****0 发帖数: 4889 | 2 有几个地方可以优化。
1. 用StringBuilder, 用法跟StringBuffer一样,但速度更快。
2. sb.append("(" + list.get(j) + "),");
要改成:
sb.append("(");
sb.append(list.get(j));
sb.append("),");
这样可以减少内存消耗。
3. 最后,如果还是会out of memory,那就试着不要先读文件存入list中,而是直接读
一行append一行。
4. 最最后,如果还是不行,你分析一下。默认内存(堆)只有64M,是不是不够?如果
不够,运行程序时java命令加入参数指定更大的内存(堆)。
【在 b********8 的大作中提到】![](/moin_static193/solenoid/img/up.png) : 我先是读取一个一个文本文件,每行15字符,文件的行数可能有几十万。然后需要把每 : 一行连起来。本来是用的 : string s = ""; : s = s + stringtoadd; : 问题是这个东西特别慢,后来我查了下可以用StringBuffer,用它的append方法,每次 : 调用sb.append(stringtoadd) : 这个速度比String+要快多了。可是又出现了新问题,总是提示: : Exception in thread "main" java.lang.OutOfMemoryError: Java heap space : at java.util.Arrays.copyOf(Unknown Source) : at java.lang.AbstractStringBuilder.expandCapacity(Unknown Source)
|
m******t 发帖数: 2416 | 3 What are you planning on doing with this one huge line after this,
if you don't mind me asking?
【在 b********8 的大作中提到】![](/moin_static193/solenoid/img/up.png) : 我先是读取一个一个文本文件,每行15字符,文件的行数可能有几十万。然后需要把每 : 一行连起来。本来是用的 : string s = ""; : s = s + stringtoadd; : 问题是这个东西特别慢,后来我查了下可以用StringBuffer,用它的append方法,每次 : 调用sb.append(stringtoadd) : 这个速度比String+要快多了。可是又出现了新问题,总是提示: : Exception in thread "main" java.lang.OutOfMemoryError: Java heap space : at java.util.Arrays.copyOf(Unknown Source) : at java.lang.AbstractStringBuilder.expandCapacity(Unknown Source)
|
s******e 发帖数: 493 | 4 You should know how jvm is supposed to handle string before you use java
string/stringbuilder/stringbuffer in this way.
Java uses string pool to handle string operation to improve the performance.
By appending string to old string, you are incrementally creating new
string objects in string pool, for example, you first line is a, you will
have one entry as a in the pool, then you append b to a, now you have two
strings of a and ab in the pool, etc.
Depending on jvm implementation, the gc mechani |
b********8 发帖数: 153 | 5 谢谢你的回复啊
我现在一个变通的办法是一次只读取20000行进行处理,然后就把这个StringBuffer
reset 再重新读2000行这样,回头我试一试StringBuilder
谢谢,我用这个试试
读入的文件都不大,总共也就40MB左右,为什么会这么容易out of memory?文件从硬盘
中读入内存会因为格式不同占用多得多的memory吗?
这个我已经改过了,初始的时候就有768MB
【在 h*****0 的大作中提到】![](/moin_static193/solenoid/img/up.png) : 有几个地方可以优化。 : 1. 用StringBuilder, 用法跟StringBuffer一样,但速度更快。 : 2. sb.append("(" + list.get(j) + "),"); : 要改成: : sb.append("("); : sb.append(list.get(j)); : sb.append("),"); : 这样可以减少内存消耗。 : 3. 最后,如果还是会out of memory,那就试着不要先读文件存入list中,而是直接读 : 一行append一行。
|
b********8 发帖数: 153 | 6 你说的是不是不应该把string s 用来循环增加?
记住了
performance.
【在 s******e 的大作中提到】![](/moin_static193/solenoid/img/up.png) : You should know how jvm is supposed to handle string before you use java : string/stringbuilder/stringbuffer in this way. : Java uses string pool to handle string operation to improve the performance. : By appending string to old string, you are incrementally creating new : string objects in string pool, for example, you first line is a, you will : have one entry as a in the pool, then you append b to a, now you have two : strings of a and ab in the pool, etc. : Depending on jvm implementation, the gc mechani
|
b********8 发帖数: 153 | 7 之前的数据都是放在文本文件里面的,是一组信号的时间序列,是我现在需要把他们搞
到数据库里面去
我查到mysql可以有一个句法可以一次插入很多行,所以就想一次把数据都读出来然后
写一个超长的insert命令加到database里面去
【在 m******t 的大作中提到】![](/moin_static193/solenoid/img/up.png) : What are you planning on doing with this one huge line after this, : if you don't mind me asking?
|
g*****g 发帖数: 34805 | 8 bad idea, you don't need to insert many lines at one sql first of
all, as long as it's in one transaction, it's probably as fast.
I would do one line per sql, but batch them up, e.g. commit once
every 100 lines.
【在 b********8 的大作中提到】![](/moin_static193/solenoid/img/up.png) : 之前的数据都是放在文本文件里面的,是一组信号的时间序列,是我现在需要把他们搞 : 到数据库里面去 : 我查到mysql可以有一个句法可以一次插入很多行,所以就想一次把数据都读出来然后 : 写一个超长的insert命令加到database里面去
|
s*****i 发帖数: 355 | 9 每一行改写成一条mysql query,用insert delay
然后直接往mysql里面导入就是了,非常快
【在 b********8 的大作中提到】![](/moin_static193/solenoid/img/up.png) : 之前的数据都是放在文本文件里面的,是一组信号的时间序列,是我现在需要把他们搞 : 到数据库里面去 : 我查到mysql可以有一个句法可以一次插入很多行,所以就想一次把数据都读出来然后 : 写一个超长的insert命令加到database里面去
|
n*********n 发帖数: 580 | 10 insert delay是不是jdbc 2.0的东西?
【在 s*****i 的大作中提到】![](/moin_static193/solenoid/img/up.png) : 每一行改写成一条mysql query,用insert delay : 然后直接往mysql里面导入就是了,非常快
|
s*****i 发帖数: 355 | 11 mysql的
【在 n*********n 的大作中提到】![](/moin_static193/solenoid/img/up.png) : insert delay是不是jdbc 2.0的东西?
|
m******t 发帖数: 2416 | 12
You might consider batch insert as bug suggested. It's standard jdbc api
supported by all major vendors now.
【在 b********8 的大作中提到】![](/moin_static193/solenoid/img/up.png) : 之前的数据都是放在文本文件里面的,是一组信号的时间序列,是我现在需要把他们搞 : 到数据库里面去 : 我查到mysql可以有一个句法可以一次插入很多行,所以就想一次把数据都读出来然后 : 写一个超长的insert命令加到database里面去
|
b********8 发帖数: 153 | 13 谢谢各位的帮助!
【在 m******t 的大作中提到】![](/moin_static193/solenoid/img/up.png) : : You might consider batch insert as bug suggested. It's standard jdbc api : supported by all major vendors now.
|
m*****e 发帖数: 47 | 14 Allocate StringBuffer at the beginning so that it does not copy the char
array:
StringBuffer sb = new StringBuffer(15*500000);
That's about 10MB. Should be fine.
But then insert has its own max length... |