IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Java Discussion :

Sérialisation et performances


Sujet :

Langage Java

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    82
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 82
    Par défaut Sérialisation et performances
    Bonjour à tous,

    Je me suis documenté ces derniers jours sur le mécanisme de sérialisation. Il paraît incontestablement formidable sur le plan du service rendu au développeur. J'envisage donc de l'utiliser pour sauvegarder ma structure de données sur le disque. Mais je me pose encore quelques questions relatives aux pertes de performances de ce mécanisme par rapport à un mécanisme plus "manuel" et classique comme on pourrait le coder en C++ par exemple.

    Par performances, j'entends particulièrement temps d'exécution et encombrement du fichier sur le disque. J'ai trouvé une info sur le net précisant que sur un cas test, la sérialisation pouvait être environ 2 fois plus lente qu'un mécanisme classique mais je n'ai rien lu sur le rendement en terme de taille de fichier créé. J'imagine qu'il doit bien y avoir un certain prix à payer en contrepartie de la simplicité de codage...

    Je serais ravi de lire les appréciations de ceux d'entre vous qui ont eu l'occasion d'évaluer les performances de la sérialisation.

    Merci !

  2. #2
    Membre émérite
    Profil pro
    Inscrit en
    Février 2007
    Messages
    572
    Détails du profil
    Informations personnelles :
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations forums :
    Inscription : Février 2007
    Messages : 572
    Par défaut
    La serialisation prend effectivement en pratique plus de place

    Quand tu utilises la serialisation, par défaut, tu enregistres presque tous les attributs de ta classe, même ceux qui n'ont pas besoin d'être enregistrés. L'effort consiste à supprimer ce que tu ne veux pas enregistrer. Et si tu utilises une classe que tu n'as pas définie toi meme, tu vas peut être enregistrer des informations qui ne t'interesse pas.

    Quand tu fais un enregistrement manuel, l'effort consiste à choisir ce que tu veux enregistrer, et comment tu vas le faire. Tu vas donc chercher à ne prendre que le strict necessaire.

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    82
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 82
    Par défaut
    As-tu eu l'occasion de faire un comparatif chiffré entre les deux méthodes ?

    Si on fait abstraction des champs inutile d'une classe de base qu'on ne maîtrise pas, sais-tu ce que coûte réellement la sérialisation d'un champ par rapport à une bête sauvegarde à la manière de grand-maman ? J'imagine que des infos telles que le nom du champ doivent être sauvées mais y a-t-il autre chose ?

    Merci pour ton avis !

  4. #4
    Membre Expert
    Avatar de gifffftane
    Profil pro
    Inscrit en
    Février 2007
    Messages
    2 354
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire (Rhône Alpes)

    Informations forums :
    Inscription : Février 2007
    Messages : 2 354
    Par défaut
    Je pratique beaucoup la sérialisation, mais je ne suis jamais allé la comparer à d'autres méthodes, particulièrement celles de grand-maman.

    Je la trouve très pratique, à condition de faire un fichier = un objet. Ce qui impose une gestion de fichiers. Je pense que d'autres formes ne sont pas très pratiques, parce que de toutes façons le flux de relecture doit relire tout le fichier. La gestion de fichiers n'est pas une lourde charge, à condition de maitriser la classe File ce qui, on l'admettra, est à la portée du premier venu.

    Il FAUT placer le serialVersionUID, sinon c'est la panique assurée au bout de 2 jours.

    Question optimisation vitesse, un cache d'objet fait éventuellement l'affaire.

    Que veux-tu savoir d'autre ?

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    82
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 82
    Par défaut
    Je ne suis pas sûr de comprendre ce que tu entends par un fichier = un objet. Dans mon cas, mon appli contient un projet avec sa structure de donnée. L'ensemble devra se sauver sous la forme d'un fichier par projet. Donc pour un objet projet, il y aura un fichier, si c'est cela que tu voulais dire.

    Sinon, merci pour vos avis . Je pense me tourner vers la sérialisation qui me paraît vraiment séduisante. Et même si il faut claquer un peu plus d'espace disque, je mise sur le fait que ça reste raisonnable.

  6. #6
    Expert confirmé
    Avatar de le y@m's
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2005
    Messages
    2 636
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Février 2005
    Messages : 2 636
    Par défaut
    En ce qui concerne les attributs n'ayant pas besoin d'être sérialisés, le mot clé transient est là pour ça .
    Je ne répondrai à aucune question technique par MP.

    Pensez aux Tutoriels et aux FAQs avant de poster ;) (pour le java il y a aussi JavaSearch), n'oubliez pas non plus la fonction Rechercher.
    Enfin, quand une solution a été trouvée à votre problème
    pensez au tag :resolu:

    Cours Dvp : http://ydisanto.developpez.com
    Blog : http://yann-disanto.blogspot.com/
    Page perso : http://yann-disanto.fr

  7. #7
    Membre extrêmement actif Avatar de Mister Nono
    Homme Profil pro
    Ingénieur Mathématiques et Informatique
    Inscrit en
    Septembre 2002
    Messages
    2 254
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur Mathématiques et Informatique
    Secteur : Santé

    Informations forums :
    Inscription : Septembre 2002
    Messages : 2 254
    Par défaut
    Citation Envoyé par dabeuliou
    Mais je me pose encore quelques questions relatives aux pertes de performances de ce mécanisme par rapport à un mécanisme plus "manuel" et classique comme on pourrait le coder en C++ par exemple.
    C'est vraiment une question à se poser de nos jours.

    C'était peut-être vrai au début de Java, mais on est à la version 6.

    A+

  8. #8
    Membre chevronné Avatar de Scorpyosis
    Homme Profil pro
    Inscrit en
    Janvier 2004
    Messages
    365
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2004
    Messages : 365
    Par défaut java -version ;-)
    Le plus simple est encore de tester! On fait une boucle ou on enregistre des objets dans un fichier, et une autre ou on enregistre leur champ. Ensuite on recharge les fichiers dans le cas1 en ayant directement l'objet dans le cas2 en reconstruisant l'objet...

    Prenons une classe a sauvegarder:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     
    import java.io.Serializable;
     
    public class ObjetASerialise implements Serializable 
    {
    	private static final long serialVersionUID = 1L;
     
    	private String champ1;	
     
    	public ObjetASerialise(String s1)
    	{
    		this.champ1 = s1;		
    	}
     
    	public String getChamp1() {
    		return champ1;
    	}	
    }
    Et une petite classe de test:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
     
    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.FileReader;
    import java.io.IOException;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.io.PrintWriter;
    import java.util.Date;
     
     
    public class Test {
     
    	public static int nbBoucle = 500000;
    	public static String fileObjet = "FObjet.txt";
    	public static String fileAttribut = "FAttribut.txt";
     
    	public static long dateDebut = 0 ;
    	public static long dateFin = 0;
     
    	public static void objetSerialisation()
    	{
    		File f = new File(fileObjet);
    		ObjectOutputStream oos = null;
    		try {
    			oos = new ObjectOutputStream(new FileOutputStream(f));
    			for(int i = 0 ; i< nbBoucle; i++)
    			{	
    				ObjetASerialise obj = new ObjetASerialise(""+i);
    				oos.writeObject(obj);
    			}
    			oos.close();
    		} catch (FileNotFoundException e) {
    			e.printStackTrace();
    		} catch (IOException e) {
    			e.printStackTrace();
    		}		
     
    	}
     
     
    	public static void attributObjetSerialisation()
    	{
    		File f = new File(fileAttribut);
    		BufferedWriter bw ;		
    		try {			
    			bw = new BufferedWriter(new PrintWriter(f));
    			for(int i = 0 ; i< nbBoucle; i++)
    			{	
    				bw.write(""+i);				
    			}
    			bw.close();
    		} catch (FileNotFoundException e) {
    			e.printStackTrace();
    		} catch (IOException e) {
    			e.printStackTrace();
    		}	
     
    	}
     
    	public static void lireObjet()
    	{
    		File f = new File(fileObjet);
    		ObjectInputStream ois = null;
    		try {
    			ois = new ObjectInputStream(new FileInputStream(f));
    			for(int i = 0 ; i< nbBoucle; i++)
    			{					
    				ObjetASerialise objet = (ObjetASerialise)ois.readObject();
    				objet.getChamp1();
    			}
    			ois.close();
    		} catch (FileNotFoundException e) {
    			e.printStackTrace();
    		} catch (IOException e) {
    			e.printStackTrace();
    		} catch (ClassNotFoundException e) {
    			e.printStackTrace();
    		}		
    	}
     
    	public static void lireAttribut()
    	{
    		File f = new File(fileAttribut);
    		BufferedReader br ;		
    		try {			
    			br = new BufferedReader(new FileReader(f));
    			for(int i = 0 ; i< nbBoucle; i++)
    			{	
    				String s = br.readLine();
    				ObjetASerialise objet = new ObjetASerialise(s);
    				objet.getChamp1();
    			}
    			br.close();
    		} catch (FileNotFoundException e) {
    			e.printStackTrace();
    		} catch (IOException e) {
    			e.printStackTrace();
    		}			
    	}
     
    	public static void start()
    	{		
    		dateDebut = new Date().getTime();		
    	}
     
    	public static void finish()
    	{
    		dateFin = new Date().getTime();
    		System.out.println(">>>Tps execution : "+ (dateFin-dateDebut)+" ms");
    		dateDebut =0;
    		dateFin =0;
    	}
     
    	public static void main(String[] args) 
    	{
    		System.out.println("===Debut du test===");
     
    		start();
    		attributObjetSerialisation();
    		finish();
     
    		start();
    		objetSerialisation();
    		finish();
     
    		System.out.println("Taille du Fichier 1 = "+ new File(fileAttribut).length());
    		System.out.println("Taille du Fichier 2 = "+ new File(fileObjet).length());		
     
    		start();
    		lireAttribut();
    		finish();
     
    		start();
    		lireObjet();
    		finish();				
     
    		System.out.println("===Fin du test===");
    	}
    }
    Et le resultat donne :
    ===Debut du test===
    >>>Tps execution : 843 ms
    >>>Tps execution : 21094 ms
    Taille du Fichier 1 = 2888890
    Taille du Fichier 2 = 7388950
    >>>Tps execution : 3344 ms
    >>>Tps execution : 13781 ms
    ===Fin du test===
    Donc oui clairement la serialisation met plus de temps pour l'ecriture et la lecture et les fichiers générés sont plus gros. Mais bon c'est aussi plus facile a gérer alors....

    EDIT: fait avec la version 5 update 11 pour info

  9. #9
    Membre Expert
    Avatar de gifffftane
    Profil pro
    Inscrit en
    Février 2007
    Messages
    2 354
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire (Rhône Alpes)

    Informations forums :
    Inscription : Février 2007
    Messages : 2 354
    Par défaut
    Je signale qu'il existe aussi une autre forme de sérialisation en java, plutôt orientée vers les beans, avec le java.beans.XMLDecoder/Encoder. Ce mode de sérialisation est assez sympa, il oblige à réfléchir plus en terme de modèle qu'en terme d'objet, et il permet aux hackers fous d'intervenir dans la tuyauterie avec un bête éditeur de texte. Encore plus passionant.

  10. #10
    Membre émérite
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    548
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 548
    Par défaut
    Un inconvenient c'est que si tu utilises la serialisation pour du stockage de long terme, tu auras vite des problèmes lors des changements de version.
    C'est assez compliqué de garantir le fait que le fichier sauvegardé avec la vielle version puisse être ouvert avec la nouvelle.

  11. #11
    Membre Expert
    Avatar de gifffftane
    Profil pro
    Inscrit en
    Février 2007
    Messages
    2 354
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire (Rhône Alpes)

    Informations forums :
    Inscription : Février 2007
    Messages : 2 354
    Par défaut
    Heu... effectivement, garantir, c'est compliqué, mais en pratique, cela se passe très bien : il suffit 99 fois sur 100 d'avoir placé le serialVersionUID.

  12. #12
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    82
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 82
    Par défaut
    Merci à Scorpyosis d'avoir pris le temps de faire ces tests . C'est très intéressant.
    J'ai continué ma réflexion et je me suis rendu compte d'une chose toute bête : renommer une classe après avoir sérialisé un objet de cette classe empêche la désérialisation de fonctionner. C'est affreux . S'interdire de renommer certaines classes pendant la vie d'un logiciel est un inconvénient sévère à mon sens.

    Existe-t-il une parade à cela ? Il est bien évident que le serialVersionID n'est d'aucun secours ici puisque le mécanisme de désérialisation lève une ClassNotFoundException avant de s'intéresser à des problèmes de version.

    Et bien que cela ne résolve pas le problème, je suis curieux de savoir pourquoi c'est le nom de la classe qui est utilisé pour l'identifier plutôt qu'un identifiant sous forme d'UUID ou équivalent, ce qui me paraît bien plus stable.

  13. #13
    Membre Expert
    Avatar de gifffftane
    Profil pro
    Inscrit en
    Février 2007
    Messages
    2 354
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire (Rhône Alpes)

    Informations forums :
    Inscription : Février 2007
    Messages : 2 354
    Par défaut
    Il n'existe pas de système assurance tout risque contre les changements. Et heureusement, d'ailleurs, le concept est en lui même complètement idiot.

    Il me semble qu'il vaut mieux travailler avec des routines de transfert de l'ancienne à la nouvelle classe. Ainsi, tu peux gérer beaucoup plus facilement la mise à jour des systèmes.

    Pour mettre à jour un système, en général je modifie l'ancienne classe - et pas la nouvelle - de façon à générer, à partir de l'ancienne, la nouvelle. Ainsi si je trouve un objet sérialisé de l'ancienne version, alors je génère un objet de l'ancienne version (forcément), avec lequel je gènère un objet de la nouvelle. Et j'efface l'ancienne sérialisation, et je re-sérialize avec la nouvelle.

    Tout ceci impose de conserver, pendant une ou deux versions, la classe de l'ancienne version dans le jar ; elle est simplement marquée deprecated, et je fais un système de warning avec les logs pour mieux indiquer qu'il ne faut plus l'utiliser.

    Il vaut mieux faire ce code dans l'ancienne, car c'est souvent du code un peu crade (ça évite de poluer, dès le départ, la nouvelle), et, en plus, lorsque le système a été remis à jour (à la version n+2 ou 3), on peut supprimer sans crainte la classe de l'ancienne. Si tu fais l'adaptation dans la nouvelle, tu ne peux pas supprimer aussi facilement l'ancienne, puisque tu as une référence dans la nouvelle. On peut faire du nouveau avec l'ancien, on ne peut pas faire de l'ancien avec le nouveau.

Discussions similaires

  1. [maintenance][performance] Que faire comme maintenance ?
    Par woodwai dans le forum PostgreSQL
    Réponses: 5
    Dernier message: 06/11/2003, 16h39
  2. Performance xml
    Par MicKCanE dans le forum XML/XSL et SOAP
    Réponses: 2
    Dernier message: 07/07/2003, 07h41
  3. [ POSTGRESQL ] Problème de performance
    Par Djouls64 dans le forum PostgreSQL
    Réponses: 6
    Dernier message: 26/05/2003, 17h18
  4. [JDBC][connexion persistante] performances avec JDBC
    Par nawac dans le forum Connexion aux bases de données
    Réponses: 6
    Dernier message: 06/05/2003, 11h37
  5. performance entre 3DS, ase, asc ...
    Par amaury pouly dans le forum OpenGL
    Réponses: 3
    Dernier message: 24/03/2003, 12h41

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo