manejo - leer archivo txt asp net c#
Crear y escribir un archivo XML arroja la excepción-> sistema de memoria fuera de la excepción? (6)
¿Qué tan grande es widthNode, lengthNode y heightNode en su código de carga? Si llega algún valor irrazonable, podría terminar asignando una gran matriz de acceso - y se asignarán objetos lo suficientemente grandes en el gran montón de objetos, que es mucho más difícil de gestionar - por un lado, no se compacta. Entonces tendrías un proceso de 3 GB que solo usa 70 MB de memoria.
¿La excepción ocurre en la carga repetida (y la liberación), o también ocurre si carga solo un nodo por cada aplicación que se ejecuta? Los objetos por vista de dirección en el perfilador CLR son útiles para tener en cuenta la disposición de la memoria real: verá lagunas de espacio libre con bastante facilidad si su problema es la fragmentación del montón.
Y por último, pero no menos importante, es posible que OutOfMemoryException esté completamente equivocado por alguna razón: el culpable habitual tiende a obtener un valor incorrecto en los constructores de matrices (por ejemplo, la nueva int [int.MaxValue] va a fallar).
He estado desarrollando durante algún tiempo un pequeño juego llamado ''voxel'' en XNA. Un .NET C # como el juego Minecraft. Utilizo un concepto simple para guardar y leer datos de mis juegos para construir el mapa mundial. Todo está almacenado en un archivo xml.
Ahora intento cargar un mapa más grande, y ''paf'' se genera una excepción durante la generación de mi mapa:
[ Sistema sin memoria de excepción ]
No entiendo por qué, porque después de la excepción, mi archivo no es muy pesado, es de unos 70 mb . ¿Es normal ver un aumento de excepción durante la generación de un archivo XML de hasta 70 mb ?
Entorno de desarrollo utilizado
- Microsoft Windows 7 (x64) bits
- Visual Studio 2012 professionnel Actualización 3
- 8192 Ram
- CPU Intel i5 2.5 Ghz (4 cpus)
Hice una prueba con CLR Profiler para comprobar cómo funciona el recolector de basura:
El código donde inicializo mi XmlWritter:
private XmlTextWriter myXmlTextWriter ;
#region prepareNewWorldXmlFIle
private void PreparedNewWorldXmlFile()
{
Stream fs = new FileStream(currentPath + "World//world.xml", FileMode.Create);
myXmlTextWriter = new XmlTextWriter(fs,Encoding.ASCII);
myXmlTextWriter.Formatting = Formatting.Indented;
myXmlTextWriter.WriteStartDocument(false);
myXmlTextWriter.WriteComment("World Map ID:");
//World and his attribute
myXmlTextWriter.WriteStartElement("World");
myXmlTextWriter.WriteStartElement("Matrix", null);
myXmlTextWriter.WriteStartElement("Regions");
}
#endregion
El código que uso para generar mi mapa mundial y escribir un archivo xml:
//Octree calcul and generate map to xml file
foreach (Region region in arcadia.world.Regions)
{
isAllCheckSameIdOctree = false;
if (isFirstGenerationWorld)
{
//Regions and attributes
myXmlTextWriter.WriteStartElement("Region");
myXmlTextWriter.WriteAttributeString("id", indexRegion.ToString());
myXmlTextWriter.WriteAttributeString("min", "x:" + region.PositionMin.X + ";y:" + region.PositionMin.Y + ";z:" + region.PositionMin.Z);
myXmlTextWriter.WriteAttributeString("max", "x:" + region.PositionMax.X + ";y:" + region.PositionMax.Y + ";z:" + region.PositionMax.Z);
myXmlTextWriter.WriteStartElement("Structures");
myXmlTextWriter.WriteAttributeString("type", "cube");
}
indexRegion++;
if (region.Matrice != null)
{
//If the node to generate contain minimum a height divisible by 2
if (((region.PositionMax.Y - region.PositionMin.Y) / 2) > 2)
{
//generate and octree by 8
GenerateNodes(region, region.PositionMin, 8);
}
else if (((region.PositionMax.Y - region.PositionMin.Y) / 2) <= 2)
{
//generate and octree by 4
GenerateNodes(region, region.PositionMin, 4);
}
while (!isAllCheckSameIdOctree)
{
if (nodeToRegenerate != null && needRecurseBuild)
{
//if the node is greater than 2
if (nodeToRegenerate.TotalHeight > 2)
{
nodeToRegenerate = GenerateNodes(nodeToRegenerate, region, nodeToRegenerate.Position, 8);
if (nodeToRegenerate == null)
{
isAllCheckSameIdOctree = true;
}
}
else if (nodeToRegenerate.TotalHeight <= 2)
{
nodeToRegenerate = GenerateNodes(nodeToRegenerate, region, nodeToRegenerate.Position, 4);
if (nodeToRegenerate == null)
{
isAllCheckSameIdOctree = true;
}
}
}
else
{
isAllCheckSameIdOctree = true;
}
}
if (isFirstGenerationWorld)
{
myXmlTextWriter.WriteEndElement();//Ferme le noeud Structures
myXmlTextWriter.WriteEndElement();//Ferme le noeud Region
myXmlTextWriter.Flush();
}
}
else
{
if (isFirstGenerationWorld)
{
myXmlTextWriter.WriteEndElement();//Ferme le noeud Structures
myXmlTextWriter.WriteEndElement();//Ferme le noeud Region
myXmlTextWriter.Flush();
}
}
}
if (isFirstGenerationWorld)
{
myXmlTextWriter.WriteEndElement();//Ferme le noeud Regions
myXmlTextWriter.WriteEndElement();//Ferme le noeud World
myXmlTextWriter.Flush();
myXmlTextWriter.Close();
}
Captura de excepciones en mi función generatedNode, ver más abajo para más información
Mi función generatedNode recursive donde la excepción se dispara con ''system out of memory exception
#region ReGenerateWorld
private Node GenerateNodes(Node nodeToRegenerate, Region region, Vector3 position, int countToCut)
{
//Relative dimension of the parent octree
int widthParent = (int)nodeToRegenerate.TotalWidth / 2;
int heightParent = (int)nodeToRegenerate.TotalHeight / 2;
int lenghtParent = (int)nodeToRegenerate.TotalLenght / 2;
//Relative dimension of the parent octree
int widthNode = (widthParent) / (countToCut / (countToCut / 2));
int heightNode = (heightParent) / (countToCut / (countToCut / 2));
int lenghtNode = (lenghtParent) / (countToCut / (countToCut / 2));
if (heightNode < 1)
{
heightNode = 1;
}
int refX = (int)position.X / 2;
int refY = (int)position.Y / 2;
int refZ = (int)position.Z / 2;
int indexStartX = 0;
int indexStartY = 0;
int indexStartZ = 0;
int nbrToCut = 0;
if (heightParent >= 2)
{
nbrToCut = ((widthParent / (widthParent / 2))) * ((heightParent / (heightParent / 2))) * ((lenghtParent / (lenghtParent / 2)));
}
else
{
nbrToCut = 4;
heightNode = 1;
}
//Calculate the number of cubic to cut
//Génére les noeud racine
int countVertical = 0;
int calcPosX = 0;
int calcPosY = 0;
int calcPosZ = 0;
int[][][] nodeMatriceWorld = null;
bool firstTime;
newNode = null;
int idGroup = 0;
bool isSameId = true;
int idToCheck = 0;
for (int index = 0; (index < nbrToCut) && (refY < 32); index++)
{
indexStartX = refX;
indexStartY = refY;
indexStartZ = refZ;
try
{
nodeMatriceWorld = new int[widthNode][][];
for (int i = 0; i < widthNode; i++)
{
nodeMatriceWorld[i] = new int[lenghtNode][];
for (int j = 0; j < lenghtNode; j++)
{
nodeMatriceWorld[i][j] = new int[heightNode];
}
}
}
catch (Exception ex)
{
// OUT OF MEMORY EXCEPTION HERE
Console.Out.WriteLine(ex.Message);
}
firstTime = true;
for (int epaisseur = 0; epaisseur < heightNode; epaisseur++, indexStartY++)
{
for (int ligne = 0; ligne < lenghtNode; ligne++, indexStartZ++)
{
for (int collone = 0; collone < widthNode; collone++, indexStartX++)
{
if (firstTime)
{
calcPosX = indexStartX;
calcPosY = indexStartY;
calcPosZ = indexStartZ;
firstTime = false;
}
nodeMatriceWorld[collone][ligne][epaisseur] = matriceWorld[indexStartX][indexStartZ][indexStartY];
}
indexStartX = refX;
}
indexStartZ = refZ;
}
indexStartY = refY;
idGroup = matriceWorld[calcPosX][calcPosZ][calcPosY];
countVertical++;
if (newNode != null)
{
newNode.Dispose();
}
newNode = new Node(nodeMatriceWorld, new Vector3(calcPosX, calcPosY, calcPosZ), idGroup, widthNode, heightNode, lenghtNode);
region.Nodes[idGroup].Add(newNode);
//Regions.Add(new Node(nodeMatriceWorld, new Vector3(calcPosX, calcPosY, calcPosZ), idGroup));
refX += widthNode;
if (countVertical >= 4)
{
refY = ((int)position.Y / 2) + heightNode;
refX = ((int)position.X / 2);
refZ = (int)position.Z / 2;
countVertical = 0;
}
else if (countVertical == 2)
{
refZ = ((int)position.Z / 2) + lenghtNode;
refX = ((int)position.X / 2);
}
}
isSameId = true;
nodeToRegenerate = null;
needRecurseBuild = false;
idToCheck = 0;
// Check for each octree node if all are the same id
foreach (List<Node> listNode in region.Nodes)
{
foreach (Node node in listNode.Where(m => m.isGroupSameId == false))
{
isSameId = true;
idToCheck = node.matriceNode[0][0][0];
node.isGroupSameId = true;//Le met a true au depart
for (int epaisseur = 0; epaisseur < node.TotalHeight / 2 && isSameId; epaisseur++)
{
for (int ligne = 0; ligne < node.TotalLenght / 2 && isSameId; ligne++)
{
for (int collone = 0; collone < node.TotalWidth / 2 && isSameId; collone++)
{
if (node.matriceNode[collone][ligne][epaisseur] != idToCheck)
{
isSameId = false;//si au moin un cube est différent on le marque
node.isGroupSameId = false;
//node.ItemGroup = node.matriceNode[collone, epaisseur, ligne];
nodeToRegenerate = node;
needRecurseBuild = true;
break;
}
}
}
}
if (!isSameId)
{
break;
}
else
{
if (idToCheck != 0)
{
isSameId = true;
node.isGroupSameId = true;
node.ItemGroup = idToCheck;
node.matriceNode = null;
node.Cube = new Primitives3D.Cube(node.ItemGroup, node.Position, new Vector3(0, 0, 0), node.TotalWidth, node.TotalHeight, node.TotalLenght);
//Initialise le cube qui représente le noeud
node.Cube.BuildCubeStart();
if (isFirstGenerationWorld)
{
myXmlTextWriter.WriteStartElement("Cube");
//Structures et ses attributs
myXmlTextWriter.WriteAttributeString("id", node.ItemGroup.ToString());
myXmlTextWriter.WriteAttributeString("min", "x:" + node.Cube.BoundingBox.Min.X + ";y:" + node.Cube.BoundingBox.Min.Y + ";z:" + node.Cube.BoundingBox.Min.Z);
myXmlTextWriter.WriteAttributeString("max", "x:" + node.Cube.BoundingBox.Max.X + ";y:" + node.Cube.BoundingBox.Max.Y + ";z:" + node.Cube.BoundingBox.Max.Z);
myXmlTextWriter.WriteEndElement();//Ferme le noeud xml cube
myXmlTextWriter.Flush();
}
//Ajoute l''id du noeud aux groupe d''id de la region s''il n''y était pas auparavant
if (!region.IdFound.Contains(node.ItemGroup) && node.ItemGroup != 0)
{
region.IdFound.Add(node.ItemGroup);
}
}
// If the node group is equal to an empty group id -> 0 it removes entire else
{
nodeToDelete = node;
}
}
}
if (!isSameId)
{
break;
}
//Console.Out.WriteLine("Nodes cout generated : " + Nodes.Count.ToString());
}
// If a node does not contain all the same id -> go remove it
if (!isSameId)
{
region.Nodes[nodeToRegenerate.ItemGroup].Remove(nodeToRegenerate);
}
if (nodeToDelete != null)
{
region.Nodes[nodeToDelete.ItemGroup].Remove(nodeToDelete);
}
nodeToDelete = null;
//Dispose the resources
newNode.Dispose();
nodeMatriceWorld = null;
return nodeToRegenerate;
}
#endregion
La excepción:
En primer lugar, asegúrese de cerrar FileStream después de usarlo. ejemplo) - esta es una de las mejores prácticas.
private void PreparedNewWorldXmlFile()
{
using(Stream fs = new FileStream(currentPath + "World//world.xml", FileMode.Create))
{
myXmlTextWriter = new XmlTextWriter(fs,Encoding.ASCII);
myXmlTextWriter.Formatting = Formatting.Indented;
myXmlTextWriter.WriteStartDocument(false);
myXmlTextWriter.WriteComment("World Map ID:");
//World and his attribute
myXmlTextWriter.WriteStartElement("World");
myXmlTextWriter.WriteStartElement("Matrix", null);
myXmlTextWriter.WriteStartElement("Regions");
}
}
Creo que deberías liberar todos los objetos de nodo en tu instancia de clase de región. porque GC no recopilará la instancia de clase de región, sin embargo, la configura como nula.
Hace poco recibí un error similar al procesar XML a través de XSLT. Mis archivos eran solo 5MB sin embargo. Cambié mi procesamiento XSLT a una clase .net (conversión usando la herramienta de conversión MS) y eso resolvió el problema. Aparentemente algunos errores con el procesador XSLT.
Es posible que tenga un problema similar y, tal como lo sugiere el otro usuario, intente utilizar diferentes procesadores de documentos XML, ya que el usuario puede tener un error o una limitación.
Puede salirse de la excepción de memoria con métodos recursivos cuando se queda sin memoria de pila. Básicamente, su recursión es infinita o cercana a ella lo suficiente como para agotar la memoria reservada para la pila.
Según tengo entendido, tu problema no está en XML, sino en la matriz dentada int [] [] [] nodeMatriceWorld . Su tamaño es demasiado grande o está creando esta matriz demasiadas veces. Aquí está tu código:
try
{
nodeMatriceWorld = new int[widthNode][][];
for (int i = 0; i < widthNode; i++)
{
nodeMatriceWorld[i] = new int[lenghtNode][];
for (int j = 0; j < lenghtNode; j++)
{
nodeMatriceWorld[i][j] = new int[heightNode];
}
}
}
catch (Exception ex)
{
// OUT OF MEMORY EXCEPTION HERE
Console.Out.WriteLine(ex.Message);
}
Compruebe widthNode, lenghtNode y heightNode. Para nodeMatriceWorld necesita al menos sizeof (int) * widthNode * lenghtNode * heightNode bytes de memoria.
parece que intentas representar un mapa con una matriz tridimensional, usando un mapa de alturas; sin embargo, solo necesitas 2 dimensiones.
ejemplo: la matriz: int map [x] [y]; donde el valor del mapa [x] [y] es la z.
de esta manera necesitas mucha menos memoria que debería arreglar tu problema