• StringBuilder vs System.out.println :: 마이구미
    Java 2016. 12. 28. 20:16
    반응형

    이번 글의 제목은 "StringBuilder vs System.out.println" 이다.

    글의 목적은 알고리즘 문제들의 시간을 줄이는 것이다.

    그렇다면 어떻게 줄일 수 있는지 천천히 살펴보자.


    대부분 알고 있듯이 System.out.println은 출력을 하기 위해 사용하고 있다.


    int a = 123;

    System.out.println(a);

    // 123

    System.out.println("Hello World!");

    // Hello World!


    간단히 보면 표준 입출력 기능을 제공해준다고 봐도 된다.

    그렇다면 조금 더 깊게 System.out.println을 내부적으로 어떻게 되어있는지 보자.


    public void println(String x) { synchronized (this) { print(x); newLine(); } }


    단어 그대로 print는 출력 부분, newLine은 새로운 줄을 생성하는 것이다.

    그리고 보다시피 synchronized block으로 씌여져 있는 걸 확인할 수 있다.


    synchronized는 무엇인가?

    해석 그대로 동기화다.

    필요한 내용이므로 살짝 알아보고 가겠다.

    하나의 프로세스에는 하나 이상의 스레드가 존재한다.

    스레드를 통해 같은 프로세스에서 데이터 공유가 가능하다.

    때론 공유 데이터가 작업 중인 스레드가 마칠 때까지 다른 스레드에서 접근하지 못하도록 하기 위한 것이 synchronized(동기화)이다.

    동기화의 단점은 작업중인 스레드가 마칠 때까지 다른 스레드들이 대기시간이 발생한다는 것이다.


    즉, System.out.println 또한 동기화가 적용되어 있는 것이다.

    그렇기에 작더라도 오버헤드가 발생되게 되는 것이다.

    오버헤드(overhead)는 어떤 처리를 하기 위해 들어가는 간접적인 처리 시간 · 메모리 등을 말한다.

    예를 들어 A라는 처리를 단순하게 실행한다면 10초 걸리는데, 안전성을 고려하고 부가적인 B라는 처리를 추가한 결과 처리시간이 15초 걸렸다면, 오버헤드는 5초가 된다. 또한 이 처리 B를 개선해 B'라는 처리를 한 결과, 처리시간이 12초가 되었다면, 이 경우 오버헤드가 3초 단축되었다고 말한다.

    아래와 같이 테스트케이스가 1억개라서 1억번의 출력이 필요하다면 1억번의 System.out.println 호출이 필요하다면 어떨까?


    for(int i=0;i<100000000;i++) {

    System.out.println(i);

    }


    오버헤드 쌓여 성능 저하를 초래하게 된다.

    이러한 이유로 프로젝트에서는 System.out.println으로 로그를 남기지 말라는 이야기가 있는 것이다.


    그렇기에 알고리즘 문제에서는 출력할 데이터들을 모아두고 한번의 System.out.println을 이용해 출력하는 방법을 사용한다.


    그 방법을 StringBuilder을 활용하는 것이다.

    StringBuilder 클래스는 String과 동일하지만 문자열을 보다 쉽게 조작할 수 있는 클래스이다.

    자세한 건 문서를 보면 된다.


    StringBuilder sb = new StringBuilder();


    for(int i=0;i<100000000;i++) {

    sb.append(i + "\n");

    }


    System.out.println(sb.toString());


    위 소스처럼 출력 데이터를 append 메소드를 통해 계속 붙여나가다가 마지막에 System.out.println를 호출해서 출력할 수 있게 된다.

    실제 알고리즘 문제에서 1000000번의 테스트 케이스가 존재하는 곳을 제출해보았다.



    StringBuilder 적용



    위와 같이 속도 차이가 크게 나는 걸 확인할 수 있다.

    자칫 잘못하면 시간 초과를 당할 수도 있기에 주의하자.

    프로젝트나 알고리즘 문제 상관없이 System.out.println 을 이해하고 사용해야한다.


    StringBuilder 클래스 문서

    https://docs.oracle.com/javase/7/docs/api/java/lang/StringBuilder.html

    반응형

    댓글 0

Designed by Tistory.