Guide de FastUtil

1. Introduction

Dans ce didacticiel, nous examinerons la bibliothèque FastUtil .

Tout d'abord, nous allons coder quelques exemples de ses collections spécifiques au type.

Ensuite, nous analyserons les performances qui donnent à FastUtil son nom.

Enfin, jetons un coup d'œil aux utilitaires BigArray de FastUtil .

2. Caractéristiques

La bibliothèque Java FastUtil cherche à étendre le Java Collections Framework. Il fournit des cartes, des ensembles, des listes et des files d' attente spécifiques au type avec une empreinte mémoire réduite et un accès et une insertion rapides. FastUtil fournit également un ensemble d' utilitaires pour travailler avec et manipuler de grands tableaux, ensembles et listes (64 bits).

La bibliothèque comprend également une multitude de classes d'entrée / sortie pratiques pour les fichiers binaires et texte.

Sa dernière version, FastUtil 8, a également publié une foule de fonctions spécifiques au type, étendant les interfaces fonctionnelles du JDK .

2.1. La vitesse

Dans de nombreux cas, les implémentations FastUtil sont les plus rapides disponibles. Les auteurs ont même fourni leur propre rapport de référence approfondi, en le comparant à des bibliothèques similaires, notamment HPPC et Trove.

Dans ce tutoriel, nous chercherons à définir nos propres benchmarks à l'aide du Java Microbench Harness (JMH).

3. Dépendance de taille complète

En plus de la dépendance JUnit habituelle , nous utiliserons les dépendances FastUtils et JMH dans ce didacticiel.

Nous aurons besoin des dépendances suivantes dans notre fichier pom.xml :

 it.unimi.dsi fastutil 8.2.2   org.openjdk.jmh jmh-core 1.19 test   org.openjdk.jmh jmh-generator-annprocess 1.19 test 

Ou pour les utilisateurs de 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. Fichier Jar personnalisé

En raison du manque de génériques, FastUtils génère un grand nombre de classes spécifiques au type. Et malheureusement, cela conduit à un énorme fichier jar.

Cependant, heureusement pour nous, FastUtils inclut un script find-deps.sh qui permet la génération de jars plus petits et plus ciblés comprenant uniquement les classes que nous voulons utiliser dans notre application.

4. Collections spécifiques à un type

Avant de commencer, jetons un coup d'œil rapide au processus simple d'instanciation d'une collection spécifique à un type. Prenons un HashMap qui stocke les clés et les valeurs en utilisant des doubles.

Pour cela, FastUtils fournit une interface Double2DoubleMap et une implémentation Double2DoubleOpenHashMap :

Double2DoubleMap d2dMap = new Double2DoubleOpenHashMap();

Maintenant que nous avons instancié notre classe, nous pouvons simplement remplir les données comme nous le ferions avec n'importe quelle carte de l'API Java Collections:

d2dMap.put(2.0, 5.5); d2dMap.put(3.0, 6.6);

Enfin, nous pouvons vérifier que les données ont été correctement ajoutées:

assertEquals(5.5, d2dMap.get(2.0));

4.1. Performance

FastUtils se concentre sur ses implémentations performantes. Dans cette section, nous utiliserons le JMH pour vérifier ce fait. Comparons l'implémentation de Java Collections HashSet à IntOpenHashSet de FastUtil .

Voyons d' abord comment implémenter 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; }

Above, we've simply declared the IntOpenHashSet implementation of the IntSet interface. We've also declared the initial size setSize with the @Param annotation.

Put simply, these numbers are fed into JMH to produce a series of benchmark tests with different set sizes.

Next, let's do the same thing using the Java Collections implementation:

@Benchmark public Set givenCollectionsHashSetWithInitialSizeSet_whenPopulated_checkTimeTaken() { Set intSet = new HashSet(setSize); for(int i = 0; i < setSize; i++) { intSet.add(i); } return intSet; }

Finally, let's run the benchmark and compare the two implementations:

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

These results make it clear theFastUtils implementation is much more performant than the Java Collections alternative.

5. Big Collections

Another important feature of FastUtils is the ability to use 64-bit arrays. Arrays in Java, by default, are limited to 32 bits.

To get started, let's take a look at the BigArrays class for Integer types. IntBigArrays provides static methods for working with 2-dimensional Integer arrays. By using these provided methods, we can essentially wrap our array into a more user-friendly 1-dimensional array.

Let's take a look at how this works.

First, we'll start by initializing a 1-dimensional array, and converting it into a 2-dimensional array using IntBigArray's wrap method:

int[] oneDArray = new int[] { 2, 1, 5, 2, 1, 7 }; int[][] twoDArray = IntBigArrays.wrap(oneDArray.clone());

Nous devons nous assurer d'utiliser la méthode de clonage pour garantir une copie complète du tableau.

Maintenant, comme nous le ferions avec une liste ou une carte , nous pouvons accéder aux éléments en utilisant la méthode get :

int firstIndex = IntBigArrays.get(twoDArray, 0); int lastIndex = IntBigArrays.get(twoDArray, IntBigArrays.length(twoDArray)-1);

Enfin, ajoutons quelques vérifications pour nous assurer que notre IntBigArray renvoie les valeurs correctes:

assertEquals(2, firstIndex); assertEquals(7, lastIndex);

6. Conclusion

Dans cet article, nous avons plongé dans les fonctionnalités de base de FastUtils .

Nous avons examiné certaines des collections spécifiques au type proposées par FastUtil , avant de jouer avec certaines BigCollections .

Comme toujours, le code peut être trouvé sur GitHub