달력

52024  이전 다음

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
# 테스트 환경
1. jdk1.6.0_23
2. 프로파일링 옵션 : -Xrunhprof:cpu=samples,file=d:/cpu1.txt,depth=3
runhprof 옵션은 jdk 가 제공하는 기본 프로파일링 기능으로 자세한 내용은 "java -Xrunhprof:help" 명령어를 통해 확인할 수 있음
3. 테스트 항목
- StopWatch 를 사용한 메서드 시작과 종료 직전의 시각을 측정
- runhprof 옵션을 통한 cpu 타임 샘플링

# 테스트 케이스 및 테스트 소스와 소요시간(단위 밀리세컨드)
1. 문자열 연산(O), 10만번, slf4j - 5번 테스트해서 평균 산정
@Test
public void test() {
    StopWatch watch = new StopWatch();
    watch.start();
    for (int i = 0; i < 100000; i++) {
        LOGGER.info("a" + "b" + "c" + "d");
    }
    watch.stop();
    LOGGER.info(String.valueOf(watch.getTotalTimeMillis()));
}

total time, cpu time : 7839, 1170
total time, cpu time : 8288, 1146
total time, cpu time : 8123, 1129
total time, cpu time : 8228, 1180
total time, cpu time : 8093, 1222

2. 문자열 연산(X), 10만번, slf4j - 5번 테스트해서 평균 산정
@Test
public void test() {
    StopWatch watch = new StopWatch();
    watch.start();
    for (int i = 0; i < 100000; i++) {
        LOGGER.info("abcd");
    }
    watch.stop();
    LOGGER.info(String.valueOf(watch.getTotalTimeMillis()));
}

total time, cpu time : 7854, 1132
total time, cpu time : 7920, 1169
total time, cpu time : 8078, 1226
total time, cpu time : 7931, 1153
total time, cpu time : 8072, 1118

# JDK 가 처리하는 문자열 처리 방식이 나뉘네요.
두분이 댓글 달아주신것처럼 추가로 확인해봤습니다. (2011년1월3일 추가)


3. 로그레벨 체크, 10만번, slf4j - 5번 테스트해서 평균 산정
 @Test
public void test() {
    StopWatch watch = new StopWatch();
    watch.start();
    for (int i = 0; i < 100000; i++) {
        if (LOGGER.isInfoEnabled()) {

        }
    }
    watch.stop();
    LOGGER.info(String.valueOf(watch.getTotalTimeMillis()));
}

total time, cpu time : 3, 104
total time, cpu time : 3, 107
total time, cpu time : 4, 103
total time, cpu time : 3, 107
total time, cpu time : 2, 106

4. 로그레벨보다 하위레벨로 로깅(실제로는 찍히지 않는 형태), 10만번, slf4j - 5번 테스트해서 평균 산정
 @Test
public void test() {
    StopWatch watch = new StopWatch();
    watch.start();
    for (int i = 0; i < 100000; i++) {
        LOGGER.debug("abcd");
    }
    watch.stop();
    LOGGER.info(String.valueOf(watch.getTotalTimeMillis()));
}

total time, cpu time : 3, 106
total time, cpu time : 4, 104
total time, cpu time : 3, 105
total time, cpu time : 3, 106
total time, cpu time : 3, 104

5. 문자열 연산(O), 100만번, log4j - 1번 테스트해서 평균 산정
 @Test
public void test() {
    StopWatch watch = new StopWatch();
    watch.start();
    for (int i = 0; i < 1000000; i++) {
        LOGGER.info("a" + "b" + "c" + "d");
    }
    watch.stop();
    LOGGER.info(String.valueOf(watch.getTotalTimeMillis()));
}

total time, cpu time : 74702, 11390

5. 문자열 연산(O), 100만번, slf4j - 1번 테스트해서 평균 산정
 @Test
public void test() {
    StopWatch watch = new StopWatch();
    watch.start();
    for (int i = 0; i < 1000000; i++) {
        LOGGER.info("{}{}{}{}", new Object[] {"a", "b", "c", "d"});
    }
    watch.stop();
    LOGGER.info(String.valueOf(watch.getTotalTimeMillis()));
}

total time, cpu time : 76899, 11532

6. ReflectionToStringBuilder 연산, 10만번, slf4j - 1번 테스트해서 평균 산정
 @Test
public void test() {
    StopWatch watch = new StopWatch();
    watch.start();
    for (int i = 0; i < 100000; i++) {
        LOGGER.debug(ReflectionToStringBuilder.toString(article, ToStringStyle.MULTI_LINE_STYLE));
    }
    watch.stop();
    LOGGER.info(String.valueOf(watch.getTotalTimeMillis()));
}

total time, cpu time : 12985, 2656

# ReflectionToStringBuilder.toString() 처리를 해당 모델 클래스의 toString() 을 오버라이딩하면서 처리하는 것으로 배봤습니다. (2011년1월3일 추가)

# 평균수치(단위 밀리세컨드)
1. 문자열 연산(O), 10만번, slf4j
total time, cpu time : 8114.2, 1169.4

2. 문자열 연산(X), 10만번, slf4j
total time, cpu time : 7971, 1159.6

3. 로그레벨 체크, 10만번, slf4j
total time, cpu time : 3, 105.4

4. 로그레벨보다 하위레벨로 로깅(실제로는 찍히지 않는 형태), 10만번, slf4j
total time, cpu time : 3.2, 105

5. 문자열 연산(O), 100만번, log4j
total time, cpu time : 74702, 11390

5. 문자열 연산(O), 100만번, slf4j
total time, cpu time : 76899, 11532

6. ReflectionToStringBuilder 연산, 10만번, slf4j
total time, cpu time : 12985, 2656

# 정리
- 1, 2번 경우를 볼때, 문자열 연산으로 인한 차이(8114, 7971)가 크지 않은 것 같다.
- 1, 2번 경우는 JDK 컴파일 과정의 최적화 작업으로 성능테스트 결과 차이가 없다.
- Logger로 찍어주는 문자열 자체가 연산에 의해 생성될 경우 LOGGER.isInfoEnabled() 형태로 체크하는 것이 성능상 좋을 수 있다.
- Logger로 찍어주는 문자열 자체가 특별한 연산에 의해 생성되는 경우가 아닐 경우, Logger 자체가 로그 레벨 체크 후 로깅 여부를 판단하는데 LOGGER.isInfoEnabled() 형태로 체크하지 않아도 특별한 성능상의 차이가 발생하지 않을 것으로 보인다.
- 5, 6번 경우를 볼때, log4j와 slf4j의 성능차가 크다고 보기는 어렵다.
- ReflectionToStringBuilder.toString() 처럼 문자열을 생성하는 연산의 비용이 클 경우 LOGGER.isInfoEnabled() 를 사용해서 체크하거나 해당 모델 클래스의 toString을 오버라이드 하고 slf4j 의 파라미터 인자로 처리하면 성능의 이점이 있다.

Posted by fromm0
|

[jersey] 1.0.2 릴리즈

자바 2009. 3. 1. 22:51
사내 인터페이스 작성을 위해 jersey를 사용하고 있는데 1.0.2 버전이 릴리즈되었습니다.
많은 버그를 수정했고 다음의 개선사항이 있었다고 합니다.

1. The JSON with JAXB "natural" convention
JAXB 모델을 사용해서 JSON 처리를 하거나 JSON을 다시 JAXB모델로 변경하는데 개선사항이 있다는 것으로 보입니다.
2. JSON with padding provider.
JSONP 에 대한 지원이 추가된 것입니다. JSONP 에 대해 검색을 해보니 다음처럼 설명을 하고 있군요.
JSONP(JSON with Padding)는 "Dynamic Script Tags" 혹은 "On Demend Javascript" 라고 불리는 기술을 이용하여 다른 웹사이트로 HTTP 요청을 보내고 자바스크립트 콜백 함수를 통해 실행결과를 통보 받는 방식으로 수행되는 JSON 기반 RPC 규약입니다. 이렇게 하면 브라우저의 보안 정책인 “Same Origin Policy” 제약을 넘어서서 원격 서버와의 통신이 가능해지는데, 야후의 일부 API들, 그리고 최근 개선된 Google Calendar API 등이 이미 이러한 방식을 사용하고 있습니다.
3. Resource method specific filters.
4. Atom Abdera support.
아파치의 atom 구현체인 Apache Abdera 프로젝트의 Atom 엔트리와 Feed 자바타입을 지원
5. Implicit produces.
6. Servlet as a filter.
7. Client using Apache HTTP client.
8. Pavel Bucek has added support for SSL configuration of the Client API when using HttpURLConnection

공부를 게을리 했더니 용어들이 모두 어렵습니다.
일단 내일 라이브러리 업데이트하고 API나 문서를 보면서 실제 내용을 파악해야 할 것으로 보입니다.

좀더 자세한 내용은 http://blogs.sun.com/sandoz/entry/jersey_1_0_2_is 를 참고하시면 됩니다.

'자바' 카테고리의 다른 글

[CI툴] hudson  (0) 2009.04.05
[JSON] Jackson JSON Processor  (0) 2009.03.01
[ibatis] 개발자 가이드 업데이트  (0) 2009.02.28
[ibatis] 메일링리스트를 통해서 본 3.0 소식  (2) 2009.02.15
[자바] 인코딩  (1) 2009.01.30
Posted by fromm0
|
import java.io.Writer;
import java.util.regex.Pattern;

import com.thoughtworks.xstream.core.util.QuickWriter;
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;

public class MyPrettyPrintWriter extends PrettyPrintWriter {
    private static final char[] AMP = "&amp;".toCharArray();
    private static final char[] LT = "&lt;".toCharArray();
    private static final char[] GT = "&gt;".toCharArray();
    private static final char[] SLASH_R = " ".toCharArray();
    private static final char[] QUOT = """.toCharArray();
    private static final char[] APOS = "'".toCharArray();
   
    public LocalPrettyPrintWriter(Writer writer) {
        super(writer);
    }

    protected void writeText(QuickWriter writer, String text) {       
       
        String CDATAPrefix = "&lt;![CDATA[";
        String CDATASuffix = "]]&gt;";

        if (!text.startsWith(CDATAPrefix) &amp;&amp; !Pattern.matches("[^[0-9]]+", text)) {
            text = CDATAPrefix+text+CDATASuffix;
        }
       
        int length = text.length();
        if (!text.startsWith(CDATAPrefix)) {
            for (int i = 0; i &lt; length; i++) {
                char c = text.charAt(i);
                switch (c) {
                case '&amp;':
                    writer.write(AMP);
                    break;
                case '&lt;':
                    writer.write(LT);
                    break;
                case '&gt;':
                    writer.write(GT);
                    break;
                case '"':
                    writer.write(QUOT);
                    break;
                case '\'':
                    writer.write(APOS);
                    break;
                case '\r':
                    writer.write(SLASH_R);
                    break;
                default:
                    writer.write(c);
                }
            }
        } else {
            for (int i = 0; i &lt; length; i++) {
                char c = text.charAt(i);
                writer.write(c);
            }
        }
    }
}


import java.io.Writer;

import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.xml.XppDriver;

public class MyXppDriver extends XppDriver {

    public HierarchicalStreamWriter createWriter(Writer out) {
        return new MyPrettyPrintWriter(out);
    }
}





Posted by fromm0
|