ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • java String 연산속도
    카테고리 없음 2007. 3. 8. 19:17
    아까 쓴 java, ruby, python 속도비교에서 java의 string concat 을 language에서 제공하는 "S = S1 + S2" 형태를 사용했다가 StringBuffer.append()를 쓰는 것과 상상 이상의 속도차이가 난다는 것을 알게 됬다.

    무려 65.695/0.187 = 351.310160428 배..
    350배가 넘는 저 차이는 어디서 오는 것일까..

    s = s1 + i 라는 코드가 어떻게 컴파일되는지 뜯어 보니..
    temp sb = new StringBuilder();
    sb.append(s1);
    sb.append(i);
    c = sb.toString();

    이렇게 되고 있었다. (예전에는 StringBuffer를 사용했는데 StringBuilder로 바뀌었군... - StringBuffer를 사용하도록 -target 1.3을 주고 컴파일해도 속도는 마찬가지로 느림..)

    그렇다면 c = b.append(a); 와 어떤 부분에서 차이가 있을지 고민해 보니 append는 char[] 복사이니 거의 integer operation 이고.. 문제가 될만한 부분은 sb.toString() ...

    풀어보면
    sb.toString()
    = new String(sb)
    = new String(sb.getValue())
    음.. char type이 오가고 있으니 encoding 변환을 하는 것도 아닐진데.. 300배 차이는 많이 오버인데..

    object 생성속도가 느리다는 결론 말고는 없어보인다. memcp가 한두번 더 일어나긴 하지만 300배 차이가 있을것 같지는 않고..
    몇가지 테스트를 더 해보니..

    for() {
    StringBuilder sb = new StringBuilder();
    sb.append(b);
    sb.append(i);
    b = sb.toString();
    }
    로 하였을 경우동일한 속도(당연하지만..)

    StringBuilder sb = new StringBuilder();
    for() {
    sb.setlength(0);
    sb.append(b);
    sb.append(i);
    b = sb.toString();
    }
    로 하였을 경우 13초로 감소..
    아마 이것은 object 생성보다는 내부 buffer expend 과정이 생략되서일 듯하고..


    StringBuilder sb = new StringBuilder();
    for() {
    sb.append(i);
    }
    b=sb.toString();
    으로 하니까 0.3초대로 감소... 이부분은 string copy 한번 덜 하는 효과...

    그런데 이건 반칙이잖아.. 중간에 b = b + i 에서 "b + i"에 해당하는 object 생성을 생략하는 꼴이니까..
    결국 memcopy 가 한번도 없는데, 여러번을 해야 하는 상황이 되서 그랬던 모양이다.

    결론은 python 이나 ruby compiler/interpreter/vm 이 string을 좀더 똘똘하게 처리한다는 얘기가 되는군...

    댓글

Designed by Tistory.