Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
No results found
Show changes
Showing
with 491 additions and 19 deletions
package p4a;
public class MainLinkedListPersoAddFin {
public static void main(String[] args) {
LinkedListPerso<Integer> linkedList = new LinkedListPerso<Integer>();
int nbOperation = Integer.parseInt(args[0]);
for (int i = 0; i < nbOperation; i++) {
linkedList.ajout(0, i);
}
}
}
package p4a;
import java.util.Random;
public class MainLinkedListPersoGet {
public static void main(String[] args) {
Random rnd = new Random();
LinkedListPerso<Integer> linkedList = new LinkedListPerso<Integer>();
int nbOperation = Integer.parseInt(args[0]);
for (int i = 0; i < nbOperation; i++) {
linkedList.ajout(0, i);
}
for (int i = 0; i < nbOperation; i++) {
linkedList.acces(rnd.nextInt(nbOperation));
}
}
}
package p4a;
public class MainLinkedListPersoRemoveDecrementation {
public static void main(String[] args) {
LinkedListPerso<Integer> linkedList = new LinkedListPerso<Integer>();
int nbOperation = Integer.parseInt(args[0]);
for (int i = 0; i < nbOperation; i++) {
linkedList.ajout(0, i);
}
for (int i = nbOperation-1; i >= 0; i--) {
linkedList.suppression(i);
}
}
}
package p4a;
public class MainLinkedListPersoRemoveFirstValue {
public static void main(String[] args) {
LinkedListPerso<Integer> linkedList = new LinkedListPerso<Integer>();
int nbOperation = Integer.parseInt(args[0]);
for (int i = 0; i < nbOperation; i++) {
linkedList.ajout(0, i);
}
for (int i = 0; i < nbOperation; i++) {
linkedList.suppression(0);
}
}
}
package p4a;
public class MainLinkedListStdAddCentre {
public static void main(String[] args) {
LinkedListStd<Integer> linkedList = new LinkedListStd<Integer>();
int nbOperation = Integer.parseInt(args[0]);
for (int i = 0; i < nbOperation; i++) {
linkedList.ajout(0, i);
}
for (int i = 0; i < nbOperation; i++) {
linkedList.acces((nbOperation/2)%2==0?nbOperation/2:(int)(nbOperation/2-0.5));
}
}
}
package p4a;
public class MainLinkedListStdAddDebut {
public static void main(String[] args) {
LinkedListStd<Integer> linkedList = new LinkedListStd<Integer>();
int nbOperation = Integer.parseInt(args[0]);
for (int i = 0; i < nbOperation; i++) {
linkedList.ajout(0, 0);
}
}
}
package p4a;
public class MainLinkedListStdAddFin {
public static void main(String[] args) {
LinkedListStd<Integer> linkedList = new LinkedListStd<Integer>();
int nbOperation = Integer.parseInt(args[0]);
for (int i = 0; i < nbOperation; i++) {
linkedList.ajout(0, i);
}
}
}
package p4a;
import java.util.Random;
public class MainLinkedListStdGet {
public static void main(String[] args) {
Random rnd = new Random();
LinkedListStd<Integer> linkedList = new LinkedListStd<Integer>();
int nbOperation = Integer.parseInt(args[0]);
for (int i = 0; i < nbOperation; i++) {
linkedList.ajout(0, i);
}
for (int i = 0; i < nbOperation; i++) {
linkedList.acces(rnd.nextInt(nbOperation));
}
}
}
package p4a;
public class MainLinkedListStdRemoveCentre {
public static void main(String[] args) {
LinkedListStd<Integer> linkedList = new LinkedListStd<Integer>();
int nbOperation = Integer.parseInt(args[0]);
for (int i = 0; i < nbOperation; i++) {
linkedList.ajout(0, i);
}
for (int i = 0; i < nbOperation; i++) {
linkedList.suppression((nbOperation-i)%2==0?(nbOperation-i)/2:(int)((nbOperation-i)/2-0.5));
}
}
}
package p4a;
public class MainLinkedListStdRemoveDecrementation {
public static void main(String[] args) {
LinkedListStd<Integer> linkedList = new LinkedListStd<Integer>();
int nbOperation = Integer.parseInt(args[0]);
for (int i = 0; i < nbOperation; i++) {
linkedList.ajout(0, i);
}
for (int i = nbOperation-1; i >= 0; i--) {
linkedList.suppression(i);
}
}
}
package p4a;
public class MainLinkedListStdRemoveFirstValue {
public static void main(String[] args) {
LinkedListStd<Integer> linkedList = new LinkedListStd<Integer>();
int nbOperation = Integer.parseInt(args[0]);
for (int i = 0; i < nbOperation; i++) {
linkedList.ajout(0, i);
}
for (int i = 0; i < nbOperation; i++) {
linkedList.suppression(0);
}
}
}
package p4a;
public class MainTableauPersoAdd {
public static void main(String[] args) {
int nbOperation = Integer.parseInt(args[0]);
TableauPerso tab = new TableauPerso(nbOperation);
for (int i = 0; i < nbOperation; i++) {
tab.ajout(0, i);
}
}
}
package p4a;
import java.util.Random;
public class MainTableauPersoGet {
public static void main(String[] args) {
Random rnd = new Random();
int nbOperation = Integer.parseInt(args[0]);
TableauPerso tab = new TableauPerso(nbOperation);
for (int i = 0; i < nbOperation; i++) {
tab.ajout(0, i);
}
for (int i = 0; i < nbOperation; i++) {
tab.acces(rnd.nextInt(nbOperation));
}
}
}
package p4a;
public class MainTableauStdAdd {
public static void main(String[] args) {
int nbOperation = Integer.parseInt(args[0]);
TableauStd tab = new TableauStd(nbOperation);
for (int i = 0; i < nbOperation; i++) {
tab.ajout(0, i);
}
}
}
package p4a;
import java.util.Random;
public class MainTableauStdGet {
public static void main(String[] args) {
Random rnd = new Random();
int nbOperation = Integer.parseInt(args[0]);
TableauStd tab = new TableauStd(nbOperation);
for (int i = 0; i < nbOperation; i++) {
tab.ajout(0, i);
}
for (int i = 0; i < nbOperation; i++) {
tab.acces(rnd.nextInt(nbOperation));
}
}
}
package p4a;
public interface Structure {
public void ajout(Object element, int position);
public void suppression(int position);
public Object acces(int position);
}
package p4a;
public class TableauPerso implements Structure{
private Object[] tableau;
private int nbElements;
public TableauPerso(int taille) {
if (taille < 0) {
throw new IllegalArgumentException("TableauPerso : taille negative " + taille);
}
this.tableau = new Object[taille];
nbElements = 0;
}
@Override
public void ajout(Object element, int position) {
if (position < 0 || position > nbElements) {
throw new IndexOutOfBoundsException("ajout : mauvais index " + position);
}
if (nbElements >= tableau.length) {
throw new IllegalStateException("ajout : tableau plein");
}
for (int i = nbElements; i > position; i--) {
tableau[i] = tableau[i - 1];
}
tableau[position] = element;
nbElements++;
}
@Override
public void suppression(int position) {
if (position < 0 || position >= nbElements) {
throw new IndexOutOfBoundsException("suppression : position incorrecte " + position);
}
for (int i = position + 1; i < nbElements; i++) {
tableau[i - 1] = tableau[i];
}
nbElements--;
}
@Override
public Object acces(int position) {
if (position > tableau.length || position < 0) {
throw new IllegalArgumentException("acces : position incorecte");
}
return tableau[position];
}
}
package p4a;
public class TableauStd implements Structure {
private Object[] tableau;
public TableauStd(int taille) {
if (taille < 0) {
throw new IllegalArgumentException("TableauStd : taille negative " + taille);
}
this.tableau = new Object[taille];
}
@Override
public void ajout(Object element, int position) {
if (position > tableau.length) {
throw new UnsupportedOperationException("ajout : operation non supportee (taille depassee)");
}
else tableau[position] = element;
}
@Override
public void suppression(int position) {
throw new UnsupportedOperationException("suppression : operation non supportee");
}
@Override
public Object acces(int position) {
if (position > tableau.length || position < 0) {
throw new IllegalArgumentException("acces : position incorecte");
}
return tableau[position];
}
}
......@@ -4,58 +4,157 @@
## Problème
Description du Problème.
Description du Problème :
Description de tous les paramètres exploratoires du problème
Nous allons comparer les différences de performances sur 3 opérations communes à différentes structures de données (tableaux, LinkedList et ArrayList).
Nous allons également réimplementer ces opérations nous même et à nouveau comparer les différences de performance avec les implémentations standard (proposées par java).
Nous avons choisi d'utiliser le language objet java.
Opérations :
- Ajout d'un élement à une certaine position (n'exite pas pour les tableaux standards, add() pour les LinkedList / ArrayList)
- Suppression d'un élement à une certaine position(n'existe pas pour les tableaux standards, remove() pour les LinkedList / ArrayList)
- Accès d'un élement à une certaine position(tab[position] pour les tableaux, get() pour les LinkedList / ArrayList)
## Dispositif expérimental
### Organisation objet
Description de l'organisation des classes et interfaces, ou diagramme de classes.
Voila notre diagramme de classe explicitant l'organisation objet de l'application.
![](UML/diagramme.svg)
Toutes les structures de données vont implémenter une Interface *"Struture"* que nous allons créer et qui contiendra les opérations choisies.
Dans le package **Standard**, nous appelerons juste les bonnes méthodes déja présentes dans les libraires standards et dans
le package **Perso** nous réimplementerons par nous même ces opérations.
### Application
[code source de l'application](chemin)
```
Description de l'application et des arguments
```
L'application est divisée en 2 parties : les scripts shells qui appellent nos differentes classes de Main compilées en java.
Il existe un script shell pour chaque graphique et celui-ci appelle les classes Main choisies avec la commande "/usr/bin/time -f "%U,%M"
[code source des scripts shell](https://git.unistra.fr/jdubocage/P4a/-/tree/master/Scripts_Shell)
[code source des fichiers Java](https://git.unistra.fr/jdubocage/P4a/-/tree/master/P4A/src/p4a)
### Environnement de test
Description de la plateforme de test
Tout les tests ont été réalisés sur le serveur troglo.iutrs.unistra.fr
Description de la plateforme de test (extrait de /proc/cpuinfo)
```
Extrait pertinent de /proc/cpuinfo
processor : 1
vendor_id : GenuineIntel
cpu family : 15
model : 6
model name : Common KVM processor
cpu MHz : 2095.078
cache size : 16384 KB
siblings : 2
cpu cores : 2
clflush size : 64
cache_alignment : 128
address sizes : 40 bits physical, 48 bits virtual
```
### Description de la démarche systématique
Description de la démarche systématique et de l'espace d'exploration pour chaque paramètres.
Voici la démarche que nous avons suivi pour génerer des données puis produire des graphiques :
```
Suite des commandes, ou script, à exécuter pour produire les données.
1. Compiler les fichiers source dans le dossier P4A\src\p4a avec la commande javac ./*.java
2. Choisir le script shell de son choix et le copier dans le dossier P4A\src
3. Executer ce script shell pour génerer puis enregistrer les données avec la commande ./nomScript.sh > perf.csv
4. Executer la commande R pour pouvoir générer les graphiques avec ces données
5. Charger la librairie ggplot2 (commande : library(ggplot2)) puis charger les données : perf <- read.csv("perf.csv")
6. Génerer le graphique avec la commande ggplot(perf, arguments) puis exportation avec ggsave("nomGraphique.png")
```
Chaque script shell réalise le test sur les différentes structures de données 3 fois (parametrable en changeant la valeur de la variable TESTS).
Le nombre de fois que l'opération testée est executée est également parametrable via la variable NBOPERATIONS.
Cette variable est une séquence de plusieurs nombre permettant d'obtenir plusieurs points sur les graphiques.
## Résultats préalables
### Temps d'exécution
### Consommation CPU
### Ajout de Valeur
| | Tete de liste | Queue de liste |
| ----------------------------------| -------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| | ![plot](./graphiques/CPU_Linked_Array_List_Ajout_Debut_Liste.png) | ![plot](./graphiques/CPU_LinkedList_ArrayList_Ajout_Fin.png) |
### Suppression de Valeur
| | Tete de liste | Queue de liste |
| ----------------------------------| -------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| | ![plot](./graphiques/CPU_LinkedList_ArrayList_Remove_Debut.png) | ![plot](./graphiques/CPU_LinkedList_ArrayList_Remove_Fin.png) |
### Assignation de valeur (tableau)
![plot](prealable.png)
<img src="./graphiques/CPU_Tab_Assign.png" width="500"/>
### Accès de Valeur aleatoire
<img src="./graphiques/CPU_LinkedList_ArrayList_Tab_Get_Random.png" width="500"/>
### Consommation mémoire
![plot](prealable-mem.png)
### Ajout de Valeur
| | Tete de liste | Queue de liste |
| ----------------------------------| -------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| | ![plot](./graphiques/Mem_Linked_Array_List_Ajout_Debut_Liste.png) | ![plot](./graphiques/Mem_LinkedList_ArrayList_Ajout_Fin.png) |
### Suppression de Valeur
| | Tete de liste | Queue de liste |
| ----------------------------------| -------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| | ![plot](./graphiques/Mem_LinkedList_ArrayList_Remove_Debut.png) | ![plot](./graphiques/Mem_LinkedList_ArrayList_Remove_Fin.png) |
### Assignation de valeur (tableau)
<img src="./graphiques/Mem_Tab_Assign.png" width="500"/>
### Accès de Valeur aleatoire
<img src="./graphiques/Mem_LinkedList_ArrayList_Tab_Get_Random.png" width="500"/>
### Analyse des résultats préalables
La mémoire se comporte exactement pareil sur les 4 versions.
Les temps d'exécutions dépendent essentiellement de l'affichage des valeurs du tableau.
La version 2 de recherche semble un peu plus rapide.
On peut déja faire plusieurs remarques en observant les graphiques :
Pour l'ajout / suppression de valeurs (non supporté par les tableaux standards en java) :
- Les LinkedList sont bien plus efficaces en consommation CPU que les ArrayList en debut de liste.
- La différence en consommation CPU entre les deux structures est minime pour ces opérations en queue de liste.
- Les ArrayList sont légèrement moins couteuses en mémoire que les LinkedLists que soit en tete ou queue de liste.
L'assignation de valeur pour un tableau est très efficace en consommation CPU et proche des ArrayList en consommation Mémoire.
Pour l'accès de valeur aléatoire :
- Les ArrayLists et Tableaux sont très efficaces et identiques en consommation CPU.
- Les LinkedList sont beaucoup moins efficace que les deux autres structures en consommation CPU.
- En consommation mémoire, les Tableaux et ArrayLists sont proches et les LinkedList sont légerement plus couteuses.
### Discussion des résultats préalables
Explications précises et succinctes sur ce que les limites des résultats
préalables et ce qu'ils ne permettent pas de vérifier.
Ces différences sont logiques et correspondent à leur implémentation :
Dans une LinkedList, chaque élément est stocké en mémoire avec l'adresse du suivant et du précédent.
Dans une ArrayList, les éléments sont stockés en mémoire de manière à ce que leur position soit calculée par l'algorithme.
- Pour ajouter ou supprimer un élement en tête d'une LinkedList il suffit de modifier l'élément qui était auparavant le premier pour lui ajouter l'adresse du nouvel élément alors que dans une LinkedList tous les éléments suivants doivent être décalés, ce qui explique la grande différence de consommation CPU observée sur ces opérations.
- Pour l'accès de valeur dans une LinkedList l'algorithme part du début ou de la fin de la liste selon la position et la parcours jusqu'à tomber sur la position désirée, ce qui prends plus de temps que l'ArrayList dont la postion des élements est connue et dont il est donc très peu couteux d'accéder à n'importe quel élément. Cela explique le comportement similaire entre les Tableaux et les ArrayList ainsi que le cout CPU plus élevé pour les LinkedList.
- La consommation légerement supérieure en mémoire pour les LinkedList s'explique par le stockage en mémoire des pointeurs sur les élements précedants et suivants.
## Etude approfondie
......
NbOperations,Version,CPU,Mem
100000,ArrayListStd,0.93,49744
100000,ArrayListStd,0.92,51900
100000,ArrayListStd,0.94,54076
100000,LinkedListStd,0.10,57368
100000,LinkedListStd,0.09,53968
100000,LinkedListStd,0.10,58016
125000,ArrayListStd,1.50,56932
125000,ArrayListStd,1.49,49920
125000,ArrayListStd,1.48,54748
125000,LinkedListStd,0.10,57980
125000,LinkedListStd,0.11,51984
125000,LinkedListStd,0.09,56848
150000,ArrayListStd,2.18,53000
150000,ArrayListStd,2.19,52208
150000,ArrayListStd,2.12,54892
150000,LinkedListStd,0.11,57384
150000,LinkedListStd,0.10,56276
150000,LinkedListStd,0.09,56932
175000,ArrayListStd,2.90,51824
175000,ArrayListStd,2.87,50036
175000,ArrayListStd,2.91,57148
175000,LinkedListStd,0.10,58256
175000,LinkedListStd,0.09,56192
175000,LinkedListStd,0.11,55976
200000,ArrayListStd,3.77,54168
200000,ArrayListStd,3.81,53232
200000,ArrayListStd,3.79,49800
200000,LinkedListStd,0.10,56552
200000,LinkedListStd,0.09,54564
200000,LinkedListStd,0.10,56368
225000,ArrayListStd,4.79,56976
225000,ArrayListStd,4.81,53152
225000,ArrayListStd,4.79,55096
225000,LinkedListStd,0.10,54560
225000,LinkedListStd,0.10,56372
225000,LinkedListStd,0.10,56580
250000,ArrayListStd,5.89,52100
250000,ArrayListStd,5.97,53948
250000,ArrayListStd,5.96,51932
250000,LinkedListStd,0.09,58324
250000,LinkedListStd,0.10,63632
250000,LinkedListStd,0.11,58200
275000,ArrayListStd,7.26,57844
275000,ArrayListStd,7.18,59240
275000,ArrayListStd,7.17,52188
275000,LinkedListStd,0.10,58096
275000,LinkedListStd,0.09,61856
275000,LinkedListStd,0.10,61336
300000,ArrayListStd,8.54,54092
300000,ArrayListStd,8.57,53752
300000,ArrayListStd,8.55,53884
300000,LinkedListStd,0.11,58108
300000,LinkedListStd,0.11,58852
300000,LinkedListStd,0.09,62012