These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 4 posts ] 
Author Message
 Post subject: Utilisation de la méthode Evict()
PostPosted: Wed Jul 25, 2007 12:47 pm 
Newbie

Joined: Wed May 23, 2007 4:09 am
Posts: 16
J'utilise nHibernate 1.2 et j'ai le problème suivant:
Dans une boucle (disons 100 itérations):

1) si je fais juste une requête (session.CreateQuery(), c'est rapide
2) si je fais juste un ajout (session.Save()), c'est rapide

mais si dans la boucle je fais les 2, nHibernate est très très lent.

C'est vrai avec n'importe quelle base de donnée, mais cela n'arrive pas avec d'autres ORM ni si je fais du code ADO.NET natif.

Il semble qu'utiliser la commande session.Evict() règle le probleme.

Quelqu'un a-t-il une explication ou des conseils à proposer?
Merci d'avance.


Voici un exemple:
Code:
for(int i=0; i<1000; i++)
{
    session.CreateQuery("from Test where name=?")
        .SetString(0, "robert")
        .UniqueResult();

    MyObj obj = new MyObj();
    session.SaveOrUpdate(obj);

    // Ceci rend l'execution rapide, mais pourquoi?
    // Et comment s'en passer?
    session.Evict(obj);
}


Top
 Profile  
 
 Post subject: Pb de cache de session peut-être
PostPosted: Thu Jul 26, 2007 4:12 am 
Newbie

Joined: Wed Jul 25, 2007 8:49 am
Posts: 4
Bonjour,

Je ne me suis servi que d'Hibernate et pas de NHibernate.. Pas de connaissances de .NET. Je te réponds vis à vis de ce que j'ai eu l'occasion d'expérimenter en Java, le parallèle a de bonnes chances d'être vrai.

Ceci pourrait ressembler à un problème de mémoire.
En effet, hibernate a un mécanisme de cache de session : chaque objet récupéré ou sauvé est gardé en mémoire. De plus, tu peux généralement utiliser un pool de connexions qui gèrent donc tes connexions mais aussi les "PreparedStatements" JDBC. Chaque Query passe par ces PreparedStatements. Ce mécanisme de cache augmente les performances s'il est bien géré.

D'expérience, les itérations avec Hibernate sont très dangereuses si mal gérées -> pb de surcharge mémoire, le garbage collector passe de plus en plus souvent -> les temps de traitements augmentent de manière hallucinante jusqu'à plantage

Dans ton cas, j'initialiserai une et une seule fois ma query hors du for. Ensuite, dans la boucle je ne gérerai que le setString (une query est utilisable plusieurs fois). Ca permettra d'être sur que ton statement n'est gardé qu'une seule fois en cache.
Ensuite, il est généralement bon de purger la session via un session.clear au bout d'un nombre n d' itérations : ca t'évitera de la surcharger. Si tu veux que certains objets soient conservés plus longtemps tout en en purgeant d'autres, tu peux utiliser le cache de second niveau.

Ton Session.evict correspond un peu au session.clear : il retire un objet de la session ( donc de son cache) : ceci libère la mémoire. Tu peux ne pas le faire objet par objet comme avec l'evict, mais de façon globale avec le session.clear.

Enfin, toujours pour améliorer les perfs, tu peux également prévoir de gérer le flush ( synchro avec la base (sans commit)) manuellement ce qui évite trop d'allers retours entre ton code et la base et augmente les perfs.


Bref, en résumé : utiliser session.clear, ne créer les query qu'une seule fois, utiliser du cache de second niveau si nécessaire, et gérer le flush. Sans ces quelques principes, les performances d'hibernate sur des batchs (nombreuses itérations) sont désastreuses. Elles deviennent très acceptables une fois ces principes appliqués.

En espérant que tu pourras transposer à .NET

Airness


Top
 Profile  
 
 Post subject: Ca marche
PostPosted: Thu Jul 26, 2007 7:07 am 
Newbie

Joined: Wed May 23, 2007 4:09 am
Posts: 16
Merci, de cette explication clair et consise.
Merci mille fois même car je commençait à m'inquiéter sur la stabilité de nHibernate.
J'ai donc résolu mon problème de performances en mettant session.FlushMode à Commit et non pas sur Auto.
NHibernate est vraiment très rapide !!!

Cela m'amène à une autre question: même si je met FlushMode à Never, et que je génère une exeption dans mon code en plein milieu de ma boucle, les données apparaissent dans la base de données.
nHibernate à donc bien fait des flush....
Je me demande pourquoi?

Quelle sont les réels implications de mettre FlushMode à Never ou à Commit? J'ai bien lu la doc, mais en réalité? Avez-vous des retours d'expériences?


Top
 Profile  
 
 Post subject: Flush Mode
PostPosted: Thu Jul 26, 2007 8:35 am 
Newbie

Joined: Wed Jul 25, 2007 8:49 am
Posts: 4
Avec un FlushMode positionné à COMMIT, hibernate ne flushe à priori qu'au commit de la transaction.
Avec un FlushMode à NEVER (MANUAL dans les dernières versions), c'est à toi de faire un session.flush() avant ton commit pour forcer hibernate à flusher. Je pense à priori que si tu n'as pas flushé avant un evict ou un clear de session, ta modification est perdue !

Au vu du cas que tu cites, peut-être que le flushMode ne s'applique pas sur un save ou saveOrUpdate ? Il ne s'appliquerait dans ce cas que sur les modifs d'objets ( pour lesquels un update est inutile, processus de dirty checking d'hibernate). Mais là je ne peux rien t'assurer.

Airness


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 4 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.