2014. 3. 28. 09:50ㆍ99. 정리전 - IT/11. Java
GC원인
------- (출처 : http://ir.bagesoft.com/100 )
Caused by: java.lang.OutOfMemoryError: GC overhead limit exceeded 원인: 메모리 한계 초과
해결: -Xmx 옵션으로 메모리를 더 할당.
메모리가 부족하여 가비지 컬렉션이 이루어 졌으나,
새로 확보된 메모리가 전체 메모리의 2% 미만이어서 생기는 오류. 한 마디로 더 이상 가비지 컬렉션을 할 수 없을 정도로 메모리를 사용한다는 것임.
기존) java -Xms1g -Xmx1g -jar Project.jar
해결) java -Xms4g -Xmx4g -jar Project.jar |
아래 출처 : http://ir.bagesoft.com/97
64bit OS 를 사용하고, 아끼지 말고 RAM을 추가 |
CPU만 지원한다면, 무조건 64bit 운영체제를 설치해서 사용하라. RAM이 4GB 이하라도 설치해라. CPU의 처리 단위 증가 뿐만 아니라, 메모리를 최대한 사용할 수 있기 때문에 GC의 회수가 감소하여 속도가 더 높아진다.
Windows7 64bit 에서는 OS가 사용하는 메모리를 제외하고 모두 JVM이 사용할 수 있었다. 1GB 파일을 생성하는데, 대략 5~10배 정도의 실행 시간 차이가 있었다. |
xms, xmx 옵션을 최대한 크게, 그리고 같게 |
(1) Windows7 64bit (물리적 메모리가 4g인 경우) java -jar -xms4g -xmx4g xxx.jar
재미있는 것은 Windows7 64bit 에서는 이 두 값을 물리적 메모리 보다 크게 잡아도 실행이 된다. 이유는 모르겠다.
(2) Windows XP 32bit (물리적 메모리가 4g인 경우)
java -jar -xms1.5g -xmx1.5g xxx.jar
아마 1~1.5 사이까지 가능할 것이다. 넘어 가면 실행 자체가 안 되는데 실행가능한 최대값을 찾아 사용하자. |
String 대신 StringBuilder를 사용 |
문자열에 여러 가지 조작을 가할 경우이다. 변하지 않는 문자열의 경우, String을 사용하면 된다. String을 사용하여도 컴파일러가 적당히 변환해 준다고는 하지만, 컴파일러는 항상 개발자보다 무식하다.
참고로 실행 속도는 StringBuilder > StringBuffer >> String 이며,
메모리사용량은 StringBuilder = StringBuffer << String 이다.
|
String.split() 대신 StringTokenizer.nextToken()을 사용 |
StringTokenizer.nextToken()는 사용이 불편하지만 빠르며, String.split()는 사용하기 편하지만 느리다.
token이 빈 문자열일 경우, String.split() 은 ""를 해당 배열 원소에 저장해 주지만, StringTokenizer.nextToken() 는 null을 리턴한다.
단 정규식을 구분자로 사용할 경우는 어쩔 수 없이 String.split() 을 사용해야 한다.
|
Buffered~계열 클래스 (BufferedReader, BufferedWriter 등) 를 사용 |
자세한 것은 검색을 통해 |
아래 부터의 출처
실행문장
public void testSuite() throws Exception{ int stringSize[]={100,200,500,1000,5000}; for(int i=0;i<stringSize.length;i++){ LOG_STRING=""; for(int j=0;j<stringSize[i];j++) LOG_STRING+="1234567890"; log(stringSize[i]+"0 bytes"); testFileWriter(); System.gc(); testBufferedWriter(); System.gc(); testFileOutputStream(); System.gc(); testFileBufferedOutputStream(); System.gc(); testFileChannel(); System.gc(); testFileChannelOneBuffer(); System.gc(); } } |
1. FileWriter fw = new FileWriter(LOG_HOME+"writer.log");
// java.io.FileWriter
private void testFileWriter() throws Exception { FileWriter fw = new FileWriter(LOG_HOME+"writer.log"); long st = Timer.getCurrentTime(); for(int i =0;i<loop;i++){ fw.write(LOG_STRING); } log("FileWriter :"+Timer.getElapsedTime(st) +"ms"); fw.close(); }
|
2. BufferedWriter bw = new BufferedWriter(new FileWriter(LOG_HOME+"writer.log"));
|
3. FileOutputStream fos = new FileOutputStream(LOG_HOME+"outputstream.log");
|
4. BufferedOutputStream fos = new BufferedOutputStream(new FileOutputStream(LOG_HOME+"bufferedoutputstream.log"));
|
5. FileChannel fc =(new FileOutputStream(new File(LOG_HOME+"filechannel.log"))).getChannel(); + Byte Buffer 매번 생성
|
6. FileChannel fc =(new FileOutputStream(new File(LOG_HOME+"filechannel.log"))).getChannel(); + ByteBuffer 재사용
|
1K | 2K | 5K | 10K | 50K | |
FileWriter | 31 | 32 | 94 | 203 | 1281 |
FileWriter + BufferedWriter | 15 | 31 | 94 | 188 | 1000 |
FileOutputStream | 32 | 47 | 109 | 188 | 1063 |
FileOutputStream + BufferedOutputStream | 31 | 47 | 109 | 203 | 1578 |
FileChannel | 47 | 63 | 109 | 219 | 2906 |
FileChannel + Byte Buffer 재사용 | 31 | 47 | 188 | 250 | 2766 |
(해당 레코드를 1000번씩 write)