어느 방식이 효율적일까.

DeadWhale·2023년 2월 23일
0

JAVA

목록 보기
5/10

어느 방식이 효율적일까.

개요

회사 업무를 하는 도중 JSON 노가다를 어쩔수 없이 해야하는 경우가 생겼다

코드를 작성하면서 SELCET 해 온 LIST을 반복하며
JSON Object를 생성해 JSON Array에 적재하는 일이였는데

매 반복마다 객체를 생성하는것과 객체를 초기화 해 사용하는것의 장단점이 궁금해져 작성하게 되었다.

생각

처음에는 하나의 객체를 초기화하면서 저장하는 방식이 무조건 빠를것이라고 생각했다.

객체를 생성하는 속도보다 ,객체를 초기화 하는 속도가 빠를것이라고 생각했기 때문이다

다른 팀원이 왜 이렇게 써야하냐고 물어보면 대답할수 있도록

일단 이 코드를 구현해봐서 실제로 빠른지 비교해보고 설명할 수 있도록 학습 해봐야겟다.


비교

private static void whatTheFast() {
    long createStr = System.currentTimeMillis();
    JSONObject jsonObject = new JSONObject();
    long createEnd = System.currentTimeMillis();
    System.out.println("객체를 생성 하는 속도 : " + (createEnd-createStr) + " ms.");

    long start = System.currentTimeMillis();
    jsonObject.clear();
    long end = System.currentTimeMillis();
    System.out.println("객체를 초기화 하는 속도 : " + (end - start) + " ms.");
}
객체를 생성 하는 속도 : 6 ms.
객체를 초기화 하는 속도 : 0 ms.

JSON에 값이 하나도 없을때에는 당연히 초기화 하는 속도가 훨씬 빠르다.

더미 데이터를 50개정도 넣어보고 테스트를 더 넣어봤다.

private static void whatTheFast() {
    long createStr = System.nanoTime();
    JSONObject jsonObject = new JSONObject();
    long createEnd = System.nanoTime();
    System.out.println("객체를 생성 하는 속도 : " + (createEnd-createStr) + " Nms.");

    for (int o=0; o<500; o++) jsonObject.put(String.valueOf(o),o);

    long start = System.nanoTime();
    jsonObject.clear();
    long end = System.nanoTime();
    System.out.println("객체를 초기화 하는 속도 : " + (end - start) + " Nms.");
}
객체를 생성 하는 속도 : 6342417 Nms.
객체를 초기화 하는 속도 : 12875 Nms.

더 자세하게 보기 위해 nano time으로 변환해 테스트 해봤다.
최대 50000개까지 넣어봤는데 변함 없이 비교하기 힘들 정도로 객체의 초기화가 더 빠르다

Json의 초기화는 왜 빠를까?

JSONObject의 내부 구현은 HashMap의 구조를 가진다.

clear도 그냥 HashMapclear를 사용한다.

# HashMapclear()

public void clear() {
      Node<K,V>[] tab;
      modCount++;
      if ((tab = table) != null && size > 0) {
          size = 0;
          for (int i = 0; i < tab.length; ++i)
              tab[i] = null;
      }
  }
  • tab은 내부 해시테이블을 가르킨다.
  • modCount는 수정 횟수를 의미하는 변수이다
  • 지역변수로 선언 되어 있는 해시테이블을 인스턴스변수 tab에 대입 후
    • null && 길이가 1이상 일때 사이즈를 0으로 초기화 한 후 (사이즈는 테이블의 데이터 개수를 의미)
    • 각 배열을 반복하며 모든 객체에 null을 대입한다.

이 메소드를 보면 알 수 있듯이 O(n)의 시간 복잡도를 가지게 된다.

하지만 객체의 생성도 O(n)의 시간 복잡도를 가진다

  1. 객체의 생성은 메모리에 할당하는 시간도 필요하다

  2. 객체의 초기화는 객체를 한번만 할당하고 필드의 값을 변환하는 과정만 있기 때문에 비용이 절약된다.

  3. 객체 생성은 GC의 과도한 발생을 유발한다.

  4. 초기화의 경우 객체의 메모리 위치가 항상 일정해 캐시 히트율이 높아져 성능이 개선될 수 있다고 한다.

    캐시 메모리에는 데이터를 저장하는 작은 용량의 메모리가 할당되어 있다

    프로그램이 반복적으로 같은 메모리 주소에 접근할 경우
    해당 메모리 주소에 대한 데이터가 캐시에 이미 존재하고 있다면
    캐싱히트가 발생해 더욱 빠르게 가져올 수 있다.

    캐시 메모리의 성능을 평가하는 지표로 자주 활용된다고 한다.
    오늘 처음 알았는데 나중에 이 부분에 대해 공부하면 재밌을것 같다


결과

당연히 초기화가 빠를것같다고 생각은 했지만 팀원이나 상사가 왜 그렇냐고 물어보면
딱 조리있게 설명할 자신이 없어 잘 말해보기 위해 작성해 보았다.

JSON외에도 MAP을 반복하면서 생성하는 코드들이 회사의 코드중 여럿 발견되었는데
오늘 알게된 지식을 바탕으로 다른 사람에게 설명해봐야겟다.

0개의 댓글