Tags:
create new tag
, view all tags

Stage de Nicolas Adam - ENSIIE Strasbourg - [30/05/16 au 5/08/16]

Important : cette page est réservée au suivi du stage, merci de ne pas la modifier

Informations générales pour les stagiaires

Pour toute information concernant ce stage : contacter André

Sujet

Documents de travail

  • ...

Stage (mai - août 2016)

Mai

  • 30 :
    • Accueil
    • Téléchargement de Webstorm, clone du git
    • Lecture des pages de wiki de Pierre et Arnaud + rapport de stage de Pierre
    • Début de lecture et compréhension de l'app
  • 31 :
    • Focalisation sur la création de l'octree
    • Lancement de l'application et divers tests
    • Piste : nanocubes

Juin

  • 1 :
    • Lecture de différentes classes dans l'application
    • Test de fonctionnalités découvertes en lisant le code de l'application
  • 2 :
    • Discution avec Jérôme de l'application et changement de bureau (j'occupais la place de Jérôme lorsqu'il n'était pas là)
    • Pré-soutenance des stagiaires en salle de réunion
    • Recherche sur MongoDB, notamment sur la création d'arbres et la façon de stocker de très nombreuses d'informations. Dans le cadre des arbres, il semblerait qu'il faille privilégier un document par noeud
    • Recherche sur la façon dont est traité le zoom dans l'application : cet outil me sera probablement utile. À poursuivre...
  • 3 :
    • Conférence : "Progrès récents des tests de la gravitation dans le système solaire", Christophe Le Poncin-Lafitte
    • Rapide comparaison de certaines BDD noSQL : http://www.developer.com/db/nosql-database-comparison-mongodb-apache-cassandra-and-couchbase.html
    • Exercice alerte incendie
    • Lecture du research paper sur les nanocubes : http://nanocubes.net/assets/pdf/nanocubes_paper.pdf
      • Résumé : Un nanocube est une représentation de données spatio-temporelles et d'attributs. Un nanocube peut contenir plusieurs millions à plusieurs milliards d'entrées, tout en restant modeste en mémoire. Les requêtes sur un nanocube sont extrêmement rapides, avec une moyenne de 800µs (0.8ms) et un maximum de 12ms.
      • Dans le cas de l'application de visualisation, ce sont surtout les requêtes sur les données spatiales qui nous intéressent. Dans l'étude sur le nanocube, les données spatiales utilisées sont la longitude et la latitude (utilisation d'un quadtree). Le nanocube décrit dans ce papier ne nous intéresse pas tel quel puisque les attributs et la "temporalité" ne nous sont d'aucune utilité et que les données spatiales sont en deux dimensions. Certains algorithmes pourront cependant être repris et adaptés pour la 3D, surtout étant donnée la rapidité des requêtes.
  • 6 :
    • Idée : au lieu de charger les données avec l'outil de zoom, il serait possible de les charger lors du clic sur un point (en chargeant complètement l'octant de ce point et les octants voisins par exemple)
    • Recherches sur les bases de données orientées graphes (neo4j) et les bases de données spatiales. Une base de données spatiale serait très utile avec un index 3D. Cela permettrait de trouver très facilement les points dans une sphère centrée sur un autre point (voir suggestion précédente). Problème : la gestion de la 3D dans les bases de données spatiales ne semble pas très courante. Voir : https://en.wikipedia.org/wiki/Spatial_database
    • Possibilité d'utiliser le code de Morton pour optimiser la recherche dans les octrees si cette architecture est choisie côté serveur. Assez bas niveau (manipulation de bits) mais très optimisé. Voir liens suivants :
    • En utilisant le code de Morton, il serait théoriquement assez facile de récupérer les points situés dans une sphère de rayon r autour d'un point centrale c. La requête vers l'API comprendrait donc seulement ces deux paramètres et non pas les 24 paramètres (8 points * 3 coordonnées) nécessaires à une boite englobante. L'API renverrait dans ce cas là les 8 octants englobant la sphère.
  • 7 :
    • Le couple Node.js - MongoDB me semble être une bonne solution côté serveur.
      • Si on stock un fichier par collection, il sera possible d'en ajouter approximativement 24 000 dans une base de données.
    • Réunion avec toutes les personnes concerné par le projet. Démo rapide à la bibliothèque puis discussion du futur de l'application en salle de réunion.
      • La taille du jeu de données sera de l'ordre du téraoctet. Celles-ci seront à ma disposition dans les prochains jours.
      • Je vais commencer à developper la partie serveur avec Node.js et MongoDB :
        • Je vais premièrement écrire un script permettant de charger des données sous la forme d'un octree dans la base de données.
        • Un deuxième script sera alors developpé pour parcourir l'octree depuis ses feuilles et générer les données dégradées qui seront chargées vers le client.
          • Les octrees intermédiaire (pas les feuilles) contiendront les données dégradés, qui seront des barycentre pondérés des données des feuilles.
      • Les scripts seront testés avec des fichiers peu conséquents pour vérifier qu'ils fonctionnent correctement avant de tenter de charger les gros jeux de données.
  • 8 :

    • Téléchargement de Node.js, npm, MongoDB et Robomongo (pour la visualisation de la BDD).

    • Mise en place de la base du projet, installation des dépendances avec npm (Express, Mongoose...) et création d'un README.
    • Test du bon fonctionnement du serveur et du routage et insertion d'un objet simple dans la base de données.
    • Ajout d'un vrai modèle d'octree. Celui-ci ne comporte pas de champ attribute pour simplifier les manipulations ni de champ fils : ce dernier n'est pas nécessaire puisque la recherche d'un octree s'effectuera en théorie à l'aide de l'id.
    • Recherche sur la lecture de fichier avec Node.js : module fs.
  • 9 :

    • Problème de PC après l'installation de mises à jour la veille -> je n'ai pu travailler sur l'application de la journée.
  • 10 :

    • Café à la coupole à 10h. Il n'y a pas eu de conférence aujourd'hui.
    • Comme l'ordinateur ne fonctionnait toujours pas à mon retour, André m'a prêté son Mac pour que je puisse tout de même aller sur internet.
    • Retour de ma machine à 16h15.
    • Explication du bug J_LEGACY par Jérôme.
  • 13 :
    • Arnaud est arrivé. J'ai de nouveau un poste de travail dans la bibliothèque.
    • La machine a été réinstallée suite au problème de jeudi. Réinstallation de Node.js, MongoDB, git, etc.
    • Focalisation sur la création des octrees côté serveur. Ces derniers ne sont pas encore gérés avec le code de Morton :
      • Création d'octree en fonction d'un tableau de points (coordonnées x, y et z).
      • Fonction d'ajout de barycentre sur l'octree pour la visualisation de données dégradées.
  • 14 :
    • Installation de grunt et jsdoc pour générer la documentation. Création du gruntfile. Dans le répertoire App_Server, dans une console :
      • grunt docClient -> génère la documentation client dans le dossier "doc" de App_Client
      • grunt docServer -> génère la documentation server dans le dossier "doc" de App_Server
      • grunt doc -> génère les deux documentations
    • Ajout d'un Id code de Morton à chaque octree.
    • Création de la fonction d'ajout d'octree (entier) à la base de données de façon récursive. Test de cette dernière.
    • Test de la lecture d'un fichier ligne par ligne : la lecture d'un fichier de 16mo est presque instantanée, vérifier avec le traitement des données.
  • 15 :
    • Refactoring de tout le code :
      • Suppression des dossiers controllers et models
      • Un fichier javascript par classe
    • Reader de fichier Trian. Ces derniers disposent d'une ligne header qui annonce le nombre d'éléments puis d'un élément par ligne. Les coordonnées sont séparées par " ".
      • Problème d'insertion dans la base de données : ligne 6010 du fichier liver.trian, seule la coordonnée x est présente.
      • L'insertion dans la base de données est fonctionnelle.
      • Pour plus tard : trouver comment notifier de l'ajout d'un octree complet. Je vois deux pistes pour l'instant :
        • Utiliser des promises et déclencher un signal lorsque tous les fils ont été insérés -> piste privilégiée pour l'instant.
        • Changement le mode d'insertion : commencer par insérer les fils et insérer leur père que lorsque ceux-ci ont bien été insérés dans la base de données.
  • 16 :
    • Test de requêtes (dans Robomongo) sur l'octree inséré dans la base de données :
    • data : liver.trian - 18010 points - 5329 documents en base - profondeur maximale des feuilles : 8 - limit : ceil(tab.length / 4096) = 5
      • Tous les documents : db.getCollection('octree').find({})
        • Performances : 0.000s en moyenne.
      • Recherche avec id : db.getCollection('octree').find({id : "id"}), avec id le code de Morton d'un octant.
        • Performances : entre 0.000s et 0.003s.
        • Les performances dépendent de la profondeur de l'octant recherché. Si on recherche "" (la racine, code vide), le temps moyen est de 0.003s. On atteint les 0.000s à partir du niveau 3 de l'arbre (code à partir de "000000000").
      • Recherche avec pattern : db.getCollection('octree').find({id : {$regex : /pattern/}})
        • Le pattern utilisé était de type /^id/, avec id le code de Morton d'un sous-octree. Renvoie cet octree ainsi que tous les autres commençant par ce code -> Renvoie donc cet octree et tous ses descendants.
        • Performances : entre 0.020s et 0.000s.
        • Comme pour la recherche avec id, les performances dépendent du niveau de recherche dans l'arbre.
          • Le maximum de 0.020s est atteint pour la requête de la racine et de tout ses fils. Pattern : /^/. Cette requête ne sera jamais utilisée en pratique puisque elle est similaire à la requête sur tous les documents, qui est instantanée.
          • À une profondeur de 1 dans l'arbre, les performances ne sont déjà plus que de 0.002s en moyenne et celles-ci continuent de s'améliorer au fur et à mesure que la profondeur augmente.
    • Ces performances sont très encourageantes. Les plus mauvaises requêtes sont celles qui concernent la racine et les sous-octrees de profondeur faible. Il y a de grandes chances qu'en pratique les requêtes se focalisent sur des octrees à des profondeurs élevées.
    • Il sera tout de même nécessaire de tester avec des données très importantes. De plus, les temps donnés ici ne prennent pas en compte le traitement des données côté serveur ni l'envoie de ces dernières vers le client.
    • Possible amélioration : pour l'instant tous les arbres crées sont insérés dans la base de données. Il serait possible de n'insérer que ceux qui contiennent des points pour alléger l'insertion dans la DB et éventuellement améliorer la recherche.
    • Intégration des fonctions de recherche d'octrees dans le code de l'application.
    • Je n'étais pas satisfait de l'organisation de mon code (surtout l'organisation du couple Express-Mongoose). Réécriture de certaines parties du code pour coller à certaines indications trouvées ici : http://stackoverflow.com/questions/22966854/structure-of-express-mongoose-app
  • 17 :
    • Journée de méthodologie de développement, organisée par xstra-dev :
      • J'ai pu assister à de nombreuses présentations : Documentation, TDD, IDE, Gestionnaire de tâches, Versioning et Mise en production.
      • En fin d'après-midi, un TP d'initiation à Git a été proposé.
      • J'avais déjà des connaissances sur certains des outils ou des méthodes présentés mais j'ai tout de même appris des choses intéréssantes, nottament sur des commandes avancés de git.
  • 20 :
    • Fin de réécriture de l'accès à la base de données à l'aide de Mongoose et Express. Le code est beaucoup plus propre.
    • L'api fonctionne maintenant correctement :
    • Ajout du script pour charger des données part, puisque ce seront des données de ce type que le serveur devra gérer.
    • Détection d'un soucis lors de la sauvegarde de l'octree dans la base de données. Cette sauvegarde prend trop de temps.
      • Le temps d'insertion semble être plus ou moins le même entre le fichier trian.liver et les fichier part. Pourtant les fichiers part insèrent beaucoup moins d'octrees dans la base. À confirmer...
    • La partie serveur est terminée pour le moment. Je vais maintenant me focaliser sur la liaison entre celle-ci et le côté client.
  • 21 :
    • Recherche d'une library permettant d'effectuer facilement des requêtes ajax. J'ai choisi Qwest : https://github.com/pyrsmk/qwest
    • Installation de Bower puis installation de Qwest à l'aide de ce dernier. Le projet devient un peu bordelique au niveau des librairies : certaines se trouvent dans App_Server et d'autres dans App_client, certaines sont installées à la main et d'autres avec des gestionnaires de packages, etc. J'essaierai de me pencher là-dessus un peu plus tard.
    • Après avoir bataillé un moment avec une erreur de Cross Domain, j'ai réussi à la résoudre en fusionnant la partie serveur et la partie client.
      • Cette erreur venait du fait que le client était lancé à la main sur un autre port que le serveur. C'est maintenant le serveur qui renvoie l'application. Ces derniers partagent donc le même port, il n'y a plus de soucis de Cross Domain.
    • La connexion entre le serveur et le client est donc maintenant effective et les requêtes fonctionnent.
  • 22 :
    • Installation de la library Q avec Bower. Intégration des promises côté client, entre autre pour les requêtes vers le serveur.
    • Repas du solstice à partir de midi.
    • Échec de la tentative de retour au travail.
  • 23 :
    • Recherche dans le code pour trouver l'endroit dans ajouter les points récupérer depuis le serveur. J'ai trouvé une piste et fait quelques modifications mais cela ne fonctionne toujours pas.
    • Préparation de la réunion infusion du vendredi, au cours de laquelle je présente Webstorm avec Thibault.
  • 24 :
    • Réunion infusion : J'ai présenté l'IDE webstorm avec Thibault. Une présentation sur Webpack et ESLinter a aussi été donnée.
    • J'ai enfin déterminé comment afficher des points récupérés avec le serveur. Mes modifications ne sont pas propres du tout et il faudra améliorer ça plus tard (en discuter avec Jérôme notamment).
    • J'en ai profité pour ajouter les promises au fichier reader et ai corrigé un gros soucis dans le reader des part.
    • J'ai aussi ajouté une fonction permettant de lire tous les fichiers contenu dans un dossier.
      • La création d'un octree avec tous les fichiers part ne fonctionne pas : FATAL ERROR non déterminée, probablement un problème de mémoire.
      • Il faudra faire plus de tests lundi. Je devrai aussi améliorer l'insertion, qui est trop longue pour l'instant.
      • Une idée à tester serait de mettre tous les futurs documents dans un tableau et les insérer d'un coup, au lieu de les insérer de façon récursive.
  • 27 :
    • J'ai passé la journée à faire fonctionner l'insertion de tout un répertoire dans la base Mongo :
      • J'ai dû créer un tableau des différents documents à insérer (une sorte d'applatissement de l'octree).
        • Cela me permet de gérer l'insertion au compte-gouttes. Je travaille pour l'instant avec 200 insertions simultanées.
      • C'est assez lent, je vais peut-être devoir me passer de mongoose pour accélerer l'insertion -> utilisation des drivers Mongo.
      • Contrairement à l'insertion dans la base de données, la lecture et le traitement de celles-ci est extrêmement rapide.
      • J'ai aussi accéleré l'insertion en base de données et réduit la charge des données dans la base :
        • Seules les feuilles sont insérées avec leurs points (pas les noeuds intermédiaires ni la racine donc).
        • Les feuilles qui ne disposent pas de points ne sont plus insérées.
        • Pour l'instant, les noeuds qui ne sont pas des feuilles sont toujours insérés dans la base de données. Ces derniers ont peu d'intérêt, je vais peut-être me décider à les supprimer. Je vais tout de même faire des tests avant.
      • Comme il y a moins de données dans la base, le temps de traitement par le serveur est plus important. Je dois encore vérifier que les performances des requêtes depuis le serveur sont acceptables.
    • Jérôme m'a expliqué comment fonctionne l'affichage des données en détail. Je n'avais finalement pas fait n'importe quoi lorsque j'ai affiché les données.
    • Je testerai demain le chargement de toutes les données part depuis la base de données pour tester la réactivité de l'application.
  • 28 :
    • Test d'insertion de tous les part end :
      • 10 documents à la fois, avec les noeuds intermédiaires: 314s - 17431 / 17433 documents insérés
      • 10 documents à la fois, sans les noeuds intermédiaires : 317 - 15252 / 17433 documents insérés
      • 50 documents à la fois, avec les noeuds intermédiaires : 326s - 17431 / 17433 documents insérés
      • 50 documents à la fois, sans les noeuds intermédiaires : - 328s 15252 / 17433 documents insérés
      • 200 documents à la fois, avec les noeuds intermédiaires : 347s - 17431 / 17433 documents insérés
      • 200 documents à la fois, sans les noeuds intermédiaires : 339s - 15252 / 17433 documents insérés
      • 500 documents à la fois, avec les noeuds intermédiaires : 377s - 17431 / 17433 documents insérés
      • 500 documents à la fois, sans les noeuds intermédiaires : 380s - 15252 / 17433 documents insérés
      • 1000 documents à la fois, avec les noeuds intermédiaires : FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory
      • 1000 documents à la fois, sans les noeuds intermédiaires : FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory
    • J'ai commencé les tests à 200 documents puis ai augmenté la charge. Comme il y avait une augmentation du temps d'insertion, j'ai tenté avec des valeurs inférieurs, d'abord 50 puis 10 documents insérés.
    • Nous remarquons qu'il ne sert à rien de chercher une insertion simultanée importante. Une insertion de peu d'éléments à la fois est plus rapide. De plus, cela permet d'éviter une erreur lors d'un trop grand nombre d'insertion.
    • L'insertion ou non des noeuds intermédiaire n'impacte pas beaucoup les performances. Je ne vais peut-être pas les garder en base.
    • Après avoir effectué quelques tests :
      • La requête sur toutes les données du serveur ne sont pas possible : pas assez de mémoire (memory leak ?)
      • Il faudra vérifier avec les données de test combien il est nécessaire d'envoyer de points à chaque fois, ou faire plusieurs requêtes pour toutes les récupérer.
    • J'ai rajouté une fonction pour tester l'affichage des barycentres :
      • Ce n'est qu'à moitié concluant : la forme affichée est reconnaissable mais trop prévisible. En effet, comme les feuilles de l'octree sont assez homogènes, les barycentres seront très centrés.
      • Il serait possible d'augmenter la profondeur de l'octree pour limiter cet effet de découpage, mais les performances risquent d'être impactés.
      • Le mieux serait de trouver un autre moyen pour calculer des données dégradées.
  • 29 :
    • Correction de l'affichage des barycentres : tous les barycentres des feuilles n'étaient pas affichés.
    • Réunion avec André :
      • Exposition des problèmes auxquels je suis confronté :
        • Insertion trop lente dans la base de données.
        • Affichage de barycentres trop grossier -> décision prise de descendre en profondeur dans l'arbre, comme exposé plus haut. Tests en cours.
        • Requêtes sur de gros volume de données : out of memory -> faire plusieurs petite requêtes pour remplacer une grosse ? Est-il possible de régler ce problème de mémoire ?
      • Je ne m'occupe pas du serveur pour l'instant : je vais essayer d'avoir une version fonctionnelle sur ma machine avant d'essayer de travailler sur de plus gros volumes de données.
      • Je vais travailler aujourd'hui sur les requêtes dynamiques des données lors de la navigation dans le cube de visualisation.
    • Je n'ai finalement pas travaillé sur les requêtes dynamiques en elles-même mais sur l'optimisation des requêtes, qui étaient encore beaucoup trop longues :
      • Après une après-midi de recherche et plusieurs pistes que je n'ai pas gardé (agréggation de documents par exemple), j'ai enfin compris pourquoi mes requêtes étaient si lentes !
      • Mongoose (rappel : Mongoose = wrapper MongoDB pour Node.js) wrap les documents récupérés avec des méthodes save, etc. Cela ralenti très grandement les requêtes et fait exploser la mémoire pour un grand nombre de documents !
      • La méthode lean() permet de récupérer les documents tels qu'ils sont insérés dans la base de données.
      • Pour les 2 millions de points dans la base :
        • Sans lean() : FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory après +- 30 secondes
        • Avec lean() : 5 secondes
  • 30 :
    • Finalisation des requêtes côté serveur.
      • Ajout de la methode lean() à toutes celles-ci sauf getOctree().
      • Renommage de certaines fonctions pour qu'elles soient plus représentatives de ce qu'elles font : getAllOctrees() -> getAllPoints() par exemple.
      • Ajout de timers pour avoir un retour sur les temps d'exécution des requêtes et sur les temps d'envoi des données.
      • Finalement, la requête sur tous les points de la base de données prends 5 secondes et l'envoi des données vers le client prend 15 secondes. Il est peut-être encore possible d'optimiser l'envoi des données.
    • J'ai commenté le code des requêtes côté serveur. Ce dernier ne sera normalement plus modifié, sauf pour des corrections de bugs ou des optimisations.
    • Monsieur Tellier est venu à l'observatoire pour voir comment se passe mon stage.
      • Je lui ai rapidement expliqué ce que je fais et les objectifs à atteindre.

Juillet

  • 1 :
    • Séminaire "Dust evolution in Milky Way PDRs and Andromeda" - Heddy Arab
    • Nombreuses recherches sur la gestion des caméras. Jérôme m'a expliqué en détails comment ces dernières fonctionnent.
    • Ajout de la récupération des coordonnées en fonction de la caméra.
      • Les caméras Rotating et Global ne sont pas gérées pour l'instant.
    • Début de l'ajout de la fonction de repérage dans l'octree : classe Octree.js. Je la terminerai lundi et la lierai alors à la base de données.
  • 4 :
    • J'ai terminé la fonction de repérage de l'octree et l'ai finalement inséré dans la classe util.js.
    • Le chargement des données est fonctionnel mais n'est pour l'instant pas agréable à utiliser : les données sont chargées lorsque l'on quitte un octant pour rentrer dans un autre.
      • On arrive donc dans un octant vide, puis les données sont chargées.
      • Je vais donc devoir explorer certaines idées pour pouvoir charger les données avant de sortir de l'octant, lorsque l'utilisateur se rapproche d'un de ses bords.
    • Je suis aussi en train de tester une façon pour (peut-être) accélerer les requêtes :
      • J'ai remarqué qu'une requête sur un octant d'un octree est plus de 8 fois plus rapide qu'une requête sur tout un octree.
      • Je vais donc tester les performances de 8 requêtes sur les octants d'un octree pour remplacer une requête sur tout l'octree.
  • 5 :
    • Finalemement, les performances des requêtes sur les 8 octants ne sont pas significativement meilleures qu'une requête sur l'octree entier. Cela ne fait que surcharger le serveur avec des requêtes inutiles... Je vais donc laisser cette piste de côté.
      • Pour l'instant, le temps de chargement d'un octant de niveau 1 du nuage de 2 millions de points est de l'ordre de 2 secondes. C'est encore un peu long.
    • J'ai aussi essayé d'augmenter la rapidité des requêtes sur la base de données en utilisant les drivers Mongoose :
      • Ces derniers ne me permettent aucun gain de performance. L'usage de la méthode lean() est suffisant.
    • Je vais modifier le chargement des données pour charger tous les octrees voisins de l'octree courant.
      • Pour cela je vais devoir reconstruire l'octree à l'aide de la base de données (en utilisant les id de tous les octants).
      • L'octree reconstruit sera gardé en cache par l'application, pour ne pas avoir à le reconstruire à chaque fois.
    • J'ai trouvé comment accélérer les requêtes en agrégeant les résultats dans un seul document (méthode aggregate) :
      • 380ms en moyenne - 172549 documents comprenant chacun un id
      • 260ms en moyenne - 1 document comprenant un tableau de 172549 id
      • Quand j'aurais fini la reconstruction de l'octree, je testerai des requêtes aggrégeant les points. J'espère voir un gain de performance au moins similaire !
  • 6 :
    • Réunion avec André, Jérôme et Thibault. Nous avons discuté de l'avancement du projet ainsi que des prochains objectifs :
      • Je vais tout d'abord terminer la construction de l'octree, afin de précharger les octants voisins de l'octant courant.
      • Il faudrait aussi que j'ajoute les paramètres des points à la base de données, pour tester les performances des requêtes sur une base complètement remplie.
      • J'ajouterai aussi les boites englobantes des octants lorsqu'ils seront chargés, pour pouvoir effectuer facilement des tests et visualiser les bornes.
      • Le serveur ne dispose que de 9Go de RAM. Il y aura probablement des soucis lors du chargement de tous les fichiers dans la base de données puisque je dois stocker tous les points en mémoire pour pouvoir construire l'octree.
        • Une solution serait de construire des sous-octrees (1/8ème de la racine par exemple) puis de les rassembler une fois tous construit. Cela consommerait moins de mémoire mais prendrait plus de temps, puisqu'il faudra parcourir tous les fichiers plusieurs fois (8 dans ce cas).
    • J'ai eu des soucis pour écrire la fonction de création de la représentation de l'octree à partir de la base de données (pour déterminer les voisins d'un octant). Elle est maintenant terminée.
    • J'ai commencé à écrire la fonction pour déterminer les voisins d'un octant. Je n'ai pas pu la terminer et continuerai cela demain.
  • 7 :
    • La fonction pour déterminer les voisins d'un octant est terminée.
    • Modification de toutes les requêtes côté serveur et des routes : ajout de promises à la place des callbacks.
    • Ajout de l'aggrégation pour la requête getBarycentre : on passe de 620ms à 460ms.
    • J'ai tenté d'ajouter l'aggrégation sur les requêtes sur les points : ce n'est pas concluant, les requêtes étant moins performantes.
      • Il faudra continuer à explorer cette piste, mes requêtes étaient peut-être inutilement compliquées.
    • La récupération des points des octants voisins à l'octant courant ne fonctionne toujours pas. J'ai un dernier soucis à corriger et cela devrait être bon.
  • 8 :
    • L'affichage des octans voisins fonctionne correctement !
    • Je charge les 26 octans voisins de l'octant dans lequel la caméra se trouve en +/- une seconde. Cela pourra être optimisé par la suite en ne chargeant que les voisins qui n'ont pas encore été chargés.
    • J'ai découvert un bug qui se produit lorsque deux requêtes getNeighbours() sont appelées très rapidement à la suite l'une de l'autre.
      • Ce bug entraîne une disparition de certains points alors qu'ils sont encore dans le champs de la caméra.
      • Pour l'instant, j'empêche au navigateur de faire deux requêtes simultanées. J'ai tout de même réussi à reproduire le problème, mais beaucoup plus difficilement.
      • Il faudra probablement trouver une solution plus propre.
    • Recherche d'un souci de performance avec Thibault :
      • Nous soupçonnons les évènements de l'interface d'être les responsables. Plus d'investigations dès lundi matin.
  • 11 :
    • Le problème de performance ne vient pas de l'interface mais du ralentissement causé par les requêtes multiples vers le serveur.
    • J'ai ajouté un middleware pour zipper les données avant de les envoyer.
      • Exemple : sans zip : 11.9Mo - avec zip : 3.6Mo
      • La réception des données est légèrement accélerée mais n'est pas proportionelle à la compression. La compression/décompression prends en effet beaucoup de temps.
    • J'ai aussi essayé de réceptionner les données à l'aide d'un web worker. Cela ne change rien aux FPS.
    • Il faudra donc réduire les data échangées avec le serveur, et donc le nombre de points à renvoyer.
    • Je vois deux solutions simples à mettre en place :
      • Envoyer la dernière position au serveur en plus de la position courante, pour pouvoir déterminer quels octants sont déjà stockés côté client.
      • Déterminer directement côté client quels octants sont nécessaires. Cela ferait plus de requêtes mais celles-ci seraient plus rapide.
  • 12 :
    • J'ai choisi de déterminer côté client quels sont les octants que je dois récupérer depuis le serveur. Pour ce faire :
      • Je dois envoyer la représentation de l'octree générée côté serveur au client. Cette requête n'est effectuée qu'une seule fois, lorsque la vue est chargée.
        • J'ai eu un soucis de référence circulaire lors du passage de la représentation de l'octree en json (pour l'envoie au client). Pour chaque noeud de l'octree, j'avais une référence vers les fils et le père. J'ai fait une fonction supprimant les références vers les pères (elles ne sont de toute façon pas nécessaire côté client).
      • J'ai réécrit les fonctions de parcours de la représentation d'octree côté client.
    • Finalement, il ne me reste plus qu'à gérer les codes des octants : ne faire des requètes que sur les octants que je n'ai pas encore chargés.
  • 13 :
    • Le chargement des données avec mémorisation des octants voisins est maintenant fonctionnel.
    • J'ai fait des comparaisons entre l'envoie des données avec et sans la compression (au cas où les temps de compression et décompression sont plus importants que le temps de transfert des données) :
      • Finalement, la compression permet de gagner entre 100ms et 500ms par requète, ce qui n'est pas négligeable.
      • Il sera peut-être possible d'augmenter encore les performances des requêtes en changeant la stratégie ou le taux de compression. Pour l'instant, ces paramètres sont ceux par défaut du module compression d'express.
    • Découverte d'un bug étrange qui concerne le chargement de la représentation de l'octree lorsque l'application est lancée :
      • La requête prends 4 secondes à être effectuée la première fois.
      • À chaque fois que l'application est relancée, et donc que la requête est rééffectuée, celle-ci prends un peu plus de temps que la fois précédente (+-300ms).
      • Que le serveur soit relancé ou que la page du navigateur soit actualisée, la requête prendra toujours un peu plus longtemps (et c'est ce point qui est le plus bizarre).
      • La seule manière de réinitialiser la requête est de fermer complètement Firefox.
      • C'est un bug plutôt génant et je n'ai absolument aucune idée de la manière de régler ça. Il est possible que les autres requêtes soient dans le même cas et que je ne l'ai pas remarqué. J'essaierai de faire attention à ça.
  • 18 :
    • J'ai changé la construction de la représentation de l'octree, pour améliorer les performances de la requête :
      • Il n'est pas nécessaire de renvoyer la représentation de l'octree complet (qui pèse 34mo non compressée) puisque on ne descendra jamais très loin en profondeur (maximum de 3 pour le moment). Il est ainsi possible d'envoyer la représentation tronquée au niveau 3.
      • J'ai d'abord tenté de copier la représentation de l'octree et de tronquer les niveaux supérieurs à 3. Cela n'est pas assez rapide et implique beaucoup de calculs.
      • J'ai donc décidé de ne construire la représentation que jusqu'au niveau 3. Finalement :
        • On passe de 5000ms à 500ms lors de la première requête et de +-5000ms à 5ms lors des suivantes (la représentation étant en cache).
        • On passe de 1.9mo à 5.7ko en envoyant la représentation tronquée (compressée).
      • J'ai accéléré l'insertion dans la base de données en utilisant les drivers natifs de mongoDB. J'ai aussi fait des tests en ajoutant 3 paramètres par point. Performances pour l'insertion des 174201 points dans la BDD :
        • Sans les drivers et sans les paramètres : 420s
        • Sans les drivers et avec les paramètres : 485s
        • Avec les drivers et sans les paramètres : 13s
        • Avec les drivers et avec les paramètres : 17s
      • La différence est énorme ! Il sera peut-être possible d'insérer les 300go de données dans la BDD en moins d'une semaine !
      • J'ai aussi effectué des tests de lecture des points, avec et sans les paramètres :
        • Sans les paramètres : 3232ms
        • Avec les paramètres : 6000ms
      • Il y a une grosse différence de performances. Celle-ci devrait être beaucoup moins perceptible pour peu de points. De plus les paramètres ne seront normalement pas envoyés au client sans que ce dernier n'en fasse la requête.
  • 19 :
    • Correction d'un bug gênant qui empêchait l'affichage de tous les octants autour de l'octant courant lorsque l'utilisateur se déplace de plusieurs octants pendant que des requêtes sont effectuées :
      • Je compare maintenant directement les codes des octants à afficher avec les codes des octants déjà chargés, et non plus avec les codes du dernier octant traversé.
    • Réunion avec André :
      • Présentation des modifications que Thibault et moi avons effectué la semaine dernière.
      • Les grosses données de test ne sont pas encore chargées sur le serveur. Ce sera normalement fait pendant cette semaine.
      • Je travaillerai demain sur le déploiement de l'application sur le serveur. Je testerai les performances avec les données part_end.
    • Nouvelle visite du planetarium.
  • 20 :
    • Installation de node.js et npm sur le serveur :
    • Installation de mongoDB :
      • sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv EA312927
      • echo "deb http://repo.mongodb.org/apt/ubuntu trusty/mongodb-org/3.2 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-3.2.list
      • sudo apt-get update
      • sudo apt-get install mongodb-org
    • Installation de git :
      • sudo apt-get install git
    • Installation des modules avec npm. Dans App_Server :
      • npm install
    • Populate la base de données :
      • node app.js populate
    • Lancement de l'application :
      • node app.js
      • Adresse pour tester : 130.79.129.206:8080
    • Tout a l'air de fonctionner correctement mais c'est très lent ! 4to de données sont chargés en ce moment même ce qui ralenti extrêmement l'application. Je ferai de nouveaux tests lorsque les données seront chargées.
  • 21 :
    • Correction d'un bug qui permettait l'insertion de feuilles sans point et de barycentres null.
    • Les données chargées depuis le serveur ne seront maintenant chargées que si l'utilisateur clique sur le bouton "load" dans l'onglet serveur.
    • Changement dans l'affichage des données dégradées :
      • Les barycentres des noeuds ne sont plus calculés.
      • Les données dégradées sont maintenant représentées par :
        • Pour les feuilles, un point pris au hasard dans tous les points des feuilles.
        • Pour les noeuds, un point pris au hasard dans les données dégradées des noeuds fils.
    • Affichage d'un spinner pour notifier l'utilisateur d'un chargement des données.
  • 22 :
    • Correction d'un bug empêchant l'affichage des données dégradées.
    • Correction d'un bug dans le calcul du poids des données dégradées pour les noeuds de l'octree.
    • J'ai récupéré le plus petit des fichiers du jeu de données présent sur le serveur, pour tester l'ajout à la base de données avec mon script.
      • L'insertion dans la base de données est impossible : les documents font une taille de plus de 16mo, qui est la limite des documents BSON à insérer dans la base mongo.
      • Les plus de 16mo sont atteints même si j'augmente la profondeur de l'arbre à plus de 100 (ce qui laisse tout de même 8^100 octants). Ce sera de toute façon impossible d'aller jusque là en pratique.
      • Le script d'insertion à utiliser n'est donc pas un script part. J'ai envoyé un mail à André pour lui demander plus d'information sur les données.
    • En attendant de nouvelles informations, j'ai commencé à travailler sur mon rapport de stage.
  • 25 :
    • Le script permettant de traiter les données du serveur est Ramses et non Part !
      • J'ai donc ajouté le script Ramses au serveur. Ce dernier est fonctionnel et permet de traiter correctement les données.
      • J'ai aussi ajouté un traitement des arguments en ligne de commande :
      • Il est maintenant possible de spécifier le script avec lequel on veut traiter les données ainsi que le path de celles-ci. Par exemple :
        • node app.js Ramses=./RandomDirectory/dataDirectory
    • J'ai tenté d'ajouter les données des 9 premiers fichiers dans la base de données.
      • J'ai des erreurs de segmentation côté serveur que je n'ai pas sur ma machine. J'ai donc importé quelques fichiers sur ma machine pour faire des tests d'insertion, en attendant de trouver la cause des erreurs de segmentation.
    • Côté client, l'insertion des 4 premiers fichiers dure +-4 minutes, pour un montant de 3go de données.
    • J'ai plusieurs erreurs lors du chargement et de l'afficahge des données dans le navigateur...
  • 26 :
    • Ajout de variables globales côté serveur (fichier app.js) pour manipuler facilement les tailles min et max des octree et octree-rep.
    • Ajout d'une taille minimale lors de la création d'un octree, pour avoir toujours une représentation d'octree à la bonne taille. Taille de 4 pour le moment.
      • Les données dégradées pourront maintenant être nulles. Il faudra vérifier cela côté client.
    • Réunion avec André :
      • Je vais continuer à travailler sur l'affichage des 3go de données.
      • Une fois l'affichage côté client fonctionnel, je travaillerai sur le chargement des données côté serveur :
        • Il ne sera pas possible de charger les 4to de données en RAM. La solution qui me semble la plus facile à mettre en place et la moins coûteuse en temps est la création d'un octree avec le File System de la machine (arborescence de fichiers). L'octree serait créé de la même manière que dans l'application, en générant de manière dynamique les fichiers nécessaires. Une fois toutes les données parcourues, il suffira d'ajouter les fichiers générés à la base mongo, un fichier représentant un document.
    • J'ai de gros soucis pour la récupération de la représentation de l'octree et des données dégradées depuis le serveur. Ces données sont trop importantes, même avec seulement 3go de data. Je ne sais pas encore de quelle façon résoudre cela.
  • 27 :
    • Après une nuit d'intense réflexion, je pense avoir trouvé des pistes à explorer aujourd'hui pour régler les problèmes de l'affichage côté client :
      • Pour la représentation de l'octree : comme les données en base ont maintenant une profondeur minimum, il est possible de calculer côté client la représentation de l'octree, jusqu'à cette profondeur. Cela permettra d'éviter des transferts de données trop importants.
      • Pour les données dégradées : il n'est plus possible d'afficher celles des feuilles de l'octree. Il faut choisir d'afficher une certaine profondeur dans l'arbre, qui permettra d'afficher entre 100k et 200k points au total, lorsque l'on sort du cube. Cela permettra d'avoir une vision globale de la forme des points sans en charger de trop.
    • La représentation de l'octree côté client est fonctionnelle ! La construction de l'octree prends 2s, pour une profondeur de 7. À partir d'une profondeur de 8, le navigateur plante : out of mermory exception. Il faudra déterminer s'il est nécessaire d'aller au-delà de 8 de profondeur et de trouver une autre solution si c'est le cas.
    • La réception des données dégradées fonctionne elle aussi à nouveau. Pour l'instant, les données d'une profondeur de 7 sont affichées. il sera possible d'adapter la profondeur en fonction des résultats et des performances lorsque l'on aura plus de données. La profondeur finale sera probablement comprise entre 6 et 8.
  • 28 :
    • Mises au point diverses côté client. Le slider de la taille des points n'est plus une fonction linéaire, permettant ainsi d'ajuster facilement la taille pour de très gros ou de très petits volumes de données.
    • Il ne restera plus que de petits détails à modifier côté client, comme le mode de chargement des données : en temps réel ou lorsque la caméra s'arrête (éventullement laisser le choix à l'utilisateur).
    • J'ai commencé à travailler sur l'octree généré avec le file system.
  • 29 :
    • Recherche d'informations sur la manipulation du FS en node.js.
    • Installation de q-IO pour faciliter la manipulation des fichiers.
    • Début de développement de l'algorithme de création de l'octree.

Août

  • 1 :
    • Travail sur le script de création de l'octree.
    • Réunion avec André, Jérôme, Thibault et Nicolas, pour montrer les avancés dans le projet.
  • 2 :
    • J'ai terminé le script de création de l'octree dans le file system.
    • Ce dernier est vraiment vraiment beaucoup trop lent. Je vais essayer de l'optimiser, mais les lectures/écritures sur le disque dur ne me permettront probablement pas des performances incroyables...
  • 3 :
    • J'ai effectué un nouveau script de création d'octree, beaucoup plus rapide ! Il n'est pas encore entièrement fini et ne fonctionne que pour un seul fichier à la fois.
      • La création de l'octree est faite en mémoire puis les fichiers sont écrit d'un seul coup. Cela permet d'éviter trop de lectures et écritures puisque les points ne sont pas ajoutés un par un.
      • Le script ne fonctionne que pour le premier fichier car il est nécessaire de prendre en compte les fichiers déjà écrit dans le fs pour les fichiers suivant. Je n'ai pas encore effectué cette partie.
      • .
    • .
  • 4 :
  • 5 :

Sauvegardes

  • à définir au cas par cas suivant le sujet du stage

Liens

  • ...

Versions testables

Testé sur ...

Documentation

Informations/travaux divers

  • ...

Travail post stage éventuel

Liste des améliorations à envisager

Bugs connus

*

Topic attachments
I Attachment Action Size Date Who Comment
Unknown file formatodp Pre769sentation_Nicolas_Adam.odp manage 5007.6 K 2016-11-03 - 09:55 AndreSchaaff  
PDFpdf Pre769sentation_Nicolas_Adam.pdf manage 2619.4 K 2016-11-03 - 09:57 AndreSchaaff  
PDFpdf Rapport_Nicolas_Adam.pdf manage 2769.3 K 2016-11-03 - 09:57 AndreSchaaff  
PDFpdf nanocubes_paper.pdf manage 10210.7 K 2016-06-03 - 14:27 UnknownUser  
Topic revision: r61 - 2016-11-03 - AndreSchaaff
 
This site is powered by the TWiki collaboration platform Powered by PerlCopyright © 2008-2024 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback