Anthony Patricio’s Blog

Decrypting another JPA benchmark

Posted in Persistance / Données by apatricio on octobre 23, 2012
Reviewing a benchmark is always an interesting task. Unfortunately it is often useless because benchmarks are rarely a good representation of real life conditions.
Last month, someone told me a new JPA implementation was trying to make noise. The author was making some buzz almost everywhere on social networks, commenting on popular articles and writing 2 articles claiming that this implementation was over 15 times faster than Hibernate. And here we are again. This sort of buzz happens every 2 years, it’s a cycle, there is nothing we can do about that.

The benchmark

Reading more about the implementation, the focus is made on fine grained tuning on every single line of code which is a really brave approach. However the way to announce « The New JPA Implementation That Runs Over 15 Times Faster… » is not a good way to promote the implementation. Anyway let’s have a closer look at the benchmark that allowed the author to conclude « 15 times faster ».
The benchmark is essentially composed of massive inserts, updates, deletes, queries by packet of 250 iterations. The domain model is composed of
  • 4 entities, yes 4 entities,
  • no inheritance, it sounds weird that a fabulous JPA implementation is not including more mapping configurations in its benchmark
  • eager fetching enabled (no subselect fetching for example),
  • cascading enabled,
  • no versioning

Last but not least, the benchmark targets an in-memory database, yes this is where it becomes suspicious.

15 times faster… faster what?

The big problem behind the title is that faster is not at all related to response time. The author tries to explain it, it’s related to CPU load, fair enough but could he clearly explain the consequences on a full system?
The fact is that the results are really hard to read and there is no relative view of the benchmark. You are told that Batoo might take 15 times less CPU time than Hibernate and what? The danger here is to mix internal APIs CPU load with the full persistence cycle composed of JPA internals, JDBC driver, networking, database engine. We all know, at least I hope so, that most of the time is spent on network and database so is this really important to focus _that much_ on JPA internals? Is hibernate that slow? Will Batoo solve your performance issues?
Let’s be extremely clear here, most of the performance issues users are facing are NOT because of JPA internals CPU load, the problems are almost always related to a slow database, too fat entity managers, inefficient queries. There are 3 general ways to solve these issues:
  • check your database !!! JPA is NOT going to fix a database internal problem
  • make a better use of the database and JPA
  • tune your own code, that requires various features and that is going to have a really big impact on the global performance numbers. In order to do so, the frameworks you are using must offer various features, this is exactly what Hibernate does: allows you to tune every single interaction your are triggering with the database.

Impacts: the Global view

I’m not going to rely on the timers provided by the benchmark. People are interested in checking how a system globally reacts when switching from one software option to another. I asked my friend and mate what tool a sysadmin would use to have a good view of the resources consumed by a process. « Easy » he told me, use the time command.
The time command runs the specified program command with the given arguments. When command finishes, time writes a message to standard output giving timing statistics about this program run. These statistics consist of (i) the elapsed real time between invocation and termination, (ii) the user CPU time (the sum of the tms_utime and tms_cutime values in a struct tms as returned by times(2)), and (iii) the system CPU time (the sum of the tms_stime and tms_cstime values in a struct tmsas returned by times(2)).
So I’m going to use time mvn test with the good format to grab the CPU numbers.
Some would say it’s not accurate. I would answer that it allows to measure a real relative impact on a global system not at the thread level.
We’ll see how much CPU% are consumed by the benchmark.
The good thing with mvn test is that we’ll also get the total time execution.

Well used Hibernate is ways faster than noob Hibernate 

In order to do some tuning, I’ll start with a low BENCHMARK_LENGTH iteration number, let’s say 5. That is 5 times each sub test, one subtest globally doing 250 iterations.
Since the in-memory db will be started by the root process, time command will also catch the DB load which we don’t want but we are just tuning the hibernate config for the moment.

Shoot 1: In memory derby, BENCHMARK_LENGTH 5

Hibernate 13 seconds 200% CPU
Batoo 9 seconds 210% CPU
Hibernate based setup _globally_ consumes less CPU but is also slower. Wait, I’ve said that this measure was including the database engine load. Having in mind that Batoo is claiming it consumes 15 times less CPU than hibernate what would that mean? That would mean that the JPA internal  CPU load is extremely low compared to the in-memory database CPU load … and still, we have an unsolvable equation here, we need more tests. Anyway, I already think know that CPU time consumed by JPA may not be a critical issue at all. But wait, small benchmark size and in memory database? This is irrelevant.
Let’s move to a local MySql instance, in-memory databases might be good for development, not for production. If I want a memory based config, I’ll got for Hibernate + Infinispan + a real database instance, not in-memory.

Shoot 2: Local MySql, BENCHMARK_LENGTH 10

Hibernate 44 seconds 64% CPU
Batoo 36 seconds 55% CPU
Batoo is the winner. Should we stop here? Certainly not.
Something is wrong. The good thing with hibernate, a _mature_ JPA implementation, is that it allows tons of tuning, being in the mapping, in the queries well everywhere. 
I remember 7 years ago, one guy at work was insulting Hibernate saying it was a piece a crap because he was observing memory issues and/or extremely long response times. One quick look at the hibernate documentation, 2 mapping parameter updates, more care of the entity manager (well Hibernate Session at that time), allowed to solve the memory issue and allowed a 10 000 faster execution. I promise it’s true, 10 000 times faster in response time.
A quick look at the documentation informs us that we should use the following global config parameters:
<property name="hibernate.jdbc.batch_size" value="50"/>
<property name="hibernate.order_update" value="true"/>
<property name="" value="true"/>
More important: checking the INFO level logs, you’ll notice that the author of the benchmark left the auto commit mode. For someone who claims to be implementing the fastest JPA implementation ever, he should review the basics.
So let’s add
<property name="hibernate.connection.autocommit" value="false" />
and rerun the test with something bigger, I also raise the BENCHMARK_LENGTH to 100. 

Shoot 3: Local MySql, BENCHMARK_LENGTH 100

Hibernate 5 min 1 seconds 29% CPU
Batoo 4 min 52 seconds 22% CPU
29% versus 22% CPU… We are talking about a production server. In my case I used a 8 core CPUs 3 years old server. 
29% of one CPU … 
This benchmark is using 
  • 3.625% of my global System CPU capacity with hibernate
  • 2.75% of my global System CPU capacity with Batoo
It seems we are really far from the 15 times faster!

A more realistic environment

I won’t stop here, the author says that his motivation is to reduce cluster size thanks to his optimized implementation. So let’s say I don’t have 8 core, only 2. Here I might be interested in reducing my CPU load.

Who says cluster, also says remote database. And even without a cluster, production system will host the database in a different server.
So I set up a really fast LAN, excellent ping and bandwidth.
Here are the new results

Shoot 4: Remote MySql, BENCHMARK_LENGTH 100

Hibernate 16 min 30 seconds 6% CPU
Batoo 17 min 55 seconds 5% CPU
(Is it me or Hibernate is faster ?)
Which, for a 4 core CPUs system means
  • 1.5% of my global System CPU capacity with hibernate
  • 1.25% of my global System CPU capacity with Batoo
or for a 8 core CPUs system means
  • 0.75% of my global System CPU capacity with hibernate
  • 0.62% of my global System CPU capacity with Batoo
Yes Batoo is better in terms of CPU load but with such low levels, who cares? The persistence engine is always waiting for the database!
In the middleware side we have a very low CPU load (at least for the JPA part), what about the DB server side? We have one CPU over the 4 constantly above 80%. A second one above 40%.

Putting all of this together, Batoo MAY consume slightly less CPUthan Hibernate but the actual database load on these benchmarks far outweighs the load imposed by either Batoo or Hibernate.

And, since the internal ORM performance is a relatively minor issue, we should think about the products’ features.
Why is that important?
  • write stupid queries and you’ll get network, database and possibly memory issues (no matter if you use Hibernate or Batoo) -> query oriented advanced features are welcome
  • be idiot using the entity manager and you’ll observe slowness and memory issues (no matter if you use Hibernate or Batoo) -> get some training and certification, persistence is not something easy, you need SKILLS 
  • not talking about the DB slowness … if you do not understand RDBMS, you MUST work with a DBA, this is not an advice, this is a requirement.
  • if you are an expert in JPA, and your application is slow because of the database, you may have hit the RDBMS limitations. Give a try to Hibernate OGM with a NoSql supported database.

Shoot 5: Remote MySql, BENCHMARK_LENGTH 100, 2 concurrent run

I’m not going to provide the results but response times are impacted by 50%. CPU load is close to 2%

Conclusion: I don’t care these CPU optimizations I prefer FEATURES!

I honestly cannot imagine JPA being a cause of CPU problem in a real life scenarios. I’m also not forgetting that Hibernate is a 12 years old project. Talented people are working full time on it, the major version is 4, that means it has been heavily totally reworked 4 times. So that’s enough to understand that it is well written and that efforts are put in the most critical area: offering features.

I did online community support then official Red Hat support. I’ve seen query response times issues (1), memory issues (2) sometimes but I can’t remember about a CPU issue related to JPA internals.

To solve 1 and 2, you need skills but also features that help you tune your code. Like being able to use a specific database syntax (dialects), or  tune associations loading, I could continue on 300 pages here and I would recommend you simply consult the Hibernate documentation’s index.

Tagged with: , , ,

La gestion des compétences

Posted in Actu / Anecdote by apatricio on octobre 3, 2012

J’ai lu avec intérêt le billet suivant:

Je suis sur le fond entièrement d’accord avec l’auteur mais la forme pose problème, ce qui est aussi relayé par certains commentaires. La question de la responsabilité de la formation est forcément soulevée.

Le développeur est-il seul responsable de sa formation? Dans la plupart des corps de métier, la réponse est évidemment non. Sous prétexte qu’il y a tonnes de tutoriels sur le web et/ou que le développeur doit forcément être un passionné, il devrait passer son temps libre à s’auto-former… Soulignons au passage que si tout travailleur doit savoir *apprendre*, tout le monde n’est pas censé être pédagogue et l’auto formation ne sera jamais aussi efficace qu’un échange avec un instructeur qui a la pédagogie innée.

Le cas du débutant

Le développeur (souvent ingénieur, ce n’est pas rien) sort de l’école avec une base plus ou moins bonne, théorique, rarement pragmatique. Souvent en stage de dernière année pré embauche il sera directement vendu comme ingénieur au client (et non comme stagiaire). Certes, c’est plutôt formateur comme première approche s’il est au contact de coachs qui ont le temps de le former. Ce n’est pas souvent le cas, après une introduction d’une demi journée il sera en face de son IDE et devra pondre des lignes. La qualité du code produit laissera forcément à désirer. Peu importe, le client délègue souvent la technique et ne sera donc pas en mesure de capter la pauvre qualité produite. Le développeur débutant n’est clairement pas responsable de cette situation. L’effet papillon d’une telle production est qu’un second développeur non formé intervenant sur ce code bancal par la suite se dira « tiens c’est comme ça qu’on fait ici? » puis le copier/coller fera son oeuvre. De temps à autre un presta tiers spécialisé dans la revue de code (le bon rôle) pointera du doigt le problème et les développeurs s’en prendront forcément plein la figure par le client et par leur chef de projet.

En passant qu’elle est la différence entre un développeur et une personne qui fait de la revue de code? L’un peut ne disposer que de très peu de jours pour implémenter un cas d’utilisation complexe alors que l’autre, pour le coup reconnu pour ses compétences techniques, dispose en proportion de plus de temps pour revoir le code produit et l’incriminer. Au final, il se pourrait très bien que les 2 disposent des mêmes compétences, ils n’ont simplement pas les mêmes moyens.

Coder c’est facile!

Bizarrement, lorsque l’on parle d’informatique d’entreprise, on a le sentiment que la compétence peut facilement être acquise. Hors les outils, frameworks, standards, buzz se multiplient à une vitesse trop élevée pour que les choix de production finaux suivent. Le développeur doit alors constamment jongler entre les oldies (struts, frameworks faits maison,…), les standards de fait et bonnes spécifications (Spring, JPA, JSF 1), les nouvelles specs (JPA 2, JSF 2, CDI)  mais aussi les *nouveautés* (ce terme étant plus ou moins faussé et très relatif) (NoSQL, Scala, …). Les managers, clients et autres RESPONSABLES n’imaginent pas combien il est éprouvant de passer d’une techno à l’autre, c’est intellectuellement épuisant. Car utiliser une techno ne se limite pas à en maîtriser la syntaxe ou même les fichiers de configuration , c’est surtout en comprendre la philosophie et pourquoi/quand l’utiliser et en connaître ses bonnes pratiques et limites.

Administrer des systèmes et gérer des projets c’est difficile sensible

Il est encore plus étrange à mon sens, que les budgets formations et certifications soient si pauvres voire nuls en comparaison aux mêmes budgets de formations et certifications des administrateurs dans leur ensemble. J’ai accès à certains chiffres éloquents, un administrateur OS, DB, réseau et Serveur d’application se verra proposer régulièrement des formations pour mise à jour de ses compétences. Celles-ci se verront validées, mais surtout mises en valeur par l’obtention d’une certification. Pourquoi ce grand écart entre les admins système et les développeurs? La réponse super naïve est de dire que les admins flirtent avec le réseau, l’hardware dans son ensemble mais aussi et surtout la sécurité. En effet, un mauvais admin pourrait laisser ouvertes des failles de sécurité , il plantera une config routeur qui bridera à 10% la capacité réseau ou plantera le DNS, quand à l’admin serveur d’application il pourra planter son clustering en le paramétrant en UDP là où de toute évidence, seule la config TCP est autorisée…

Les managers pensant comme celà sont peut être naïfs ou ils se voilent la face. Ils n’ont pas conscience que tous ces éléments critiques (sécurité, engorgement hardware, scalabilité) peuvent être mis en péril au niveau de l’application elle-même. La plus petite des webapps peut provoquer des désastres. Un mauvais développeur mal formé pourra en 3 classes pourrir votre SI, ouvrir un faille de sécurité béante vers votre BDD (SQL injection) et monopoliser votre réseau inutilement (requêtes faites à la va vite sans réellement comprendre ce qu’il se passe derrière). Vous pensez ces symptômes d’un autre âge? Avez-vous entendu de la dernière grosse faille Yahoo? C’était cette année: , cause: SQL injection, chose que l’on peut créer dans n’importe quelle application en utilisant mal JPA, JDBC, iBatis. Etre admin système requiert à mon sens des compétences solides, certaines pas évidentes mais pas vraiment d’un niveau de complexité plus élevé que le développeur.

Passons maintenant aux chefs de projet. Pourquoi m’en prendre à eux? Parce que justement je ne m’en prends à personne, simplement dans beaucoup de domaines, les qualités d’un chef de projet sont reconnues en opposition à celles du développeur que l’on trouve banales, normales, aisées à acquérir. Alors certes, un chef de projet doit impérativement avoir un bon relationnel, être un bon communiquant et posséder un sens de l’organisation et de gestion des *ressources* et compétences _sick!_ de son équipe la plus pertinente possible. En option premium il possédera des bases sur le métier du client et des bases techniques de surface. Une fois écarté le stéréotype du développeur geek qui ne sait aligner 2 mots et qui vit en ermite devant son dual screen, le développeur ne possède t’il pas aussi les qualités que l’on loue au chef de projet? Ou tout du moins une partie commune? Chacun sera libre de répondre.

Après 2 ans en TMA sur une appli delphi, swing ou struts, le pauvre développeur n’a aucune motivation/raison pour aller de lui même se mettre techniquement à jour, pourtant on a tendance à estimer que c’est implicite dans nos domaines. Comment l’empêcher de vouloir se reconvertir/évoluer vers un poste de chef de projet? Un poste qui n’est pas simple certes mais qui au moins ne sous-entends pas de constamment revoir ses compétences techniques et surtout un poste reconnu.

Tout le monde y trouve son compte … sauf le développeur

Les formations ça coûte de l’argent. Dans un domaine hyper concurrentiel, une SSII qui formerait officiellement ses équipes devrait répercuter ces coûts sur les clients. Elle serait moins compétitive. Ainsi on ne peut rendre les directeurs de marché responsables de ce système.

Si j’étais pour la théorie du complot et je ne le suis pas, j’avancerai l’argument suivant:

  • un développeur correctement formé voire certifié produit plus vite mais surtout mieux
  • il en résulte des coûts de maintenance corrective moins élevés
  • mais aussi et surtout des coûts de maintenance évolutive réduits
  • donc globalement moins de business à moyen terme

La vérité est probablement ailleurs. L’ingénierie du logiciel bouge trop et trop vite. On assiste à des évolutions majeures, à l’émergence de nouveaux modèles tous les 2 à 3 ans. Dans ces conditions est-il réaliste d’envoyer son armée d’ingénieurs en développement en formation aussi souvent? Une solution est la spécialisation des effectifs mais là encore, on demande très souvent au développeur de s’adapter à tout et très vite.

Le client qui *pense* qu’écrire une application coûte ce qu’elle coûte avec les TJM (ou forfaits, les proportions restent respectées) constatés de nos jours devraient se poser la question suivante: « et si je demandais à chaque profil qui est amené à travailler sur mes applis qu’il possède dans ses bagages une vraie formation et/ou certification? ». Peut être devrait-il supporter une hausse des tarifs sur le court terme mais il se rendrait compte qu’au final il a tout à y gagner.

Je voterai donc pour une spécialisation plus prononcée des profils, qui serait validée et exigée par le client.