IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

JavaScript Discussion :

Question concernant la mémoire


Sujet :

JavaScript

  1. #1
    Membre éprouvé
    Profil pro
    Inscrit en
    Février 2004
    Messages
    1 825
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 1 825
    Par défaut Question concernant la mémoire
    Bonjour à tous,

    Mon application va devoir charger des données de l'utilisateur qu'il aura lui même configuré via un éditeur en indiquant les le type de base de données, ses coordonnées ainsi que les tables et champs à charger.

    Par la suite, il se servira de mon application pour les manipuler.

    Par exemple il va définir :
    - ip base
    - port
    - base
    - t_clients (id, name)

    Une fois configuré j'ai un module qui va être capable d'aller chercher ces données et les transmettre à mon application. Je me pose la question de "comment les stocker".

    Intuitivement je verrais bien une structure comme celle-ci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    data["t_clients"][0]["id"] = 1
    data["t_clients"][0]["name"] = "Pierre"
    data["t_clients"][1]["id"] = 2
    data["t_clients"][1]["name"] = "Paul"
    data["t_clients"][2]["id"] = 3
    data["t_clients"][2]["name"] = "Jacques"
    J'avais implémenté ça en C++, mais le fait d'allouer des chaines de caractères "id", "name" pour chaque client faisait exploser la mémoire.

    La solution retenue était alors d'utiliser des pointeurs de membres, ce qui revenait plus ou moins (en code approximatif) à ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
     
    // données
    data["t_clients"][0] = [1, "Pierre"];
    data["t_clients"][1] = [2, "Paul"];
    data["t_clients"][2] = [3, "Jacques"];
     
    // meta
    data["t_clients"].meta["id"] = 0
    data["t_clients"].meta["name"] = 1
     
    // accès
    function getEntityById(entity, field, id)
    {
       var index = data[entity].meta[field];
       foreach(c in data[entity])
       {
          if(c[index] == id)
             return c;
       }
       return null;
    }
    Et ainsi on alloue autant de chaînes de caractères qu'il n'y a de champ par type de donnée et non par données, ce qui réduisait considérablement la mémoire utilisée.

    Est-ce que je dois me soucier de cela en javascript ?

    Question secondaire, est-il possible de gérer toute une multitude de données en javascript au sein d'un navigateur ? Par exemple si j'ai 3 millions de clients qui chacun possèdent une 10ène d'ordres , ça va pas faire planter le navigateur de charger tout ça ?

    Merci pour vos réponses,

    A bientôt

  2. #2
    Invité
    Invité(e)
    Par défaut
    Est-ce que je dois me soucier de cela en javascript ?
    Non. Même s'il faut faire attention à ce qu'on fait.
    Le truc c'est que chaque moteur JS a sa propre gestion de la mémoire et d'optimisation de code. Du coup, à moins d'aller étudier le fonctionnement de la gestion de la mémoire du moteur JS de chaque navigateur ciblé, tu ne sais pas si tes "optimisations" en seront vraiment ou si elles consommeront plus que la version originale.

    Je n'ai jamais étudié de près un moteur JS, donc je laisse à d'autres le soin d'expliciter les techniques de gestion de la mémoire.
    Mais tu es dans un contexte où - amha - chercher à économiser quelques octets de mémoire n'a pas de sens. Tu es sur un langage tellement haut niveau, pour lequel chaque instruction va engendrer des rouages complexes, que tes optimisations éventuelles sont quantités négligeables.

    PS : quand je parle des optimisations, je parle de celles du niveau que tu décris ci-dessus. Il est évident que certains codes JS sont plus optimisés que d'autres. Mais pas dans un tel niveau de détail.

  3. #3
    Membre éprouvé
    Profil pro
    Inscrit en
    Février 2004
    Messages
    1 825
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 1 825
    Par défaut
    Citation Envoyé par Enerian Voir le message
    Non. Même s'il faut faire attention à ce qu'on fait.
    Le truc c'est que chaque moteur JS a sa propre gestion de la mémoire et d'optimisation de code. Du coup, à moins d'aller étudier le fonctionnement de la gestion de la mémoire du moteur JS de chaque navigateur ciblé, tu ne sais pas si tes "optimisations" en seront vraiment ou si elles consommeront plus que la version originale.

    Je n'ai jamais étudié de près un moteur JS, donc je laisse à d'autre le soin d'expliciter les techniques de gestion de la mémoire.
    Mais tu es dans un contexte où - amha - chercher à économiser quelques octets de mémoire n'a pas de sens.
    Effectivement, si quelqu'un a un tutoriel des "bonnes pratiques" quant à la gestion de la mémoire en javascript, surtout lorsque la volumétrie est importante, ça serait pas mal sympa.

    Après j'imagine que les navigateurs ont une gestion correspondante à ces "bonnes pratiques", même si ils ont chacun la leur.

    Car en C++, mon soucis était de pouvoir accéder à une propriété d'un objet par son nom en chaîne de caractère :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    monClient.get("id") = monClient.id
    Au début j'avais fait une map de correspondant au sein de l'objet et pour chaque propriété :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    map<string, member> monClientCorrespondance;
    monClientCorrespondance.Add("id", this->id);
    monClientCorrespondance.Add("name", this->name);
    Mais du coup pour chaque client, cette table de correspondance était duppliquée et ça devait nécessitait d'allouer des chaîne "id" et "name" pour chacun d'entre eux, bien souvent plus consommatrices de mémoire que les données elles mêmes.

    Alors j'avais opté pour stocker des pointeurs de membres au niveau de la classe, comme ceci (toujours en pseudo code) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    static map<string, member> clientCorrespondance;
    clientCorrespondance.Add("id", Client::id);
    clientCorrespondance.Add("name", Client::name);
     
    // accès
    id = clientCorrespondance["id"](monClient);
    Ainsi je n'avais qu'une allocation des chaîne "id" et "name" par classe, et non par objet.

    L'optimisation représentait bien plus que "quelques octets", la consommation de mémoire 7 fois inférieure.

    Mais je ne sais pas si j'ai à me soucier de cela en Javascript

  4. #4
    Membre chevronné

    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    311
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 311
    Par défaut
    Salut,

    Les Array en JavaScript "dérive" d’Object et donc d’une sorte de map STL

    est équivalent, au niveau mémoire de :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    { '0' : 0x5b, '1' : 0xe3, length : 2 }
    Si tu souhaites avoir un contrôle total de la mémoire, le seule moyen et d’implémenter ta propre gestion mémoire en utilisant des ArrayBuffer

  5. #5
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    291
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Avril 2007
    Messages : 291
    Par défaut
    Bonjour,

    pour ma part, j'utilise souvent jsperf pour améliorer mes perfs ou pour vérifier qu'il n'y aura pas de soucis sur des gros volumes.
    Voici le lien (en anglais, désolé) : http://jsperf.com/

  6. #6
    Expert confirmé
    Avatar de sekaijin
    Homme Profil pro
    Urbaniste
    Inscrit en
    Juillet 2004
    Messages
    4 205
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Urbaniste
    Secteur : Santé

    Informations forums :
    Inscription : Juillet 2004
    Messages : 4 205
    Par défaut
    Citation Envoyé par p3ga5e Voir le message
    ... est équivalent, au niveau mémoire de :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    { '0' : 0x5b, '1' : 0xe3, length : 2 }
    ...
    Archi Faux
    les deux ont des implémentation mémoire très différentes.
    les méthodes applicables sont différentes.

    pour ta question sur les choix d'implémentations de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    monClient.get("id")
    monClient.id
    javascript le fait nativement ou presque
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    monClient.get = function(key) {return this[key];};
    si tu analyse se code d'un point de vu C++ cela revient à affecter au membre get de monClient un pointeur sur la fonction anonyme.

    en js pour généraliser ça à plusieurs objet on va faire un prototype (constructeur) tout comme en C++ tu ferait une classe.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Client = function(id, name){
     this.id = id;
     this.name = name;
     this.get =function(key) {return this[key];};
    }
    Ainsi tes membres sont définis une fois pour construire ton objet comme en C++ tu utilise new
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    var monClient = new Client(1, "foo");
    en mémoire outre les élément propres à JS tu vas avoir une allocation pour ton objet se réduisant à un pointeur vers un Number (pas de type simple en JS les nombre sont des objets) un pointeur vers la String "foo" et un pointeur vers le prototype

    donc question mémoire pas beaucoup de question à se poser.
    JS est un gros tas de pointeurs et de références.

    Tous sont des pointeurs ou des références vers quelque chose qui s'apparente à un super void* ou void& ils peuvent pointer ou référenser indiférement des objets ou des fonctions

    si tu fais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    fonction toto() {...};
    var test1 = {"id":1, "name": "foo", get:toto};
    var test2 = {"id":2, "name": "oof", get:toto};
    tu vas définir une référence toto sur une fonction
    deux référence test1 et test2 vers deux objets
    ces deux objets ont trois référence id vers un number, name vers une string et get qui a la même valeur que toto (référence la même fonction)
    si utilise le constructeur comme ci dessus
    tu as crée une référence vers le constructeur Client
    deux référence test1 et test2 vers deux objets
    ces deux objets ont trois référence id vers un number, name vers une string et __proto__ qui référence Client

    JS utilise un compteur de références lors un objet ou groupe d'objet n'est plus référencé il est supprimé de la mémoire.
    toute référence peut être réaffecté à tout moment.

    du coup mise à part lorsqu'on charge énormément d'objet et qu'on garde une référence sur chacun la gestion de la mémoire ne pose pas trop de pb.

    lorsqu'on viens de C++ il faut se méfier d'une chose
    la portée des variables
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    function test(){
       var attentionALaPortee = 45;
       document.getElementById("test").onclick=function(){
          alert(attentionALaPortee);
       }
    }
    dans ce test on défini dans la fonction test une variable celle-ci a une portée dans toute la fonction test.
    la fonction cherche l'élément test et lui ajote un handler sur la variable attentionALaPortee
    on est toujours dans la fonction test donc la variable est bien dans la portée.
    puis on sort de la fonction test. la variable attentionALaPortee n'est pas référencé et n'est plus dans la portée. on pourait penser qu'elle est détruite.

    que se passerait si on activait le clic ?
    le test montre que l'alert affiche la variable attentionALaPortee elle n'a pas été détruite.

    zn fait utiliser une variable au travers de sa portée comme on le fait dans ce test revient à la référencer.

    globalement pas de grosse difficulté avec la mémoire en JS mais quelques attentions lorsqu'on manipule les portées

    pour bien comprendre je vous conseille de lire la théorie des langages plus particulièrement la notion de closure (fermeture) tous les langage qui utilise cette notion ont quelque part un moyen de référencer les objets methodes de façon indirecte.

    A+JYT

Discussions similaires

  1. Questions concernant la mémoire et processeurs
    Par Shakan972 dans le forum Composants
    Réponses: 4
    Dernier message: 12/10/2006, 11h35
  2. Quelques questions sur la mémoire
    Par Gruik dans le forum C
    Réponses: 6
    Dernier message: 17/11/2004, 14h38
  3. Réponses: 7
    Dernier message: 10/09/2004, 14h28
  4. [Indy] Questions concernant l'envoi de mail
    Par delphicrous dans le forum Web & réseau
    Réponses: 3
    Dernier message: 24/06/2004, 15h06
  5. Question concernant l'API "WaitforSingleObject
    Par Drooxy dans le forum API, COM et SDKs
    Réponses: 3
    Dernier message: 29/03/2003, 07h26

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo