1. 소개
이 사용방법(예제)에서는 FastUtil 라이브러리를 살펴보겠습니다.
먼저 유형별 컬렉션 의 몇 가지 예를 코딩합니다 .
그런 다음 FastUtil 에 이름 을 부여하는 성능을 분석합니다.
마지막으로 FastUtil 의 BigArray 유틸리티를 살펴보겠습니다.
2. 특징
FastUtil Java 라이브러리는 Java Collections Framework를 확장하려고 합니다 . 더 작은 메모리 공간과 빠른 액세스 및 삽입으로 유형별 맵, 세트, List 및 Queue 을 제공 합니다. FastUtil 은 대형(64비트) 어레이, 세트 및 List을 사용하고 조작하기 위한 유틸리티 세트도 제공 합니다.
라이브러리에는 바이너리 및 텍스트 파일을 위한 다수의 실용적인 입/출력 클래스 도 포함되어 있습니다.
최신 릴리스인 FastUtil 8 은 JDK의 기능 인터페이스 를 확장하는 다양한 유형별 기능 도 릴리스했습니다 .
2.1. 속도
대부분의 경우 FastUtil 구현이 가장 빠릅니다. 작성자는 HPPC 및 Trove 와 같은 유사한 라이브러리와 비교하여 자체 심층 벤치마크 보고서 를 제공하기도 했습니다.
이 사용방법(예제)에서는 JMH(Java Microbench Harness) 를 사용하여 고유한 벤치마크를 정의하는 방법을 살펴보겠습니다 .
3. 완전한 크기의 의존성
이 사용방법(예제) 에서는 일반적인 JUnit 의존성 외에 FastUtils 및 JMH 의존성 을 사용할 것입니다.
pom.xml 파일 에 다음 의존성이 필요 합니다.
<dependency>
<groupId>it.unimi.dsi</groupId>
<artifactId>fastutil</artifactId>
<version>8.2.2</version>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-core</artifactId>
<version>1.35</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-generator-annprocess</artifactId>
<version>1.35</version>
<scope>test</scope>
</dependency>
또는 Gradle 사용자의 경우:
testCompile group: 'org.openjdk.jmh', name: 'jmh-core', version: '1.19'
testCompile group: 'org.openjdk.jmh', name: 'jmh-generator-annprocess', version: '1.19'
compile group: 'it.unimi.dsi', name: 'fastutil', version: '8.2.2'
3.1. Custom형 Jar 파일
제네릭이 없기 때문에 FastUtils 는 많은 수의 유형별 클래스를 생성합니다. 불행히도 이것은 거대한 jar 파일로 이어집니다.
그러나 다행 스럽게도 FastUtils 에는 응용 프로그램에서 사용하려는 클래스로만 구성된 더 작고 집중된 jar를 생성할 수 있는 find-deps.sh 스크립트가 포함되어 있습니다.
4. 유형별 컬렉션
시작하기 전에 유형별 컬렉션을 인스턴스화하는 간단한 프로세스를 간단히 살펴보겠습니다 . double 을 사용하여 키와 값을 저장 하는 HashMap 을 선택해 보겠습니다 .
이를 위해 FastUtils 는 Double2DoubleMap 인터페이스와 Double2DoubleOpenHashMap 구현을 제공합니다.
Double2DoubleMap d2dMap = new Double2DoubleOpenHashMap();
이제 클래스를 인스턴스화했으므로 Java Collections API에서 Map 으로 데이터를 채울 수 있습니다 .
d2dMap.put(2.0, 5.5);
d2dMap.put(3.0, 6.6);
마지막으로 데이터가 올바르게 추가되었는지 확인할 수 있습니다.
assertEquals(5.5, d2dMap.get(2.0));
4.1. 성능
FastUtils 는 성능 구현에 중점을 둡니다. 이 섹션에서는 JMH를 사용하여 해당 사실을 확인합니다. Java Collections HashSet<Integer> 구현을 FastUtil의 IntOpenHashSet 과 비교해 봅시다 .
먼저 IntOpenHashSet을 구현하는 방법을 살펴보겠습니다.
@Param({"100", "1000", "10000", "100000"})
public int setSize;
@Benchmark
public IntSet givenFastUtilsIntSetWithInitialSizeSet_whenPopulated_checkTimeTaken() {
IntSet intSet = new IntOpenHashSet(setSize);
for(int i = 0; i < setSize; i++) {
intSet.add(i);
}
return intSet;
}
위에서 IntSet 인터페이스 의 IntOpenHashSet 구현을 간단히 선언했습니다 . 또한 @Param 어노테이션 을 사용하여 초기 크기 setSize 를 선언했습니다.
간단히 말해서, 이러한 수치는 JMH에 입력되어 다양한 세트 크기로 일련의 벤치마크 테스트를 생성합니다.
다음으로 Java Collections 구현을 사용하여 동일한 작업을 수행해 보겠습니다.
@Benchmark
public Set<Integer> givenCollectionsHashSetWithInitialSizeSet_whenPopulated_checkTimeTaken() {
Set<Integer> intSet = new HashSet<>(setSize);
for(int i = 0; i < setSize; i++) {
intSet.add(i);
}
return intSet;
}
마지막으로 벤치마크를 실행하고 두 가지 구현을 비교해 보겠습니다.
Benchmark (setSize) Mode Cnt Score Units
givenCollectionsHashSetWithInitialSizeSet... 100 avgt 2 1.460 us/op
givenCollectionsHashSetWithInitialSizeSet... 1000 avgt 2 12.740 us/op
givenCollectionsHashSetWithInitialSizeSet... 10000 avgt 2 109.803 us/op
givenCollectionsHashSetWithInitialSizeSet... 100000 avgt 2 1870.696 us/op
givenFastUtilsIntSetWithInitialSizeSet... 100 avgt 2 0.369 us/op
givenFastUtilsIntSetWithInitialSizeSet... 1000 avgt 2 2.351 us/op
givenFastUtilsIntSetWithInitialSizeSet... 10000 avgt 2 37.789 us/op
givenFastUtilsIntSetWithInitialSizeSet... 100000 avgt 2 896.467 us/op
이러한 결과는 FastUtils 구현이 Java Collections 대안보다 훨씬 더 성능이 좋다는 것을 분명히 합니다.
5. 빅 컬렉션
Fa stUtils 의 또 다른 중요한 기능은 64비트 어레이를 사용할 수 있다는 것입니다. Java의 배열은 기본적으로 32비트로 제한됩니다.
시작하려면 Integer 유형 에 대한 BigArrays 클래스를 살펴보겠습니다 . IntBigArrays 는 2차원 정수 배열 작업을 위한 정적 메서드를 제공합니다. 이러한 제공된 방법을 사용하여 기본적으로 배열을 보다 사용자 친화적인 1차원 배열로 래핑할 수 있습니다.
이것이 어떻게 작동하는지 살펴보겠습니다.
먼저 1차원 배열을 초기화하고 IntBigArray의 wrap 메서드를 사용하여 2차원 배열로 변환합니다.
int[] oneDArray = new int[] { 2, 1, 5, 2, 1, 7 };
int[][] twoDArray = IntBigArrays.wrap(oneDArray.clone());
복제 방법을 사용 하여 어레이의 전체 복사본을 확보해야 합니다 .
이제 List 또는 Map 과 마찬가지로 get 메서드 를 사용하여 요소에 액세스할 수 있습니다 .
int firstIndex = IntBigArrays.get(twoDArray, 0);
int lastIndex = IntBigArrays.get(twoDArray, IntBigArrays.length(twoDArray)-1);
마지막으로 IntBigArray 가 올바른 값을 반환하는지 확인하는 몇 가지 검사를 추가해 보겠습니다.
assertEquals(2, firstIndex);
assertEquals(7, lastIndex);
6. 결론
이 기사에서는 FastUtils 핵심 기능 에 대해 자세히 살펴보았습니다.
일부 BigCollections 를 가지고 놀기 전에 FastUtil 이 제공하는 유형별 컬렉션 중 일부 를 살펴 보았습니다 .
항상 그렇듯이 코드는 GitHub 에서 찾을 수 있습니다.