Rapide CSV analyse
J'ai un serveur java app télécharger le fichier CSV et l'analyse. L'analyse peut prendre de 5 à 45 minutes, et se produit à chaque heure.Cette méthode est un goulot d'étranglement de l'application de sorte qu'il n'est pas prématuré d'optimisation. Le code pour l'instant:
client.executeMethod(method);
InputStream in = method.getResponseBodyAsStream(); //this is http stream
String line;
String[] record;
reader = new BufferedReader(new InputStreamReader(in), 65536);
try {
//read the header line
line = reader.readLine();
//some code
while ((line = reader.readLine()) != null) {
//more code
line = line.replaceAll("\"\"", "\"NULL\"");
//Now remove all of the quotes
line = line.replaceAll("\"", "");
if (!line.startsWith("ERROR"){
//bla bla
continue;
}
record = line.split(",");
//more error handling
//build the object and put it in HashMap
}
//exceptions handling, closing connection and reader
Est-il une bibliothèque existante qui pourrait m'aider à accélérer les choses? Puis-je améliorer le code existant?
- Quelle est la taille du fichier? Et avez-vous essayé de profilage de votre code? Cela vous donnera votre goulot d'étranglement et une idée claire d'où l'amélioration. Je ne serais pas surpris si c'est votre réseau est le premier problème. Aussi jeter un oeil à commons.apache.org/sandbox/csv en lieu et place de la construction de l'analyseur de vous-même.
- Je suis de profilage, et je suis conscient que la grande partie du temps est causée par une connexion réseau. Je veux améliorer l'analyse tout d'abord parce qu'avec le réseau, j'ai besoin de changer l'architecture. (Mon estimation, qui est plus rapide que l'analyse peut améliorer le temps de chargement de 10 à 15%).
- Juste des sons. Utilisez un csv analyseur ces sont optimisés déjà et vous êtes lié à courir dans l'évasion et de l'i18n questions en bas de la route qui vous ne voulez pas à s'inquiéter. Bonne chance.
- Semble que la méthode actuelle est assez rapide il faut 2 secondes pour analyser un fichier donc au total avec tous les fichiers d'analyse prend moins de 1% ;/
- Voir aussi stackoverflow.com/questions/3908012/parsing-csv-in-java
- Aucune idée si c'est applicable pour votre domaine, mais je considère la création de scripts shell de base de traitement (par exemple,
replaceAll
dans votre code). SED / AWK sont en fait conçues pour ce genre de choses, ne pensez pas que vous pouvez obtenir beaucoup plus vite que ça. JVM serait alors "seulement" besoin d'analyser les pré-traitées les données. Mais encore une fois, cela peut ne pas être applicable.
Vous devez vous connecter pour publier un commentaire.
Apache Commons CSV
Avez-vous vu Apache Commons CSV?
Mise En Garde Sur L'Utilisation De
split
Garder à l'esprit est que
split
ne renvoie une vue des données, ce qui signifie que l'originalline
objet n'est pas admissible pour la collecte des ordures alors qu'il y a une référence à l'un quelconque de ses points de vue. Peut-être faire une défensive copie de l'aide? (Java rapport de bug)Il n'est pas aussi fiable dans le groupement échappé CSV colonnes contenant des virgules
opencsv
Prendre un coup d'oeil à opencsv.
Ce blog, opencsv est facile CSV analyseur, a exemple d'utilisation.
Outre les suggestions ci-dessus, je pense que vous pouvez essayer d'améliorer votre code à l'aide de certains de filetage et de la concurrence.
Qui suit est une brève analyse et proposition de solution
Si la solution implique un effort, mais à la fin ce sera sûrement vous aider.
Le problème de votre code, c'est que c'est à l'aide de replaceAll et split, qui sont très coûteux en fonctionnement. Vous devriez certainement envisager d'utiliser un fichier csv analyseur/lecteur qui permettrait de faire un passage de l'analyse.
Il y a une référence sur github
https://github.com/uniVocity/csv-parsers-comparison
qui, malheureusement, est couru sous java 6. Le nombre sont légèrement différents sous java 7 et 8. Je vais essayer d'obtenir plus de détails de données pour différentes taille de fichier, mais c'est un travail en cours
voir https://github.com/arnaudroger/csv-parsers-comparison
opencsv
Vous devriez jeter un oeil à OpenCSV. Je m'attends à ce qu'ils ont de l'optimisation des performances.
Un peu de retard ici, il y a maintenant quelques projets de benchmarking pour CSV analyseurs. Votre choix dépendra de l'utilisation exacte des cas (c'est à dire les données brutes vs la liaison de données, etc).
Pour la vitesse que vous ne souhaitez pas utiliser replaceAll, et vous ne voulez pas utiliser les regex soit. Ce que vous avez toujours envie de faire dans les cas critiques comme ça, c'est de faire une machine d'état, caractère par caractère de l'analyseur. Je l'ai fait avoir roulé le tout dans une Itératif de la fonction. Il prend également dans le flux et l'analyse sans l'enregistrer ou de la mise en cache il. Donc, si vous pouvez abandonner au début qui va probablement aller très bien. Il devrait également être assez court et bien codé assez évident de savoir comment il fonctionne.
En général les processus de cette très utiles comme:
La beauté de l'API, il vaut la peine de l'apparentent à la recherche de la fonction.
Apache Commons CSV ➙ de 12 secondes pour les millions de lignes de
Oui, le Apache Commons CSV projet fonctionne très bien dans mon expérience.
Voici un exemple d'application qui utilise Apache Commons CSV bibliothèque pour lire et écrire des lignes de 24 colonnes: Un entier numéro séquentiel, un
Instantané
, et le reste sont aléatoiresUUID
objets.Pour 10 000 lignes, l'écriture et à la lecture de chacun prendre environ une demi-seconde. La lecture comprend la reconstitution de la
Integer
,Instant
, etUUID
objets.Mon exemple de code vous permet d'activer ou de désactiver la reconstitution d'objets. J'ai couru à la fois avec un million de lignes. Cela crée un fichier de 850 mo. Je suis à l'aide de Java 12 sur un MacBook Pro (Retina, 15 pouces, Fin 2013), 2,3 GHz Intel Core i7, 16 GO 1600 MHz DDR3, Apple SSD.
Pour un million de lignes, dix secondes pour lire plus de deux secondes pour l'analyse:
Code Source est une seule
.java
fichier. A une méthode d'écriture, et unread
méthode. Les deux méthodes appelées à partir d'unmain
méthode.J'ai ouvert un
BufferedReader
en appelantFichiers.newBufferedReader
.