ArrayList vs Vector vs LinkedList 성능 테스트

jy.YOON·2022년 9월 12일
0

자바

목록 보기
3/8
post-thumbnail

1.성능테스트

데이터 읽기 테스트

LOOP_COUNT 만큼 데이터를 각 리스트에 넣어두고

순차적으로 데이터를 읽는 테스트

테스트 코드

import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.TimeUnit;

@State(Scope.Thread)
@BenchmarkMode({Mode.AverageTime})
@OutputTimeUnit(TimeUnit.MICROSECONDS) //밀리세컨드 단위로 출력
public class ListGet {
    int LOOP_COUNT = 1000;
    List<Integer> arrayList;
    List<Integer> vector;
    LinkedList<Integer> linkedList;

    int result=0;

    @Setup
    public void setUp(){
        arrayList=new ArrayList<Integer>();
        vector=new Vector<Integer>();
        linkedList=new LinkedList<>();

        for (int loop=0; loop<LOOP_COUNT; loop++){
            arrayList.add(loop);
            vector.add(loop);
            linkedList.add(loop);
        }
    }

    @Benchmark
    public void getArrayList(){
        for (int loop=0; loop<LOOP_COUNT; loop++){
            result=arrayList.get(loop);
        }
    }

    @Benchmark
    public void getVector(){
        for (int loop=0; loop<LOOP_COUNT; loop++){
            result=vector.get(loop);
        }
    }

    @Benchmark
    public void getLinkedList(){
        for (int loop=0; loop<LOOP_COUNT; loop++){
            result=linkedList.get(loop);
        }
    }

    public static void main(String[] args) throws RunnerException {
        Options opt = new OptionsBuilder()
                .include(ListGet.class.getSimpleName())
                .forks(2)
                .warmupIterations(5)
                .measurementIterations(5)
                .build();

        new Runner(opt).run();
    }
}

ArrayList 속도가 가장 빠르다.

그 다음으로 Vector LinkedList 순으로 속도가 나왔음

LinkedList가 가장 늦게 나온 이유는 Queue 인터페이스를 상속받기 때문. 기존 데이터를 읽는 메서드를 수정해보자

get -> peek

수정전

   @Benchmark
    public void getLinkedList(){
        for (int loop=0; loop<LOOP_COUNT; loop++){
            result=linkedList.get(loop);
        }
    }

수정후

   @Benchmark
    public void getLinkedList(){
        for (int loop=0; loop<LOOP_COUNT; loop++){
            result=linkedList.peek(loop);
        }
    }

image-20220912122216741

수정후에는 ArrayList 는 여전히 빠르고 LinkedListVector 순으로 순서가 바뀌었다.

ArrayList와 Vector의 성능차이 이유는?

Vector는 get() 메서드에 synchronized가 선언되어 있기때문에 성능저하가 발생할 수 있다.

    public synchronized E get(int index) {
        if (index >= elementCount)
            throw new ArrayIndexOutOfBoundsException(index);

        return elementData(index);
    }

데이터 삭제 테스트

LOOP_COUNT 만큼 데이터를 각 리스트에 넣어두고 첫번째 인덱스 삭제, 마지막 인덱스 삭제 테스트

import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.TimeUnit;

@State(Scope.Thread)
@BenchmarkMode({Mode.AverageTime})
@OutputTimeUnit(TimeUnit.MICROSECONDS) //밀리세컨드 단위로 출력
public class ListRemove {
    int LOOP_COUNT = 10;
    List<Integer> arrayList;
    List<Integer> vector;
    LinkedList<Integer> linkedList;

    int result=0;

    @Setup(Level.Trial)
    public void setUp(){
        arrayList=new ArrayList<Integer>();
        vector=new Vector<Integer>();
        linkedList=new LinkedList<>();

        for (int loop=0; loop<LOOP_COUNT; loop++){
            arrayList.add(loop);
            vector.add(loop);
            linkedList.add(loop);
        }
    }

    @Benchmark
    public void removeArrayListFromFirst(){
        ArrayList<Integer> tempList = new ArrayList<Integer>(arrayList);
        for (int loop=0; loop<LOOP_COUNT; loop++){
            tempList.remove(0);
        }
    }

    @Benchmark
    public void removeVectorFromFirst(){
        List<Integer> tempList = new Vector<Integer>(vector);
        for (int loop=0; loop<LOOP_COUNT; loop++){
            tempList.remove(0);
        }
    }

    @Benchmark
    public void removeLinkedListFromFirst(){
        LinkedList<Integer> tempList = new LinkedList<Integer>(linkedList);
        for (int loop=0; loop<LOOP_COUNT; loop++){
            tempList.remove(0);
        }
    }

    @Benchmark
    public void removeArrayListFromLast(){
        LinkedList<Integer> tempList = new LinkedList<Integer>(linkedList);
        for (int loop=LOOP_COUNT-1; loop>=0; loop--){
            tempList.remove(loop);
        }
    }

    @Benchmark
    public void removeVectorFromLast(){
        LinkedList<Integer> tempList = new LinkedList<Integer>(linkedList);
        for (int loop=LOOP_COUNT-1; loop>=0; loop--){
            tempList.remove(loop);
        }
    }

    @Benchmark
    public void removeLinkedListFromLast(){
        LinkedList<Integer> tempList = new LinkedList<Integer>(linkedList);
        for (int loop=0; loop<LOOP_COUNT; loop++){
            tempList.removeLast();
        }
    }


    public static void main(String[] args) throws RunnerException {
        Options opt = new OptionsBuilder()
                .include(ListRemove.class.getSimpleName())
                .forks(2)
                .warmupIterations(10)
                .measurementIterations(10)
                .build();

        new Runner(opt).run();

    }
}

ArrayListVector 의 첫번째 값을 삭제하는 것이 유독 느린것을 확인할 수 있다.

앞쪽 인덱스가 삭제되면 뒤에 있던 데이터들이 앞으로 이동되는 과정때문에 느린것이다.

profile
5 Seconds rule

0개의 댓글

관련 채용 정보