Envoyé par : Raphael
Date : 02/02/2007 15:19
Bonjour, mon programme est un visualiseur de base de données SQLite3. Au démarrage, je charge les informations contenues dans ma base de données, ce sont des infos sur des cartes à jouer telles que : Nom, description, code, rareté,... rien de bien extraordinaire.
Pour l'instant, j'ai quasiment tout codé et ma base contenait 17 cartes (juste pour vérifier la validité de mon code) et mon logiciel s'ouvrait instantanément, mais je me suis dit qu'à terme, le chargement devrait être plus long car il y a environ 3000 cartes dans le jeu.
Je me suis donc lancé dans dans une petite progressbar qui augmente au fur et à mesure que je charge mes données dans un tableau, et ça marche, enfin presque...
En effet, j'ai gonflé artificiellement ma base de données avec un script automatique pour rentrer 400 cartes... et maintenant quand je lance mon programme, il est beaucoup plus long au démarrage, rien ne s'affiche, puis paf, toute mon interface s'affiche, ma progressbar est déjà remplie et tout marche. Pas cool... l'intérêt d'une progressbar est de faire patienter durant le chargement, et là, ma fenêtre ne s'affiche pas avant chargement totale de mes données, c'est donc râté.
Comment faire pour afficher ma fenêtre puis charger mes données ensuite afin de voir ce chargement dans ma progressbar ? Voici une version allégé de mon code :
var cards = new Array(); window.onload = function() { cards = getAllCards(); }
Et dans getAllCards() j'ai une boucle qui remplie mon tableau et en même temps incrémente ma progressbar.
Je voudrais inclure un Splash screen à mon application mais lorsque je fais un window.open dans mon "onload" et bien mon splash screen s'affiche après ma fenêtre de base, ce n'est donc plus un splash screen... comment résoudre ce problème ?
Avec seulement 17 cartes, mon logiciel prenait 14,5 Mo de RAM... Avec 400 cartes, il passe à 38,8 Mo !!! Et je trouve ça énorme car à terme, il y aura environ 3000 cartes ! un rapide calcul me fait penser que la mémoire pourrait alors monter à 240 Mo !!! o.O . En fait je charge mes cartes dans un tableau afin d'y avoir rapidement accès pour mes filtres en temps réel... mais je ne pensais pas que ça prendrait tant de mémoire que ça... Est-ce moi qui ne sait pas coder ? Dois-je détruire mes variables désuètes ? Dois-je utiliser un autre procédé ? Bref, je ne sais pas trop quoi faire...
J'espère que quelqu'un pourra quand même me venir en aide, merci d'avance =)
Envoyé par : thefab
Date : 02/02/2007 15:45
Envoyé par : chBok
Date : 02/02/2007 16:10
1. Ce problème de rafraichissement de l'UI pendant un long script me semble avoir déjà été abordé. Ne fallait-il pas se servir de setTimeout() artificiels pour y parvenir ?
Envoyé par : Raphael
Date : 02/02/2007 17:48
thefab > Concernant mes 3000 cartes, je les mets en mémoire car je voulais avant tout une interface réactive durant le filtre de mes cartes en temps réel, et je pensais que le meilleur moyen était de tout mettre en mémoire et de parcourir tout mon tableau à chaque modif. de mon filtre en application mes condition IF, afin d'afficher ou non la carte... Je pensais que ce serait le mieux... Mais pensez-vous qu'il serait préférable d'utiliser à chaque fois une requête SQL plutôt ?
chBok > J'avais déjà lu ce genre de problème mais je n'avais pas percuté que ça touchait ma situation... Effectivement, il faudrait donc une "astuce" pour parvenir à ce résultat apparemment.
Je vais essayer différentes techniques pour voir ce que ça donne et je vous tiens au courant.
Envoyé par : teddyber
Date : 02/02/2007 17:54
pour ton histoire de filtres et la question de savoir s'il est pertinent de charger les cartes en mémoire, voici mon cas : je développe une appli qui propose une textbox qui à chaque input fait une requète à une base SQLite. la requète+le vidage du tree qui affiche+le remplissage du tree est quasi-instantané (j'ai aujourd'hui 300 élements dans la base)
Envoyé par : Raphael
Date : 02/02/2007 18:10
Bah ce que tu fais, c'est donc exactement l'alternative de ce que je fais ! Et tu me dis donc que c'est instantané pour 300 éléments ? Utilises-tu "createElement" aussi pour ton tree ?
Il faudrait peut-être donc que j'essaie de changer mon fusil d'épaule et miser sur la rapidité de la requête SQLite plutôt que le parcours de mon tableau mis en mémoire tu penses ?
PS : Je viens de tenter un setTimeout qui "résoud" 1 problème : maintenant, l'interface s'affiche bien... mais bizarrement, ma progressbar passe directement à 100 % et j'ai du mal à croire que ce soit parce que c'est instantanné puisque ça met un peu de temps. Pourtant je devrais le voir se remplir, voici mon code :
function getAllCards() { var Nb_Cards_loaded = 0; var data = ycd.get("...REQUETE SQL...") while (data.executeStep()) { results.push("...MES DONNEES...") Nb_Cards_loaded++; $("loaderbar").value = Math.round(Nb_Cards_loaded*100/Nb_Cards); } }
Et ce code fonctionne bien puisqu'en mettant un alert() dans ma boucle pour faire afficher le %... ben j'ai bien le bon chiffre et en plus ma progressbar se met correctement à jour dans mon interface.
C'est bizarre non ? Il n'est pas pas question de requête SQL à interrompre non ? C'est juste une boucle... Comment ça se fait que la boucle tourne sans même avoir le temps de mettre à jour ma Progressbar ?
Envoyé par : teddyber
Date : 02/02/2007 18:16
euh oui j'use (et j'abuse) de createElement
, de setAttribute
et autres appendChild
en tout cas ce qui prends du temps chez moi c'est clairement la manipulation du DOM et pas la requète à SQLite (mesuré à coup de console.time
et console.timeEnd
dans firebug)
Envoyé par : Raphael
Date : 02/02/2007 18:30
Tiens mais alors ce que tu me dis est très étrange ! Je viens de tester un truc : J'ai désactivé mon système de filtre... en gros, tous mes IF et mes condition pour ne garder que :
Et bien : AUCUN CHANGEMENT ! La vitesse est la-même ! Et quand je rafraichis ( = Je vide mon listbox pour le reremplir avec les mêmes éléments) et bien je ne vois aucune différence ce qui veut dire que le vidage/peuplage est INSTANTANE !
Mais alors ça voudrait dire que c'est ma requête qui bouffe tout ce temps ! o.O
Il lui faut environ 3/4 seconde pour charger mes données, c'est-à-dire 400 éléments. __Est-ce que ce sont mes réglages SQLite3 qui seraient mauvais ? J'utilise Xulrunner 1.9a1... et j'ai un PIV 2.4 + 1 Go de RAM sous Ubuntu Edgy Eft.
Il me semble avoir lu sur ce forum un paramétrage à faire et qui change tout : genre de 10 sec à 1 sec ! Je vais rechercher ce topic...
Voici la requête et mon remplissage de tableau si ça peut aider quelqu'un à comprendre pour cela prend tant de temps :
var data = ycd.get("SELECT Card_ID, ID_Card, Group_ID, cards.Name as Name, Description, cards.Reference as Reference, Level, Atk, Def, Code, Monster_Attribute_ID, Monster_Type_ID, Monster_Subtype_ID, Type_ID, cards.Extension_ID as Extension_ID, Country_ID, Language_ID, Model_ID, extensions.Name as Extension_Name, extensions.Reference as Extension_Ref, Release_Date FROM cards LEFT JOIN extensions USING(Extension_ID) ORDER BY cards.Reference ASC"); while (data.executeStep()) { results.push({"Card_ID" : data.getInt32(0), "ID_Card" : data.getInt32(1), "Group_ID" : data.getInt32(2), "Restricts" : getRestricts(data.getInt32(2),data.getInt32(14)), "Reference" : data.getString(5), "Name" : {"Source": data.getString(3), "Locale": getTranslation('local_cards','Name','ID_Card',data.getInt32(1),UserLanguageID)}, "Extension" : {"ID": data.getInt32(14), "Country_ID": data.getInt32(15), "Language_ID": data.getInt32(16), "Model_ID": data.getInt32(17), "Name": data.getString(18), "Reference": data.getString(19), "Released": data.getString(20)}, "Type" : getCardType(data.getInt32(13),data.getInt32(16)), "Subtype" : {"ID": data.getInt32(13), "Name": getTranslation('types','Name','Type_ID',data.getInt32(13),data.getInt32(16)), "Locale": getTranslation('types','Name','Type_ID',data.getInt32(13),UserLanguageID)}, "Monster_Attribute" : {"ID": data.getInt32(10), "Name": getTranslation('monster_attributes','Name','Monster_Attribute_ID',data.getInt32(10),data.getInt32(16)), "Locale": getTranslation('monster_attributes','Name','Monster_Attribute_ID',data.getInt32(10),UserLanguageID)}, "Monster_Type" : {"ID": data.getInt32(11), "Name": getTranslation('monster_types','Name','Monster_Type_ID',data.getInt32(11),data.getInt32(16)), "Locale": getTranslation('monster_types','Name','Monster_Type_ID',data.getInt32(11),UserLanguageID)}, "Monster_Subtype" : {"ID": data.getInt32(12), "Name": getTranslation('monster_subtypes','Name','Monster_Subtype_ID',data.getInt32(12),data.getInt32(16)), "Locale": getTranslation('monster_subtypes','Name','Monster_Subtype_ID',data.getInt32(12),UserLanguageID)}, "Monster_Effects" : getCardMonsterEffects(data.getInt32(1),data.getInt32(16)), "Level" : data.getInt32(6), "Atk" : data.getInt32(7), "Def" : data.getInt32(8), "Description" : {"Source": data.getString(4), "Locale": getTranslation('local_cards','Description','ID_Card',data.getInt32(1),UserLanguageID)}, "Code" : data.getString(9), "Rarities" : getCardRarities(data.getInt32(0),data.getInt32(16)), "Rulings" : getCardRulings(data.getInt32(1),data.getInt32(16))}); }
Merci encore pour votre aide =)
Envoyé par : hhf
Date : 02/02/2007 21:19
qui dit beaucoup de datas dit RDF et tree, ya pas d'autre solution.
Envoyé par : Raphael
Date : 02/02/2007 21:38
Ah ouais ? J'sais pas... RDF c'est du XML à la base non ? Et l'accès XML pour des bases de données très relationnelles, me semble que c'est pas vraiment adapté ni facile d'utilisation non ? Et pour les performances, suis pas sûr que ça soit au top non ?
SQLite3 a quand même été retenu par Mozilla pour sa légèreté et sa puissance, travailler avec du RDF ce serait pas s'entêter dans quelque chose qui va finir par devenir obsolète ?
Envoyé par : hhf
Date : 02/02/2007 22:59
ben oui, mais pour le peuplement d'element graphic, rien ne vaut un rdf. Soit plus precis sur la structure des datas que tu veux afficher. J'ai lu en diagonnale ton truc, et si j'ai bien compris, tu remplis une listbox, en utilisant le DOM, c'est ca qui est lent. Avec RDF, et un tree et le flags="dont-build-content", non seulement se sera asynchrone, mais en plus tu pourras trier les données affichées. Et je te garanti que se sera rapide, et pas de freez ecran
Envoyé par : Raphael
Date : 02/02/2007 23:24
Ah oui ? J'sais pas... pourtant ça me parait pas si lent que ça l'affichage (vidage+remplissage de 400 éléments instantané). D'après ce que je vois, pour l'instant c'est surtout ma requête qui est lente.
Tu penses donc que je devrais faire quelque chose du genre :
C'est que mes données sont quand même très complexes... Toutes mes tables sont liées à au moins 2/3 autres tables pour une internationalisation de toutes les propriétés, etc... Et si je me fais ça par RDF, il va clairement y avoir des données générées en double non ?
Envoyé par : hhf
Date : 03/02/2007 01:25
Mhm, il faudrait en dire plus, nb de tables, cardinalitées, vues que tu veux afficher, etc. Peut etre que ta requete n'est pas judicieuse, une mauvaise jointure et c'est un bon produit matriciel....
Ce que je comprend pas, c'est la vues (les données à l'ecran que tu veux avoir), pourkoi tu veux garder les relation entre elle ?
Si j'ai bien compris, c'est des card style "Magic the gathering" dont tu veux faire un interface pour consulté une BDD contenant toutes les infos de ces dernieres. Donc (tu me corrige) tu veux un tree avec toutes cards, peut etre arborescent pour ranger les cards par sous categories. Puis au click sur une cards, tu affiches un certain nombre d'infos s'y raportant. Peut etre aussi de koi mettre à jour les relations
Si c'est ca que tu veux, je vois pas ou tu veux gerer tes jointures sur l'ihm. Ou alors j'ai pas trop compris ce que tu m'a dis.
Je suis à l'ecoute...
Envoyé par : Raphael
Date : 03/02/2007 08:28
Oui, tu as compris, c'est exactement ça mon programme, et ça marche au poil pour une vingtaine de cartes... Mais déjà à 400, ça commence à mettre du temps au chargement sans que je puisse mettre de progressbar (1er pb) et ça prend pas mal de RAM (40Mo... 2° pb). Alors je n'ose imaginer quand j'en aurai 3000... =/
Voici le schéma de la base de données : http://www.ycd-project.org/portail/img/y(..)
En fait, à l'ouverture, je remplie un tableau cards dans lequel je mets toutes les infos de chaque carte (cf. mon post plus haut où j'ai mis la structure de mon tableau) : nom, traductions, propriétés et toutes les traductions locales... et ce afin de pouvoir filtrer rapidement mes cartes en temps réel. Je fais appel à de nombreuses fonctions pour aller chercher les bonnes infos de suite, ainsi j'y ai accès facilement par la suite dans mon tableau.
J'avais 2 optiques possibles :
J'ai préféré la 1ère solution en me disant qu'à choisir entre :
Bah, j'ai pensé que c'était mieux une ouverture lente + utilisation/réactivité/filtrage rapide...
Voilà donc la situation. Qu'en penses-tu ?
EDIT : Je suis en train de redécouvrir mes topics d'il y a 5 mois et où je demandais des avis de connaisseurs sur la manière d'aborder mon problème : http://xulfr.org/forums/read.php?1,6223,(..)
Je me posais la question : SQLite3 ou RDF ? Et voici les avis de l'époque :
Je voulais plutôt parler de temps de construction que de temps d'accès en fait, le moteur DOM est rapide et afficher en construisant les éléments prend peu de temps. C'est dans ce sens la que je te disais de tester tes requête avec SQLite Manager car les éléments XUL sont générés. L'inverse serait, comme le dit Laurent, de travailler avec des templates, mais en local je te conseille SQLite3 pour stocker tes données et surtout pas RDF qui est absolument inutilisable pour stocker des milliers d'enregistrements.
L'utilisation de mozstorage peut être envisagé. Mais aussi rdf pourquoi pas ! Tout dépend du volume de donnée etc..
Par exemple, tu peux peut-être envisager de stocker en rdf toutes les valeurs de références (categories par exemple...), cela permettra d'utiliser les templates.
Je ne suis pas d'accord avec thefab sur le fait que rdf n'est pas fait pour stocker des milliers de données. En tout cas, à l'affichage, avec les templates, ce sera beaucoup plus rapide que si tu extrait toi même tes données de sqlite et tu génères des élements via le dom. Aprés, derrière, si tu fais beaucoup de manipulation de données compliquées, c'est vrai que l'api rdf n'est pas aisée. Mais cela peut être caché par une API de plus haut niveau (que tu realiserais)
Sachant que je ne modifie pas les données de ma Base de Données (3000 enregistrements !)... et que je n'aspire qu'à une seule chose : Une interface la plus réactive possible et un filtrage par :
Quelle serait la meilleure méthode ?
Merci d'avance pour vos conseils expérimentés à tous...
Envoyé par : hhf
Date : 03/02/2007 16:53
Bon en effet ton modele n'est pas des plus simple, (pour un truc perso) au taf on a des truc qui rentre sur plusieurs page A3 LOL. J'aurais preferé un MCD avec les cardinalitées plutot que les foreign key. ca aurait été plus simple à analyser. Néanmoins, je persite à dire que RDF est une meilleur solution et surtout n'utilise pas une listbox, mais un tree, bien plus performant avec bcp de données. Mais ceci dit ca ne te supprime pas ta BDD, il faut je pense, faire un truc comme ca.
au chargement de l'appli tu fais une req SQL pour avoir toutes les cards, tu mets en forme en RDF et tu appliques au tree des cards, sur la selection d'un treeitem, tu recup l'ID de la cards et tu fais une requete SQL pour avoir les infos supplementaires. etc ... etc.. Pour le tri, tu utilise les fonction de tree de l'arbre, qd au filtre, tu refait une requete et tu repeuple.
Tu peux faire un essais, tu fait un fichier RDF à plat, avec tes 3000 entrees, puis tu l'affecte à un tree, tu verras le tps et la reactivitée. De plus avec ce system, tu poura faire ton appli en remote XUL ou pas.
PS, il me semble dans ton modele que monster_types et monster_subtypes pourait etre regroupé en une seule table. A voir
Il n'est plus possible de poster des messages dans ce forum.
Copyright © 2003-2013 association xulfr, 2013-2016 Laurent Jouanneau - Informations légales.
Mozilla® est une marque déposée de la fondation Mozilla.
Mozilla.org™, Firefox™, Thunderbird™, Mozilla Suite™ et XUL™
sont des marques de la fondation Mozilla.