J'ai été chargé de lire de gros fichiers CSV (300k + enregistrements) et d'appliquer des modèles RegexP à chaque enregistrement. J'ai toujours été un développeur PHP et n'a jamais vraiment essayé d'autres langues, mais j'ai décidé que je devrais prendre la plongée et tenter de le faire avec Java que j'ai supposé que je serais beaucoup plus rapide.
En fait, juste lire la ligne de fichier CSV par La ligne était 3 fois plus rapide en Java. Toutefois, lorsque j'ai appliqué les exigences de REGEXP, la mise en œuvre de Java prouvait 10 à 20% plus longtemps que le script PHP. P>
Il est très bien possible que j'ai fait quelque chose de mal à Java, parce que je viens d'apprendre cela comme je suis allé aujourd'hui. Vous trouverez ci-dessous les deux scripts, tout conseil serait grandement apprécié. Je voudrais vraiment ne pas abandonner Java pour ce projet particulier. P>
code PHP p> code Java p>
5 Réponses :
Je ne vois rien de mal à votre code. Essayez d'isoler le cou de la bouteille de performance à l'aide d'un profileur. Je trouve le Netbeans profileur très convivial.
Edit: Pourquoi spéculer? Profil de l'application et obtenez un rapport détaillé de l'endroit passé. Travaillez ensuite pour résoudre les zones inefficaces. Voir http://profiler.netbeans.org/ pour plus d'informations. P>
EDIT2 : D'accord, je me suis ennuyé et j'ai profilé ceci. Mon code est identique au vôtre et analysé un fichier CSV avec 1 000 lignes identiques comme suit: p> Voici les résultats (évidemment, vos résultats seront différés car mes expressions ordinaires sont triviales) . Cependant, il est évident de voir que le traitement des regex n'est pas votre principal domaine de préoccupation. P> intéressant, si j'appliquais une buffereDreader, la performance est améliorée par un 18% (voir ci-dessous). P>
p>
p> p>
Je viens de fouetter cela dans le Bloc-notes ++, mais je vais donner aux Netbeans un aller et voir ce qu'il indique.
Apparemment, je ne sais pas comment utiliser le profileur efficacement. J'ai couru le profileur contre mon application Java, mais tout semble me montrer est la mémoire (tas), la mémoire (GC) et les threads / classes chargées ... avec le temps d'exécution de la principale (). Y a-t-il de bons tutoriels sur la façon d'utiliser cela?
@IOInterrupt - in NetBeans, profil> Profil Projet principal> CPU> Application complète> Exécuter
Merci! J'ai constaté que je devais régler le filtre pour "profiler toutes les classes" pour montrer les résultats en direct. Je vais creuser plus profondément dans cela, alors je comprends exactement ce que le problème est. Merci encore.
quelques points à noter ici. P>
Vous commencez à mesurer l'heure avant même que les motifs ne soient compilés. Je ne suis pas sûr à quel point Imprimer directement que les résultats correspondants dans le fil principal lui-même (comme Pattern.comPILE CODE> est une opération relativement coûteuse et peut consommer plus de temps si le motif est complexe. Pourquoi ne pas commencer à mesurer après l'étape de compilation? P> li>
csvreader code> classe est. p> li>
system.out.println code> bloque et coûteux), vous pouvez peut-être déléguer une impression à un fil différent. p> li>
ol>
Je préfère le temps le script de la création, car les deux scripts font essentiellement la même chose et je pense que le temps d'exécution total du script est un indicateur valide. Je pensais que la complexité de l'expression régulière était la question que je les ai donc changées pour être un mot commun unique. Le temps d'exécution PHP était de 93 secondes à 246 secondes de Java. Je pense que la classe CSVReader est efficace, car elle a été capable de lire le fichier CSV beaucoup plus rapidement (3x plus rapide) que la fonction PHP FgeCSV (). De plus, j'ai commenté la fonction println ().
@IOInterrupt: Droite. Il existe un certain nombre de facteurs qui peuvent venir jouer ici. La quantité d'entrée de la mémoire au VM joue également un rôle majeur. Vous pouvez essayer de profiler l'application comme suggérée au hotipolloi.
Je suis tout à fait ignorant quand il s'agit du VM. J'étais juste heureux de faire fonctionner cette opération.
Plusieurs choses: p>
La regex doit être compilée une seule fois et devrait être au démarrage du serveur, donc ne comptent donc pas vraiment pour la performance pendant son fonctionnement. P> LI>
Et surtout, vous écrivez une référence complètement non valide pour un programme Java à exécution longue. Vous chargez très certainement plusieurs classes pendant que l'analyse comparative et globalement ne teste que la performance de l'interprète et non le JIT qui entraînera évidemment une performance bien pire. Voir Ce excellent poste pour comment écrire une référence valide en Java. Très certainement, cela remédiera à tous les problèmes de performance présumés dans ce cas. P> li> ol>
L'OP n'a pas dit qu'il y avait un serveur, ni qu'il s'agissait d'un programme de course à pied. Ce pourrait être le cas, et vous auriez alors raison, mais ce n'est peut-être pas.
Supposé que c'était un serveur parce qu'il utilisait php, mais oui vous avez raison. Mais si le programme ne fonctionne pas longtemps et que ce n'est pas une performance cruciale, pourquoi l'enfer se soucierait-il de l'optimiser?
Le script PHP est couru manuellement via le php CLI, tout comme l'application Java est en cours de course manuellement. Je ne suis pas sûr que cela fait une différence dans ce que vous suggérez. Les deux scripts fonctionnent pendant environ 10 minutes lors du traitement d'un fichier CSV de 500 Mo.
Utiliser un lecteur en mémoire tampon strong> peut aider les performances à devenir un peu mieux:
Bonne prise, si la filereader ne vous tamponne pas elle-même, c'est sûrement un goulot d'étranglement de la performance.
C'est plus que ce soit si des tampons de CSVReader ou non.
Cela a donné une légère augmentation, mais n'était pas la sauce magique. Merci pour les suggestions!
Je recommanderais: p>
Il est tout à fait possible que des parties du moteur Regex de PHP soient plus optimisées que celle de Java pour des types d'expression spécifiques, et / ou un moyen d'optimiser l'expression réelle que vous utilisez. P>
Pas entièrement lié à votre problème de regex, mais vous voudrez peut-être regarder download.oracle.com/javase/6/docs/api/java/util/scanner.html . Vous trouverez peut-être que votre classe CSVReader n'est pas nécessaire. Ne crée pas toutes ces chaînes temporaires (
nextline code> semble avoir au moins 7 chaînes, mais que vous n'avez besoin que d'un) pourrait améliorer les performances.