Java에서는 문자열 처리를 위해서 String이라는 기본 Class를 제공합니다.

하지만 String은 구조적 특성상 속도상으로는 효율이 떨어지는 편입니다.

아래의 코드를 예로 들면,

String str = "abc" + "def" + "gh";

str에는 "abcdefgh" 라는 문자열이 최종적으로는 저장되지만..

실제 str에 값이 할당되기 전까지 아래의 4개의 String 객체가 생성됩니다.


new String("abc");

new String("def");

new String("gh");

new String("abcdefgh");


new 로 4개의 객체가 생성되는데, 실제 프로그램에서 느껴지는 체감속도에는 크게 문제가 없는것 처럼 느껴지지만,

parser 개발시 추천, 수만의 위와 같은 String연산을 처리했을시 속도에는 치명적이다.

실제 객체지향 프로그램의 Coding에서 new 를 써서 객체를

메모리상에 할당하는 시간의 비중이 프로그램 수행속도에  가장 큰 영향을 미친다고 볼수 있다.

즉, new를 사용하여 객체를 생성하는 것은 비용이 매우 높은 일중에 하나라 볼 수 있다


그래서 자바에서는 이러한 String상의 문제를 해결하기 위해 StringBuffer를 제공한다.


StringBuffer str = new StringBuffer("abc");

str.append("def");

str.append("gh");


실제 위의 코드는 String과는 달리 str 객체를 단한번 생성하고, 문자열을 추가시킨다.

원리는 String과 달리 StringBuffer는 문자열을 저장하기위해 초기배열을 10정도로 메모리상에 할당한다.

그래서 매번 메모리에 고정된 문자 저장 공간을 할당하는 String에 비해  객체생성에 대한 비용이 상당히 줄어들기 때문에,

문자열 처리의 연산속도가 String에 비해 상당히 빠르다.


하지만 StringBuffer도 고정크기 Buffer를 사용하므로, Buffer크기 이상의 문자열이 할당될 경우,

내부적으로 새로운 Buffer크기의 StringBuffer 객체를 생성하므로 자료의 구조에 따라

일시적으로 속도가 느려지는 문제가 생긴다. 궁극의 해결책은 못된다.


String과 StringBuffer의 공통적인 문제는 문자열 저장을 위해 내부적으로는,

고정크기의 char 배열을 사용하는데 있어, 배열보다 큰 공간이 필요할때,

새로운 객체를 생성하기 때문에 시간적인 비효율이 존재한다.


그래서, 고정공간 배열이 아닌 Linked List 구조의 가변공간 기반의 자료형이 있으니,

이름하여 Java Rope이다.


아래의 사이트에 자세한 설명이 있으니 살펴보도록 하자.

http://www.ibm.com/developerworks/kr/library/j-ropes/index.html


아래는 특정 웹사이트의 URL의 내용을 긁어 오는 코드이다.


 private void loadRope(URL url, int timeout) throws IOException
{
  
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
  
String ct = conn.getContentType(), charset = "euc-kr";
if (ct.indexOf("charset=") > 0)
  charset = ct.substring("charset=".length() + ct.indexOf("charset="));

conn.setConnectTimeout(timeout);
conn.setInstanceFollowRedirects(true);
String contentType = conn.getContentType();

if (contentType != null && contentType.startsWith("text/html")) {
InputStreamReader isr = new InputStreamReader(
conn.getInputStream(), charset);
BufferedReader br = new BufferedReader(isr);
String line = null;
//this.sBuf = new StringBuffer();
while ((line = br.readLine()) != null) {
         this.rope.append(line + "\r\n");
}
   br.close();
} else {
throw new IOException("Invalid URL :" + url);
}
}

BufferedReader로 읽은 문자열을,

StringBuffer와 Rope를 이용해 수행 속도를 측정한 결과 Rope가 5배 이상 빠른 결과를 보여주었다.


물론,

Rope도 만능은 아니다. 하지만 Cursor의 rollback이 없는 parser(lexer)의 구현이라면, 

사용해볼만한 가치가 충분히 있다고 보여진다.


김영곤(gonni21c@gmail)

+ Recent posts