10
votes

Manipulation de grands ensembles de données en Java / Clojure: Data Littlebig

J'ai travaillé sur une application de traitement des graphiques / données ( Vous pouvez voir une capture d'écran ici ) en utilisant Clojure (cependant, souvent, on a l'impression d'utiliser plus de Java que de Clojure), et j'ai commencé à tester mon application avec de plus grands ensembles de données. Je n'ai aucun problème avec environ 100k points, mais quand je commence à obtenir plus haut que cela, je rencontre des problèmes d'espace de tas.

Maintenant, théoriquement, environ une demi-GB devrait suffire à contenir environ 70 millions de doubles. Certes, je fais beaucoup de choses qui nécessitent des frais généraux, et je peux en fait conserver 2-3 copies des données en mémoire en même temps, mais je n'ai pas encore optimisé encore, et 500k ou donc encore < em> ordres de grandeur moins que cela, je devrais pouvoir charger.


Je comprends que Java a des restrictions artificielles (pouvant être modifiées) sur la taille du tas, et je comprends que celles-ci peuvent être modifiées, en partie, avec des options que vous pouvez spécifier au fur et à mesure que le JVM commence. Cela me conduit à mes premières questions :

  • Puis-je modifier l'espace de tas maximum autorisé si j'utilise Swank-Clojure (Via Leiningen), le JVM a le démarrage?

  • Si j'emballez cette application (comme je planifie) comme un Uberjar, serais-je en mesure de vous assurer que mon JVM a une sorte d'espace de tas minimum?

    Mais je ne me contestez pas simplement de s'appuyer sur le tas de la JVM pour alimenter ma demande. Je ne connais pas la taille des données que je peux éventuellement travailler, mais cela pourrait atteindre des millions de points, et peut-être que le tas ne pouvait peut-être pas accommoder cela. Par conséquent, je suis intéressant dans la recherche d'alternatives pour accumuler simplement les données sur. Voici quelques idées que j'avais, et questions à leur sujet:

    • Serait-il possible de lire uniquement des parties d'un fichier important (texte) à la fois, je pourrais donc importer et traiter les données dans "Chunks", par exemple, n lignes à la fois? Si c'est le cas, comment?

    • Y a-t-il un moyen plus rapide d'accéder au fichier que je lisais (potentiellement rapidement, en fonction de la mise en œuvre), autrement que simplement la lecture un peu à la fois? Je suppose que je demande que je demande aux conseils / hacks qui ont travaillé pour vous dans le passé, si vous avez fait une chose similaire.

    • Puis-je "échantillonner" du fichier; par exemple. LIRE SEULEMENT TOUS LES LIGNES Z , rédigant efficacement mes données?

      En ce moment, je prévois, s'il y a des réponses à ce qui précède (je vais continuer à rechercher!) ou des informations proposées qui conduisent à des solutions équivalentes, lisez-la dans une partie de données à la fois, graphique à la timeline ( Voir la capture d'écran -Le calendrier est vert) et a permis à l'utilisateur d'interagir avec juste ce bit jusqu'à ce qu'elle clique sur < Code> Next Chunk (ou quelque chose), puis je sauvegarderais des modifications apportées à un fichier et chargez le prochain "chunk" des données et l'affiche.

      Alternativement, j'afficherais l'ensemble de la chronologie de toutes les données (rédigées, afin que je puisse le charger), mais autorise uniquement l'accès à un "morceau" de celui-ci à la fois dans la fenêtre principale (la partie visualisée au-dessus de la chronologie verte, comme indiqué par le rectangle de fenêtre dans la chronologie).


      surtout de tous, cependant, y a-t-il une meilleure façon ? Notez que je ne peux pas descendre les données de la fenêtre principale, car je dois être capable de le traiter et laisser l'utilisateur interagir avec celui-ci (par exemple, cliquez sur un point ou à proximité pour ajouter un "marqueur" à ce point: ce marqueur est dessiné comme une règle verticale sur ce point).

      J'apprécierais toute idée, réponses, suggestions ou corrections! Je suis également prêt à exposer sur ma question de toute façon que vous le souhaitez.

      Cela espérons-le, au moins en partie, être ouvert à la source; Je voudrais un moyen simple à utiliser et rapide de faire des xy-parcelles de nombreuses données dans le monde des clojures.


      édition Downsample n'est possible que lorsque graphique, et pas toujours, en fonction des parties en étant graphique. J'ai besoin d'accéder à toutes les données pour effectuer une analyse. (Il suffit de débarrasser cela!) Bien que je devrais certainement examiner la descente, je ne pense pas que cela résoudra mes problèmes de mémoire du moins, car tout ce que je fais au graphique est en train de dessiner sur une bufferedimage.


0 commentaires

3 Réponses :


2
votes

lancer une couple d'idées du champ gauche ...

Vous trouverez peut-être quelque chose d'utile dans la bibliothèque Colt ... http: //acs.lbl. GOV / LOGICIEL / COLT /

ou peut-être des E / S mappées de mémoire.


3 commentaires

Je vais regarder dans ceux-ci! Merci.


Il convient également de rechercher un projet d'inchange, combinant de nombreuses bibliothèques de Java scientifiques dans un très bon environnement de type R (et des bibliothèques)


J'ai! En fait, j'utilise des parties de celui-ci. Le problème est que c'est terriblement lent pour de grandes quantités de données. Je l'aime bien, cependant.



2
votes

Quelques pensées:

  • Le meilleur moyen de gérer de grands ensembles de données en mémoire dans Java / Clojure consiste à utiliser de grandes matrices primitives. Si vous faites cela, vous n'utilisez essentiellement qu'un peu plus de mémoire que la taille des données sous-jacentes. Vous gérez ces tableaux dans le clojure très bien avec la fonctionnalité AGET / ASTURE

  • Je serais tenté de rétrograder, mais de maintenir un moyen d'accéder paresseusement aux points détaillés "sur demande" si vous en avez besoin, par exemple. dans le cas d'interaction utilisateur. Un peu comme la façon dont Google Maps vous permet de voir le monde entier et ne charge que le détail lorsque vous effectuez un zoom avant ....

  • Si vous ne vous souciez que de l'image de sortie de l'intrigue X-Y, vous pouvez la construire en chargement dans quelques milliers de points à la fois (par exemple, chargez-vous dans vos réseaux primitifs), les traçant ensuite en cas de défaillance. De cette façon, vous n'aurez pas besoin de conserver le jeu de données complète en mémoire.


0 commentaires

7
votes

Puis-je changer le tas maximum autorisé espace si j'utilise Swank-Clojure (via Leiningen) La JVM a au démarrage?

Vous pouvez modifier la taille du tas Java en fournissant les options -XMS (Min Heap Teas) et -XMX (MAX HEAP) au démarrage, voir le docs .

Alors quelque chose comme java -xms256m -xmx1024m ... donnerait 256 Mo de tas de tas avec l'option de croissance à 1 Go.

Je n'utilise pas Leingen / Swank, mais je m'attends à ce qu'il soit possible de le changer. Si rien d'autre, il devrait y avoir un script de démarrage pour Java quelque part où vous pouvez changer les arguments.

Si j'emballe cette application (comme i plan de) comme un uberjar, serais-je capable de s'assurer que mon JVM a une sorte de espace de tas minimum?

La mémoire n'est pas contrôlée à partir d'un fichier JAR, mais à partir du script de démarrage, normalement un fichier .sh ou .bat qui appelle Java et fournit les arguments.

Puis-je "échantillonner" du fichier; par exemple. Lisez seulement toutes les lignes Z?

java.io.randomAccessfile donne Accès au fichier aléatoire par l'indice d'octets, que vous pouvez construire pour échantillonner le contenu.

serait-il possible de lire seulement parties d'un fichier grand (texte) à un temps, donc je pourrais importer et traiter les données dans "morceaux", E.g, n lignes à Un temps? Si oui, comment?

Line-SEQ renvoie une séquence paresseuse de chaque ligne dans un fichier, de sorte que vous pouvez traiter autant de choses à la fois comme vous le souhaitez.

Alternativement, utilisez les mécanismes Java dans java.io - bufferedreader.readline () ou fichierInputtream.read (byte [] tampon)

Y a-t-il un moyen plus rapide d'accéder Le fichier que je lisais de (potentiellement rapidement, en fonction de la la mise en œuvre), autre que simplement lire un peu à la fois?

Dans Java / Clojure, vous trouverez BufferedReader ou vous pouvez maintenir votre propre tampon d'octets et lire des morceaux plus grands à la fois.

Pour tirer le meilleur parti de la mémoire que vous avez, conservez les données aussi primitives que possible.

Pour certains nombres réels, supposons que vous souhaitiez graphiquement le contenu d'un CD de musique:


3 commentaires

Merci beaucoup pour l'excellente réponse: je vais essayer certaines de ces suggestions sous peu.


Je suis allé avec Java.IO.RandomAccessFile et beaucoup cherche / relookbytes pour me donner une fonction qui renvoie rapidement un "morceau" du fichier. Je peux donc demander 512000 morceaux d'octets à la fois et choisir le chunk précédent ou le prochain morceau. Je posterai la fonction assez bientôt, mais merci beaucoup pour l'aide!


Je vous en prie. Pour d'autres optimisations, je recommanderais de connecter un profileur (comme Visualvm: VisualvM.Dev.java.net ), cela vous montre où le temps et la mémoire sont dépensés. Bonne chance pour ton projet :)