J'ai la nécessité de construire continuellement de grandes chaînes dans une boucle et de les enregistrer à la base de données qui donne actuellement occasionnellement un Qu'est-ce qui se passe essentiellement ici est de créer une chaîne en utilisant Les cordes en soi ne sont pas trop grosses (inférieures à 500kbytes chacune) et la mémoire de processus n'augmente pas pendant cette boucle. Mais toujours, je reçois occasionnellement un Qu'est-ce qui se passe ici? Pourquoi devrais-je obtenir un Étant donné que je ne peux pas contourner la conversion de toutes ces cordes, que pourrais-je faire pour rendre ce travail de manière fiable? Devrais-je forcer une collection de GC? Devrait mettre un OutofMemoryException code>. p>.
xmlwriter code> avec
stringbuilder code> en fonction de certaines données. Ensuite, j'appelle une méthode à partir d'une bibliothèque externe qui convertit cette chaîne XML en une autre chaîne. Après cela, la chaîne convertie est enregistrée dans la base de données. Tout cela est fait à plusieurs reprises dans une boucle environ 100 fois pour différentes données. P>
OutofMemeoryExcpetion code> dans
stringbuilder.append code>. Fait intéressant, cette exception n'a pas abouti à un crash. Je peux attraper cette exception et continuer la boucle. P>
OutofMorioryException code> Bien qu'il existe encore assez de mémoire libre disponible dans le système? Est-ce un problème de tas de GC? P>
thread.sleep code> dans la boucle? Devrais-je arrêter d'utiliser
stringbuilder code>? Devrait simplement réessayer lorsqu'il est confronté à un
OutofMemoryException code>? P>
3 Réponses :
Il y a de la mémoire mais pas de segment contigu qui peut gérer la taille de votre constructeur de cordes. Vous devez savoir que chaque fois que le tampon du constructeur de cordes est trop court, sa taille est doublée. Si vous pouvez définir (dans la CTOR), la taille de votre constructeur, c'est mieux.
Vous pouvez appeler En réalité, lorsque vous avez une certaine mémoire, IT Generaly montre une mauvaise conception, vous pouvez utiliser le disque dur (fichiers Temp) au lieu de la mémoire, vous ne devez pas répartir la mémoire et encore (essayez de réutiliser des objets / tampons /. ..). P>
Je vous conseille fortement de lire ce message " Out of Memory "ne fait pas référence à la mémoire physique de Eric Lippert. P> gc.collect () code> lorsque vous avez terminé avec une grande collection d'objets. P>
Si j'utilise le même StringBuilder encore et encore, je voudrais utiliser le même segment de mémoire (sauf lorsque le SB doit être agrandir)? Cela ne résoudrait-il pas à tous mes problèmes (très probablement)?
Je ne suis pas sûr, vous devrez essayer de voir si le constructeur de cordes garde sa capacité quand il est effacé ...
Pas totalement inutile: vous pouvez éviter la fragmentation de la mémoire qui semble être le vrai problème ici.
Eh bien, il peut réaffecter mais s'il n'y a pas d'autre SB à la poubelle, ce sera beaucoup plus efficace.
Un SB a un tampon, si vous réutilisez la SB, vous pouvez réutiliser le tampon. Si vous créez une nouvelle SB à chaque fois, vous créez un nouveau tampon à chaque fois et les anciens tampons sont à la poubelle. Même si le constructeur de cordes réutilisé est de taille, il y a beaucoup moins de déchets car il n'y a que des tampons de ce constructeur et non de tous les tampons de tous les constructeurs de chaînes d'opérations précédentes.
Essayez de réutiliser l'objet StringBuilder lorsque vous effectuez une génération de données.
après ou avant l'utilisation, réinitialisez simplement la taille du StringBuilder vers 0 et commencez à ajouter. Cela va diminuer le nombre d'allocations et éventuellement rendre la situation de mémoire très rare. P>
Pour illustrer mon point: P>
void MainProgram() { StringBuilder builder = new StringBuilder(2 * 1024); //2 Kb PerformOperation(builder); PerformOperation(builder); PerformOperation(builder); PerformOperation(builder); } void PerformOperation(StringBuilder builder) { builder.Length = 0; // // do the work here builder.Append(...); // }
Avec les tailles que vous mentionnez Vous êtes probablement en cours d'exécution dans Grand heap objet une fragmentation> (loh). p>
La réutilisation des objets StringBuilder n'est pas une solution directe, vous devez obtenir une adhérence sur les tampons sous-jacents. Et cela pourrait aider si vous rondez
Si possible, calculez ou estimez la taille à l'avance et pré-allouer. p>
Pourquoi réutiliser des objets StressBuilder n'est-il pas une solution directe? Signifiez-vous simplement que la réutilisation + préallocation intérieure (d'une taille qui convient à toutes les chaînes futures) serait la solution?
Bitbonk, oui, quelque chose comme ça. Le pire modèle de LOH est l'allocation des blocs de taille croissante et / ou d'alterner de longs blocs de vécus.