편안한 마음으로 LinkedList를 사용하면 휴식을 취할 수 있어요.

3425 단어 Java성능

두루뭉술하게 말하다


목록 구조의 데이터에 대해 무작위로 접근할 수 없습니다.오빠와의 약속!

발단


몇 년 전 다른 부서의 지원을 받아 제작된 자바 시스템은 조금 더 큰 데이터가 삽입되면 느릴 테니 도와주세요.
조회와 색인을 살펴봤으면 좋겠군... 코를 파면서 지원해.

처리 내용


느린 부분의 처리는 다음과 같다.
  • 처리 객체의 데이터를 List로 받습니다.
  • for 순환에서 하나하나 예처리를 합니다.
  • 처리 결과를 대상에 저장하고 OR 매핑기로 처리 결과를 INSERT에서 DB에 저장합니다.
  • 이게 다야?
    네, 이게 다예요.이런 고급스러운 일을 병행하여 처리하는 것은 당연히 할 수 없다.

    인프라 조사


    처리 중인 서버의 상태를 조사합니다.이번 인프라는 전형적인 3층 3 서버 구성이다.
    WEB 서버는 모든 것에 여유가 있습니다.
    AP 서버에서 CPU 하나가 부족합니다.
    14코어 서버(EC2의 c4.4xlarge)인 만큼 한 CPU가 아무리 노력해도 7%의 사용률을 기록한다는 게 슬프다.
    DB 서버는 디스크 로드가 다소 있지만 성능은 충분합니다.
    네트워크, 메모리 등도 조사했지만 모든 자원이 남았다.
    각종 설정치도 정상이다.

    데이터베이스 주변 조사


    보시다시피 이것은 거의 INSERT에서만 처리됩니다.
    이 때문에 AP의 CPU 부하에 신경을 많이 썼지만, 현장의 모든 이들이 DB 주변에 다양한 문제가 있다고 의심했다.
    마지막에 OR 매핑기 밟은 거 아니야?JDBC라는 그리운 경험을 직접 활용하는 목소리도 있다.
    그러나 성과가 없어 발끈한 휴일 출근을 결정했다.

    들키다


    기본으로 돌아가 논리적 처리 시간을 분석하다.
    "순환 횟수가 늘어나면서 처리가 무거워진 것 같다"는 증언에 따르면
    우리는 순환 횟수와 순환하는 처리 시간 간의 관계를 제기하기로 결정했다.
    다음은 분석 결과의 이미지입니다.입력 데이터 양을 변경해 N만건과 2N만건으로 비교했다.

    "후반부 줄었어...!"
    작은 데이터는 큰 데이터의 앞부분을 잘라낸 것이기 때문에 데이터 내용에 따라 변동하지 않는다.
    더 자세히 분석하면 도표 맨 위에 가장 시간이 걸리는 줄은 다음과 같다.
    변수data의 유형은List<MyClass>이다.
    MyClass record = data.get(i);
    
    나는 이것 때문에 간담이 서늘해졌다.오직 리스트에게서 요소를 얻는 것만은 매우 느리다.
    누군가가 입을 열었다.
    '링크드 리스트 아니에요?'
    링크드리스트 2N만점의 N만건을 꺼내는 데 시간이 많이 걸렸다.
    아마 리스트 크기의 절반을 기준으로 뒷부분의 데이터는 엉덩이부터 접근했을 거예요.
    우리를 쉬게 하는 고장은 for문을 확장for문으로 바꾸는 팩스 수준의 변경으로 끝났다.
    for (int i = 0; i < data.size(); i++) {
        MyClass record = data.get(i);
        ...
    }
    
    int i = 0;
    for (MyClass record: data) {
        ...
        i++;
    }
    
    언뜻 보기에 이것은 무슨 차이가 있습니까?변경되었지만 List의 경우 변경 전 랜덤 액세스
    변경된 후 (Iterator의) 순서에 따라 접근할 때 데이터 건수가 많을 때 성능에 있어서 구름과 진흙의 차이가 나타난다.

    많이 배웠어요.


    처음에 확장 for문장을 사용하지 않은 이유는 처리 중에도 i의 값을 사용하고 싶었기 때문이다.
    Java에도 파이톤의 enumerate가 있었으면 좋겠는데... (불평)

    좋은 웹페이지 즐겨찾기