El documento describe tres problemas y soluciones relacionados con la optimización de un motor de videojuegos en C#. El primer problema trata sobre el uso de structs versus clases y la memoria gestionada por el recolector de basura. El segundo problema aborda cómo compartir memoria entre structs definidos en bibliotecas diferentes. El tercer problema presenta una primera idea pero no proporciona detalles. Se proponen varias soluciones para los primeros dos problemas como el uso de paso por referencia, uniones explícitas y punteros para compartir la misma memoria entre structs
3. Structs
• Objetos con una vida muy corta de tiempo
• Mejor cuando solo trabaja el Stack
• Tener en cuenta el GC
• Usar paso por referencia siempre que sea posible
15. Memoria compartida entre structs
public struct Vector
{
public float X;
public float Y;
public float Z;
public Vector(float x, float y, float z)
{
this.X = x;
this.Y = y;
this.Z = z;
}
public override string ToString()
{
return string.Format("(X:{0} Y:{1} Z:{2})", X, Y, Z);
}
}
16. public void XNAMethod(ref Microsoft.Xna.Framework.Vector3 vector)
Primera Idea
Vector myVector = new Vector(1,2,3);
Vector3 xnaVector = (Vector3)myVector;
Error 1 Cannot convert type 'WindowsGame1.Vector' to 'Microsoft.Xna.Framework.Vector3'
Vector myVector = new Vector(1,2,3);
Vector3 xnaVector = new Vector3() { X = myVector.X, Y = myVector.Y, Z = myVector.Z };
17. Segunda idea
[StructLayout(LayoutKind.Explicit)]
public struct UnionVector
{
[FieldOffset(0)]
public Microsoft.Xna.Framework.Vector3 XnaVector;
[FieldOffset(0)]
public OpenTK.Vector3 OpenTkVector;
[FieldOffset(0)]
public float X;
[FieldOffset(4)]
public float Y;
[FieldOffset(8)]
public float Z;
}
UnionVector myVector = new UnionVector() { X = 1, Y = 2, Z = 3};
Vector3 xnaVector = myVector.XnaVector;
OpenTK.Vector3 oTKVector3 = myVector.OpenTkVector;
18. Tercera idea
Vector vector = new Vector(1, 2, 3);
unsafe
{
// Creamos un puntero de nuestro tipo de struct que apunta a la dirección
de memoria de nuestro vector.
Vector* pVector = &vector;
// Creamos un puntero del tipo de struct de XNA y hacemos un casting entre
punteros.
Vector3* pVector3 = (Vector3 *)pVector;
// Los métodos de XNA no permiten pasar como parámetro un puntero, por lo
que necesitamos la última conversión.
Vector3 vector3 = *pVector3;
XNAMethod(vector3);
}
19. Tercera idea
Vector vector = new Vector(1, 2, 3);
unsafe
{
XNAMethod(*(Vector3*)&vector);
}
Vector vector = new Vector(1, 2, 3);
unsafe
{
XNAMethod(ref *(Vector3*)&vector);
}