63 votes

Ai-je atteint les limites de la taille des objets que JavaScript peut gérer dans mon navigateur?

Je suis l'incorporation d'un grand tableau en <script> tags dans mon code HTML, comme ceci (rien de surprenant):

<script>
    var largeArray = [/* lots of stuff in here */];
</script>

Dans cet exemple particulier, le tableau a de 210 000 éléments. C'est bien en dessous du maximum théorique de 231 - par 4 ordres de grandeur. Voici la partie amusante: si je enregistrer JS source pour le tableau dans un fichier, ce fichier est >44 mégaoctets (46,573,399 octets, pour être exact).

Si vous voulez voir par vous-même, vous pouvez le télécharger à partir de GitHub. (Toutes les données qu'il est en conserve, tellement elle est répétée. Ce ne sera pas le cas dans la production.)

Maintenant, je suis vraiment pas un sujet de préoccupation de servir une quantité de données. Mon serveur de fichiers gzip ses réponses, de sorte qu'il n'a vraiment pas de prendre tout ce temps pour obtenir les données sur le fil. Cependant, il y a vraiment une fâcheuse tendance à la page, une fois chargé, de plantage du navigateur. Je ne suis pas de dépistage à tous dans IE (c'est un outil interne). Mes principaux objectifs sont de Chrome 8 et Firefox 3.6.

Dans Firefox, je peux voir un raisonnablement utile d'erreur dans la console:

Error: script stack space quota is exhausted

Dans google Chrome, j'ai simplement obtenir la triste page de l'onglet:

enter image description here

Couper à la chasse, déjà

  • Est-ce vraiment trop de données pour notre monde moderne, "haute-performance" des navigateurs à gérer?
  • Est-ce que je peux faire* pour traiter autant de données?

D'ailleurs, j'ai pu obtenir que cela fonctionne (lire: pas de plantage de l'onglet) sur-et-off dans Chrome. Je pensais vraiment que le Chrome, au moins, était fait d'un durcissement des trucs, mais apparemment je me trompais...


Edit 1

@Crayon: je ne cherchais pas à justifier pourquoi j'aimerais dump cette quantité de données dans le navigateur à la fois. Version courte: soit je résoudre ce un (certes pas-que-facile) problème, ou je dois résoudre toute une série d'autres problèmes. Je suis en optant pour l'approche la plus simple pour l'instant.

@différentes: pour l'instant, je ne suis pas particulièrement à la recherche de façons de réduire réellement le nombre d'éléments dans le tableau. Je sais que je pourrais mettre en œuvre la pagination Ajax ou quoi avez-vous, mais qui présente son propre ensemble de problèmes pour moi, à d'autres égards.

@Phrogz: chaque élément ressemble à quelque chose comme ceci:

{dateTime:new Date(1296176400000),
 terminalId:'terminal999',
 'General___BuildVersion':'10.05a_V110119_Beta',
 'SSM___ExtId':26680,
 'MD_CDMA_NETLOADER_NO_BCAST___Valid':'false',
 'MD_CDMA_NETLOADER_NO_BCAST___PngAttempt':0}

@Will: mais j'ai un ordinateur avec un processeur 4 cœurs, 6 go de RAM, plus d'un demi-téraoctet d'espace disque ...et je ne suis même pas demander au navigateur de le faire rapidement - je suis juste de le demander à travailler à tous!


Edit 2

Mission accomplie!

Avec le spot sur les suggestions de Juan ainsi que Guffa, j'ai pu obtenir que cela fonctionne! Il semblerait que le problème était juste dans l'analyse du code source, de ne pas vraiment travailler avec elle dans la mémoire.

Pour résumer le commentaire bourbier sur Juan réponse: j'ai dû couper mon grand tableau en une série de petits, puis Array#concat() , mais ce n'était pas assez. J'ai également eu à les mettre en séparer var des déclarations. Comme ceci:

var arr0 = [...];
var arr1 = [...];
var arr2 = [...];
/* ... */
var bigArray = arr0.concat(arr1, arr2, ...);

Pour tous ceux qui ont contribué à la résolution de ce: je vous remercie. Le premier tour est sur moi!


*à l'exception de l'évidence: l'envoi de moins de données dans le navigateur

82voto

Juan Mendes Points 31678

Voici ce que je voudrais essayer: vous avez dit que c'est un 44MB fichier. Que sûrement prend plus de 44MB de mémoire, je suppose que cela prend beaucoup plus de 44MB de RAM, peut-être la moitié d'un concert. Pourriez-vous venez de couper vers le bas les données jusqu'à ce que le navigateur ne plante pas et de voir combien de mémoire le navigateur utilise?

Même les applications qui s'exécutent sur le serveur serait bien de ne pas lire un 44MB fichier et de le garder en mémoire. Après avoir dit tout cela, je crois que le navigateur doit être capable de les gérer, alors permettez-moi de faire quelques tests.

(À l'aide de Windows 7, 4 go de mémoire)

Premier Test Je coupe le tableau en deux et il n'y avait pas de problèmes, utilise 80MB, pas de plantage

Deuxième Test Je divise le tableau en deux tableaux distincts, mais contient encore toutes les données, les utilisations de 160 mo, pas de plantage

Troisième Test Depuis Firefox a dit qu'il a couru hors de la pile, le problème est probablement qu'il ne peut pas analyser le tableau à la fois. J'ai créé deux tableaux distincts, arr1, arr2 puis n'a arr3 = arr1.concat(arr2); Il marchait bien et utilise seulement un peu plus de mémoire, autour de 165MB.

Quatrième Test je suis la création de 7 de ces tableaux (22 MO chacun) et concatting à l'épreuve du navigateur limites. Il faut environ 10 secondes pour que la page à la fin du chargement. La mémoire va jusqu'à 1,3 GO, puis il remonte vers le bas de 500 MO. Donc oui, google chrome peut s'en occuper. Il ne peut tout simplement pas analyser tout à la fois, car il utilise une sorte de récursivité comme on peut le constater par la console de message d'erreur.

Répondre à Créer des tableaux distincts (moins de 20 MO chacun), puis concat eux.

Je voudrais encore envisager de récupérer uniquement la partie nécessaire, il peut faire le navigateur lent. cependant, si c'est une tâche interne, ce devrait être bon.

Dernier point: Vous n'êtes pas au maximum de la mémoire niveaux, juste max l'analyse des niveaux.

13voto

Guffa Points 308133

Oui, c'est trop demander à un navigateur.

Que la quantité de données serait gérable si elle a déjà été données, mais il n'est pas encore de données. Considérer que le navigateur dispose d'analyser cette énorme bloc de code source lors de la vérification de la syntaxe ajoute à tout cela. Une fois analysée dans le code est valide, le code a exécuter pour produire le tableau réel.

Ainsi, toutes les données existent dans (au moins) deux ou trois versions à la fois, chacune avec un certain montant de frais généraux. Comme le littéral de tableau est un état unique, chaque étape devra inclure toutes les données.

La répartition des données en plusieurs petits tableaux serait peut-être le rendre plus facile sur le navigateur.

5voto

Matěj Zábský Points 9179

Avez-vous vraiment besoin de toutes les données? ne pouvez-vous pas diffuser simplement les données actuellement nécessaires à l'aide d'AJAX? Similaire à Google Maps - vous ne pouvez pas répondre à toutes les données de la carte dans la mémoire du navigateur, ils n'afficher que la partie que vous assistons actuellement.

Rappelez-vous que 40 mo de données peuvent être gonflés à beaucoup plus dans le navigateur interne de la représentation. Par exemple, la JS interprète peut utiliser la table de hachage pour mettre en œuvre la matrice, ce qui permettrait d'ajouter de la mémoire supplémentaire de frais généraux. Aussi, j'attends que le navigateur stocke le code source et le JS de la mémoire, seul, qui double la quantité de données.

JS est conçu pour offrir au client-côté de l'INTERFACE utilisateur de l'interaction, de ne pas manipuler des charges de données.

EDIT:

Btw, vous pensez vraiment que les utilisateurs comme le téléchargement de 40 méga-octets la valeur de code? Il y a encore de nombreux utilisateurs avec moins d'accès internet à large bande. Et de l'exécution du script sera suspendu jusqu'à ce que toutes les données sont téléchargées.

EDIT2:

J'ai eu un regard sur les données. Ce tableau va certainement être représenté comme une table de hachage. Aussi de nombreux éléments sont des objets, qui nécessitent un suivi de référence...c'est de la mémoire supplémentaire.

Je suppose que le rendement serait mieux si c'était simple vecteur de données primitifs.

EDIT3: Les données pourraient certainement être simplifié. La majorité d'entre elles sont la répétition des chaînes, ce qui peut être codé en quelque sorte, comme des entiers ou quelque chose. Aussi, mon Opéra est d'avoir de la difficulté à simplement afficher le texte, a fortiori, de l'interpréter.

EDIT4: Oubliez les objets DateTime! Utiliser unix ère des horodateurs ou des chaînes, mais pas des objets!

EDIT5: Votre processeur n'a pas d'importance parce que le JS est mono-thread. Et de votre RAM n'a pas d'importance, la plupart des navigateurs sont 32 bits, donc ils ne peuvent pas utiliser beaucoup de mémoire.

EDIT6: Essayez de modifier le tableau des indices entiers séquentiels (0, 1, 2, 3...). Que peut faire le navigateur utilisation plus efficace de la matrice de structure de données. Vous pouvez utiliser des constantes pour accéder au tableau des éléments de manière efficace. Cela va réduire la taille de la matrice par un énorme morceau.

5voto

Bitsplitter Points 637

Essayez de récupérer les données avec Ajax en tant que page JSON. Je ne connais pas la taille exacte, mais j'ai pu extraire de grandes quantités de données dans Google Chrome de cette façon.

2voto

Shadow Wizard Points 38568

Je voudrais essayer de l'avoir comme une grande chaîne avec séparateur entre chaque "élément", puis utiliser split, quelque chose comme:

var largeString = "item1,item2,.......";
var largeArray = largeString.split(",");

Espérons que la chaîne de ne pas épuiser la pile de façon rapide.

Edit: pour le tester, j'ai créé mannequin tableau avec 200 000 articles simples (chaque élément un nombre) et Chrome chargé dans un instant. 2 000 000 d'articles? Couple de secondes, mais pas de plantage. 6 000 000 d'éléments array (50 MO de fichier) fait Chrome charge pendant environ 10 secondes, mais encore, pas de plantage en soit les moyens.

Donc ce qui m'amène à croire que le problème n'est pas le tableau lui-même, mais plutôt du contenu.. optimiser le contenu de simples éléments, puis les analyser "à la volée" et cela devrait fonctionner.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X