0
votes

Maxing Out HDD Vitesse de lecture en Java pour une analyse rapide

J'ai d'énormes fichiers texte (3 chiffres-gb) représentant plusieurs objets du format suivant (// et <> ne sont que mes commentaires): XXX

Je tiens à créer des lignes dans ma base de données du formulaire valeur2, valeur3 Je l'ai donc programmé à l'aide de la liste LIVELINE de BufferedReader de Bufferedreader3] en tant que petite classe de mine dans une liste lié à lire par un autre fil en les insérant dans la base de données dès qu'il y a 1_000_000. Je pensais que cela tirerait le meilleur parti de la vitesse de lecture de mon disque dur. Mais au lieu de 190 Mo / s, je n'obtiens qu'environ 135 Mo / s, la raison étant que la CPU ne pouvant pas être en mesure d'analyser à cette vitesse. Le noyau du fil d'analyseur type de pointes de hausse et bas dans la région de 90% à 100%.

à travers des tests que j'ai découverts, qui lisent de gros bytes [] les tableaux et la convertir en cordes en une seule fois Utilise beaucoup plus le disque dur car il est plus rapide sur la CPU. Donc, mon idée était de mettre les matrices d'octets dans une file d'attente à travailler par plusieurs threads. Cependant, l'octet [] pourrait se terminer au milieu d'une ligne et donc ruiner l'analyse ou nécessiter une communication (compliquée?) Entre les threads afin de résoudre ce problème. De plus, des lignes d'un objet seront divisées entre deux threads qui n'est pas agréable.

Note latérale: Je pense que j'ai un peu trouvé l'algorithme d'analyse la plus rapide pour ce format particulier: Il suffit de numériser jusqu'à ce que vous ayez trouvé '[attr2 »' (sans le '') prenez la valeur2, puis la même chose pour atter3, puis stockez l'objet à la file d'attente. L'ordre des attributs est identique, mais il pourrait y avoir des attributs d'entre elles. dans certains cas rares. La question est de savoir comment faire de plusieurs threads, ce qui fonctionne sur un autre groupe d'octets chacun.

Ouais, c'est donc mon problème actuel, je veux que ce problème soit analysé aussi vite que possible et que je demande donc votre Sagesse :)

Ma meilleure pensée jusqu'à présent est que chaque fil comprenne chaque fil de côté les premières et dernière lignes (probablement cassées) dans une certaine source de données pour qu'ils soient fixés plus tard (je me fiche de la ordre des objets).

Vous avez probablement une idée plus simple, plus rapide et plus simple?


2 commentaires

Il est hautement improbable que vous puissiez "maximum" votre vitesse de lecture de votre disque dur. Pas en Java. Pas dans n'importe quelle langue.


Le seul but du disque dur est de disposer de ces fichiers stockés et de lire. Il n'a pas d'autre emploi, rien ne l'utilise. Lorsque j'utilise de grandes bytes [] tableaux, il devient très très proche de sa vitesse de lecture maximale


3 Réponses :


1
votes

Si votre performance est liée à la CPU, comme vous le croyez, vous avez raison, vous avez raison de faire l'analyse de plusieurs cœurs en parallèle, c'est la voie à suivre.

J'essaierais d'avoir un seul fil qui crée des tampons contenant un certain nombre de lignes complètes, puis envoie ces tampons à un pool de fils d'analyse. Ce fil unique serait un goulot d'étranglement, mais je pense que vous pourriez être capable de le rendre assez rapide.

Je lisais un tampon, pas faire une conversion de chaîne, laissez-le simplement en octet [], puis numérisez vers l'arrière de la fin pour trouver des lignes partielles. Envoyez ce tampon à analyser, avec une taille qui indique à l'analyseur de ne pas analyser la ligne partielle. Espérons que la numérisation à l'envers est aussi simple que "numériser jusqu'à la recherche d'un"] ", à moins que des caractères"] "peuvent apparaître dans les valeurs.

Copier la ligne partielle au début de la mémoire tampon suivante, puis lisez plus d'octets directement après la ligne partielle, etc.

Puis chaque fil d'analyse a des lignes complètes pour travailler.

Le thread de goulot d'étranglement est rapide, car il ne scanne que les derniers octets de chaque tampon avant de le transmettre.

Il y a d'autres choses que vous pourriez faire, telles que l'allocation statique des tampons pour éviter GC et faire toute l'analyse dans un octet [] au lieu de la chaîne, mais je pense que c'est une optimisation prématurée.


2 commentaires

Cela séparerait toujours les objets entre les tampons car un objet consiste en plusieurs lignes. Par conséquent, je dois numériser à l'envers jusqu'à ce que je trouve '[last_attribute_i_want ""]', non?


Oui, cela diviserait les objets. Donc, ainsi que la longueur du tampon, vous devez passer un numéro de séquence de bloc qui permettrait à la valeur correspondante2 de Block N avec Value3 à partir de Block N + 1, pour éviter de balayer de loin. Mais cela devient compliqué, je pense que @ici est une meilleure solution.



1
votes

Il n'y a aucune bonne raison pour laquelle avoir une division de données sur deux tampons consécutifs devrait causer des complications majeures.

supposer que les données d'intérêt sont courtes par rapport à la taille de la mémoire tampon (ce qui semble probable, puisque vous dites que les tampons sont choisis pour être très gros), les scissions tampons au milieu des données intéressantes seront très rares, donc un ultra- Une solution efficace n'est pas nécessaire. La solution simple est donc destinée au fil de lecture de revenir à la lecture du bloc de données suivant afin de compléter les données intéressantes. Bien sûr, ces données ont déjà été lues, mais la lu deux fois ne va pas causer de mal.

(le fil doit lire le prochain bloc de données même s'il n'a pas encore terminé la correspondance de [attr2 lorsqu'il atteint la fin du tampon. Mais s'il s'avère que ça n'a pas été [attr2 , il se termine simplement.)

Cette stratégie n'entraînera pas le même [attr2 étant traitée par plusieurs threads, car il n'est traité que par le fil qui a reçu le tampon qui contient le premier caractère du motif. Et, comme mentionné ci-dessus, il n'augmentera pas de manière significative le nombre de lectures de disque effectuées. (En fonction de votre système d'exploitation et de votre chargement de la machine, il peut ne pas augmenter le nombre de lectures de disque, car il est possible que le bloc de données soit toujours dans le cache tampon du système d'exploitation.)


1 commentaires

Wow, merci, si simple. Bien sûr, le format d'octet [] Un thread a pris peut également être lu par un autre fil!



1
votes

Sans le code réel, il est proche de l'impossible de trouver le goulot d'étranglement de la CPU.

Donc, procurez-vous un profileur décent (chez notre société que nous utilisons JProfiler) pour connaître la méthode / la ligne de code consommant la majeure partie de la CPU.

Lors du profilage, votre application fonctionnera comme 10x plus lente que la normale, mais les temps relatifs passés dans les différentes parties resteront plutôt représentatifs pour l'exécution normale.

Souvent, vous trouverez une seule méthode appelant 90% de la CPU. Optimiser celui-là.


0 commentaires