Quelle est la taille des objets fonction Javascript?

Je me demandais simplement comment la surcharge est sur un objet fonctionnel. Dans un modèle de conception OOP, vous pouvez générer beaucoup d'objets avec leurs propres fonctions privées, mais dans le cas où vous avez plus de 10 000, ces objets fonctionnels privés, je suppose, peuvent générer beaucoup de frais généraux. Je me demande s'il y a des cas où il serait avantageux de déplacer ces fonctions vers une classe d'utilité ou un gestionnaire externe pour sauvegarder la mémoire prise par ces objets fonctionnels.

C'est ainsi que Chrome gère les fonctions, et d'autres moteurs peuvent faire différentes choses.

Voyons ce code:

 var funcs = []; for (var i = 0; i < 1000; i++) { funcs.push(function f() { return 1; }); } for (var i = 0; i < 1000; i++) { funcs[0](); } 

http://jsfiddle.net/7LS6B/4/

Maintenant, le moteur crée 1000 fonctions.

La fonction individuelle elle-même ne prend presque aucune mémoire (36 octets dans ce cas), puisqu'elle contient simplement un pointeur vers un objet appelé SharedFunctionInfo, qui est essentiellement une référence à la définition de fonction dans votre code source *. C'est ce qu'on appelle l' analyse paresseuse .

Ce n'est que lorsque vous l'exécutez que le JIT démarre et crée une version compilée de la fonction qui nécessite plus de mémoire. Ainsi, funcs[0] prend 256 octets à la fin:

Capture d'écran de l'analyseur de tas

*) Ce n'est pas exactement vrai, il contient également des informations de portée, le nom de la fonction et d'autres métadonnées , c'est pourquoi il a une taille de 592 octets dans ce cas.

Tout d'abord, il est courant de placer des méthodes dans le prototype du constructeur d'objets, de sorte qu'ils seront partagés entre toutes les instances d'un objet donné:

 function MyObject() { .... } MyObject.prototype.do_this = function() { ... } MyObject.prototype.do_that = function() { ... } 

Notez également qu'un "objet fonction" est un bloc de code constant ou une fermeture; Dans les deux cas, la taille n'est pas liée au code:

 x = []; for (var i=0; i<1000; i++) { x.push(function(){ ... }); } 

La taille de chaque élément du tableau ne dépendra pas de la taille du code car le code lui-même sera partagé entre toutes les instances de l'objet fonction. Une certaine mémoire sera requise pour chacune des 1000 instances, mais ce serait approximativement la même quantité requise par d'autres objets, comme des chaînes ou des tableaux et non liés à la quantité de code présent dans la fonction.

Les choses seraient différentes si vous créez des fonctions en utilisant Javascript eval : dans ce cas, je m'attends à ce que chaque fonction prenne un peu et proportionnellement à la taille du code, à moins qu'une mise en cache et un partage super-intelligents ne soient effectués également à ce niveau.

Les objets fonctionnent en fait occupent beaucoup d'espace. Les objets eux-mêmes peuvent ne pas prendre beaucoup de place comme indiqué ci-dessous, mais les objets de fonction semblent prendre beaucoup plus. Pour tester cela, j'ai utilisé Function("return 2;") pour créer un tableau de fonctions anonymes.

Le résultat a été tellement implicite par l'OP. Qu'elles occupent effectivement de l'espace.

Créé Fonction

100 000 de ces Function() créées ont généré 75,4 Mo, à partir de 0. J'ai exécuté ce test dans un environnement plus contrôlé. Cette conversion est un peu plus évidente, où il indique que chaque objet fonction va consommer 754 octets. Et ceux-ci sont vides. Les objets de fonction plus grands peuvent dépasser 1kb qui deviendront significatifs très rapidement. Spinning up the 75MB était non trivial sur le client, et a provoqué un verrou de près de 4 secondes de l'interface utilisateur.

Voici le script que j'ai utilisé pour créer les objets fonctionnels:

 fs = []; for(var i = 0; i < 100000; i++ ){ fs.push(Function("return 2;")); } 

L'appel de ces fonctions affecte également les niveaux de mémoire. L'appel des fonctions a ajouté une utilisation supplémentaire de mémoire de 34 Mo.

Appelé Appelé

C'est ce que j'avais l'habitude de les appeler:

 for( var i = 0; i < fs.length; i++ ){ for( var a = 0; a < 1000; a++ ){ fs[i](); } } 

L'utilisation de jsfiddle en mode édition est difficile à obtenir des résultats précis, je suggère de l'intégrer.

Embedded jsFiddle Demo


Ces déclarations sont incorrectes, je les ai laissées pour permettre aux commentaires de conserver le contexte.

Les objets de fonction ne prennent pas beaucoup d'espace. Le système d'exploitation et la mémoire disponibles vont être ce qui décide à la fin de la gestion de cette mémoire. Cela n'aura aucun impact sur une échelle dont vous devriez vous inquiéter.

Lorsqu'il a été chargé sur mon ordinateur, un jsfiddle relativement vide a consommé 5,4 Mo de mémoire. Après avoir créé 100 000 objets fonctionnels, il a sauté à 7,5 Mo. Cela semble être une quantité insignifiante de mémoire par objet fonction (l'implication étant 21 octets par objet fonction: 7.5M-5.4M / 100k).

Image mémoire

jsFiddle Demo