본문 바로가기
프로그래밍 놀이터/안드로이드, Java

[Java] String 을 + 로 연결하는 건 이제 그만! StringBuilder 로 간단하게 메모리와 퍼포먼스를 동시에 잡아보자.

by 돼지왕 왕돼지 2012. 1. 12.
반응형



1. Prerequisite & References


- Java에 관한 기초지식.

[Java] Garbage Collection ( GC ) 가 뭔가요? GC 기초부터 고급까지!





2. Intro


제목만 보고는 무슨 말인지 모르겠어요


 네, 자세히 설명해 드리겠습니다. String 관련된 코드를 보면 다음과 같은 구문을 쉽게 찾을 수 있을 것입니다.

String information = "CK";
information += " lives in ";
information += "Seoul";
information += " likes ";
information += "delicious foods ";
information += "such as";
information += "Sushi,";
information += "Fried Chicken,";
information += " and so on";


 자 피하고자 하는 코드는 바로 이런 string 을 + 로 연결하여 새로운 string을 만드는 것입니다.

이런 String + 연산은 메모리 문제와 퍼포먼스 문제를 야기할 수 있다는 것이죠.






3. Information


String을 + 로 연결하면 생기는 문제


 앞서 설명한 것처럼 string 의 + 연결은 메모리 문제와 퍼포먼스 문제를 야기할 수 있습니다.
먼저 메모리 문제부터 보고 갈까요?


메모리 문제


 예시로 제공한 코드는 사실 다소 억지스러운 부분이 있긴 합니다. 누가 저렇게 쓰겠습니까?
하지만 저것은 그냥 저런 "식" 의 코드는 안 된다는 idea 를 보여드리기 위함이었습니다.

그럼 무엇이 메모리 문제를 초래하는 걸까요?
사실 많은 Java 개발자분들이 String 을 primitive type ( int, float 등과 같은 기본형 ) 으로 여기고 사용하고 있지만 
첫 글자를 대문자로 썼다는 점에서도 알 수 있듯이 String 요녀석은 사실 class입니다.

class 라는 것은 heap 메모리를 차지한다는 이야기지요.
따라서 "CK", " lives in", "Seoul" 등 저런식의 즉각적인 String 객체 생성도 모두 메모리를 잡아먹는 행위입니다.

자 문제는 여기에 있습니다.

String information = "CK ";
information += "lives in";

 

 을 하게 되면, information이 차지하는 memory 의 size 가 달라집니다.
더 이상 "CK"와 "lives in"은 필요없고 "CK lives in"이라는 String 만 필요하게 되죠.
그럼 여기서 기대되는 operation 은 무엇일까요?
"CK" 와 "lives in"의 GC와 "CK lives in"을 위한 새로운 메모리 주소 할당입니다.

자 이제 감이 오시나요?
저런식으로 + 로 연결하여 assign 하게 된다면 + 하는 String 의 갯수가 늘어나면 늘어날수록
GC 대상 object 수도 함께 늘어나고 그만큼 memory 할당도 추가로
늘어나게 된다는 것입니다.

이게 문제가 되냐구요?
일반 프로그래밍에서는 저런 코드를 찾아보기 힘들고, 그렇게 많은 String을 더하지 않는지도 모릅니다.
하지만 이 문제는 query 문을 만드는데서 많이 발생합니다.
Query Operation은 매우 무거운 작업입니다.
복잡한 Database 를 쓰는 경우, 여러번의 query 를 통해 결과를 도출하는 것은 엄청난 시간을 소비하기도 합니다.
따라서 가능한 query 횟수를 최소화 하여 원하는 결과를 뽑아내는 작업이 필요하며 이 과정에서
String + operation이 엄청나게 발생하곤 합니다.

따라서 메모리의 소모량이 엄청나게 되어 버리는 것이죠.


Performance


 메모리 문제는 결국 Performance 문제로 직결됩니다.
반복적 Memory의 할당과 GC는 때문이죠.
메모리 할당 자체도 문제가 되지만, GC가 더 큰일입니다.

GC의 방식에 따라 어플리케이션이 버벅대거나 심하면 한동안 멈출 수도 있습니다.
또한 메모리를 많이 사용하면 가상메모리를 써야 하는 상황이 생기기도 하는데,
아시다시피 가상메모리를 사용하면 performance 라는 단어는 입 속으로 쏙~

메모리 할당과 GC 등이 성능에 미치는 영향은
다음을 참고하시기 바랍니다.

[Java] Garbage Collection ( GC ) 가 뭔가요? GC 기초부터 고급까지!






그럼 + 가 필요한 상황에 어떻게 대처해야 해요?


StringBuilderStringBuffer Class 를 사용하여 String 을 조합해야 합니다.
이 녀석들은 string 들을 연결하여 조합할 때 새로운 메모리주소를 할당하여 결과를 assign 하는 형태가 아닌,
기존에 있던 메모리 주소에서 크기를 확장하여 결과를 assign 하는 형태로 새로운 메모리 할당과 GC를 많이 줄일 수 있습니다.
사용방법은 다음과 같습니다.

StringBuilder sb = new StringBuilder( "CK " );
sb.append( "lives in " );
sb.append( "Seoul ");
...




그럼 StringBuilder 나 StringBuffer만 쓰면 만사 오케이인가요?


 모든지 "완벽"이란건 없죠 세상에. 특히나 IT 를 비롯한 공학 세상에는 TradeOff 란 걸 항상 생각해야 합니다.
몇개의 String을 조합하는데 StringBuilder 를 쓴다면 코드를 복잡하게 하여 가독성을 떨어뜨릴 뿐더러,
StringBuilder 라는 객체를 따로 관리해야 하기도 하죠.
그래서 "만사오케이"라고 말하기는 그렇지만 대부분은 둘이 더 좋다고 볼 수 있습니다.



StringBuilder와 StringBuffer가 같은 기능을 수행하는데 왜 Class 를 두개로 나눠둔건가요?


 사실 하는 일은 같지만 thread 측면에서 차이가 있습니다.
StringBuilder thread-safe 하지 않고, StringBufferthread-safe 합니다.
Thread-safe 같은 기능이 추가되면 당연히 performance 측면에서 불리하겠죠?
그래서 StringBuilder 가 사실 더 빠릅니다.
Multi thread 환경에서는 둘 중 어떤 것을 사용할 지 잘 고려해야겠습니다.



그럼 대부분 StringBuffer와 StringBuilder가 유리한데 Java는 왜 + 기호를 남겨뒀을까요?


 바로 똑독한 Compiler 대문이죠.
간단한 String + 연산들은 Compiler에서 자동으로 StringBuffer와 StringBuilder로 바꾸어 버렵니다.
즉 Compiler에서 변환가능한 '간단한' String + 연산은 알아서 좋은 성능을 내도록 내부적으로 변경 해준다는 것입니다.
다만, Compiler에서는 이 자동변환에 대해 완벽하지 않기 때문에 
복잡한 녀석들에 대해서는 프로그래머의 노력이 반드시 동반되야 하겠지요.
( 가능하면 StringBuilder나 StringBuffer를 사용하자는 의미입니다. )






 [CharSequence에 대해]

 




4. Summary


- String 의 + 연산은 메모리 할당과 GC 유발로 메모리 릭 ( Memory Leak )과 성능 저하 ( Performance Degradation )을 초래할 수 있다.

- 이 문제를 피하려면 StringBuilder 나 StringBuffer를 써야 한다. 둘은 thread-safe 지원 여부가 다르다.

- 간단한 + 연산은 컴파일러에서 StringBuilder 나 StringBuffer 형태로 자동 변환하여 수행한다.

- CharSequence Interface를 잘 사용하면 추가적 최적화를 꾀할 수 있다.




5. References


http://developer.android.com/reference/java/lang/StringBuilder.html 
  Android StringBuilder Java Doc.

http://developer.android.com/reference/java/lang/StringBuffer.html 
  Android StringBuffer Java Doc.

http://developer.android.com/reference/java/lang/CharSequence.html 
  Android CharSequence Java Doc.

- [자바 성능을 결정짓는 코딩 습관과 튜닝 이야기], 이상민 저, 한빛미디어
 자바의 성능에 관련된 여러가지 사항들을 소개하는 책으로 자바 중급자정도가 읽으면 좋은 책. 


반응형

댓글