increase in memory leads to the graphic device to be suspended

HI ,I am working on a MonoGame.Forms project but i have a proplem with the process memory that it keeps icreasing in steady rate with time even without doing anything , which will lead the graphic devise to be suspended after around 40min or so .
the basic idea of my editor that it loads a json file that contains a skeletal structure then i deserialize(convert) the json into a list of bones the display the armature in my ViewPort (monogame) class
I posted on a the same problem befor but the increase of the memory back then was hiegh and fast
i was told that happend because i was creating a new basiceffict each time i draw somthing
but now i made sure to create only one in DrawWorld ,
but now the rate of increase in memory is not affected by loading a file , Whether there is a file is loaded or not the memory will keep increasing , also me editor can load fbx files but that dosnt affect
the memory that much.
it reached 700mb after like 10-15 min without touching it .

       public static ViewPort mono;
        private GraphicsDeviceManager graphics;
        GraphicsDevice graphicsDevice;
        SpriteBatch spriteBatch;
        private BasicEffect basicEffect;
        public static Matrix WorldMatrix= Matrix.CreateWorld(Vector3.Zero,Vector3.Forward,Vector3.Up);
        public static Matrix Projection;
        public static Matrix View;
        public static VertexPositionColor[] vertices = new VertexPositionColor[0];
        public static VertexPositionColor[] triVertices = new VertexPositionColor[0];
        protected override void Initialize()
        {
            BoneJsonEditor.Include.MySFformat.mono = this;
            _stopwatch = Stopwatch.StartNew();
            spriteBatch = new SpriteBatch(GraphicsDevice);
            this.graphicsDevice = GraphicsDevice;
            base.Initialize();
 
        }
 protected override void Update(GameTime gameTime)
        {

            Form1.UpdateSelected();
            DisplayOption.UpdateBool();
            MySFCamera(gameTime);
            base.Update(gameTime);

        }
 protected override void Draw()
        {

            base.Draw();


            GraphicsDevice.Clear(MegaGray);

            // Measure the elapsed time since the last frame
            long elapsedTicks = _stopwatch.ElapsedTicks - _lastFrameTime;
            float elapsedSeconds = (float)elapsedTicks / Stopwatch.Frequency;
            _lastFrameTime = _stopwatch.ElapsedTicks;

            // Measure the current memory usage
            long memoryUsage = GC.GetTotalMemory(false);
            long processMemoryUsage = Process.GetCurrentProcess().WorkingSet64;


            Editor.spriteBatch.Begin();
            DrawWorld();
            GraphicsDevice.BlendState = BlendState.AlphaBlend;
            DrawAxes();
            Editor.spriteBatch.DrawString(Editor.Font, $"Memory: {(processMemoryUsage / 1024f / 1024f):F2} MB", new Vector2(GraphicsDevice.Viewport.Width - 150, 10), Color.White);
            GraphicsDevice.BlendState = BlendState.AlphaBlend;
            BoneDisplay();
            GraphicsDevice.BlendState = BlendState.AlphaBlend;
            if (isShow3dEnabled)
            {
                if (isMdlTriangleEnabled)
                {
                    renderMode = RenderMode.Triangle;
                }
                else if (isMdlLineEnabled)
                {
                    renderMode = RenderMode.Line;
                }
                else
                {
                    renderMode = RenderMode.BothNoTex;
                }

                DrawModel();
            }

            KeyboardState state = Keyboard.GetState();
            if (!isDialogOpen && state.IsKeyDown(Microsoft.Xna.Framework.Input.Keys.V))
            {
                checkVerticesSilent();
                Editor.spriteBatch.End(); // End sprite batch before displaying form
                displayVerticesInfo();
                Editor.spriteBatch.Begin(); // Begin sprite batch again after form is closed

            }


            Editor.spriteBatch.End();
            _lastMemoryUsage = memoryUsage;
            _lastProcessMemoryUsage = processMemoryUsage;

        }

my update method have only my camera and updates some display options like diplaying bones as a stick or a octahedral etc, which is controlled by another form
the DrawWorld method sets up my basiceffict and world matrices
the DrawAxis and DrawGround draws XYZ and grid lines

 private void DrawWorld()
        {

            var cameraPosition = new Vector3(cameraX + offsetX, cameraY + offsetY, cameraZ + offsetZ);
            var cameraLookAtVector = new Vector3(centerX + offsetX, centerY + offsetY, centerZ + offsetZ);
            var cameraUpVector = Vector3.UnitY;

            basicEffect = new BasicEffect(GraphicsDevice);
            basicEffect.View = Matrix.CreateLookAt(
                 cameraPosition, cameraLookAtVector, cameraUpVector);
            basicEffect.VertexColorEnabled = true;
            float aspectRatio =
                                 (float)GraphicsDevice.Viewport.AspectRatio

                ;

            float fieldOfView = Microsoft.Xna.Framework.MathHelper.PiOver4;
            float nearClipPlane = 0.1f;
            float farClipPlane = 200;

            basicEffect.Projection = Matrix.CreatePerspectiveFieldOfView(
                fieldOfView, aspectRatio, nearClipPlane, farClipPlane);

            basicEffect.VertexColorEnabled = true;

            basicEffect.World = WorldMatrix;
            Projection = basicEffect.Projection;
            View = basicEffect.View;

            BlendState blendState = new BlendState();
            DepthStencilState depthBufferState = new DepthStencilState();
            depthBufferState.DepthBufferEnable = true;
            depthBufferState.DepthBufferFunction = CompareFunction.LessEqual;
            GraphicsDevice.DepthStencilState = depthBufferState;
            basicEffect.CurrentTechnique.Passes[0].Apply();
        }
 private void DrawAxes()
        {
            float Axis = 20;
            Vector3 xAxis = new Vector3(Axis, 0, 0);
            Vector3 yAxis = new Vector3(0, Axis, 0);
            Vector3 zAxis = new Vector3(0, 0, Axis);
           

            VertexPositionColor[] AXvertices = new VertexPositionColor[6];
           int[] indices = { 0, 1, 2, 3, 4, 5 };

            AXvertices[0].Position = Vector3.Zero;
            AXvertices[0].Color = Color.Red;
            AXvertices[1].Position = xAxis;
            AXvertices[1].Color = Color.Red;
            AXvertices[2].Position = Vector3.Zero;
            AXvertices[2].Color = Color.Green;
            AXvertices[3].Position = yAxis;
            AXvertices[3].Color = Color.Green;
            AXvertices[4].Position = Vector3.Zero;
            AXvertices[4].Color = Color.Blue;
            AXvertices[5].Position = zAxis;
            AXvertices[5].Color = Color.Blue;
            
            GraphicsDevice.DrawUserIndexedPrimitives(
                Microsoft.Xna.Framework.Graphics.PrimitiveType.LineList,
                AXvertices,
                0,
                AXvertices.Length,
                indices,
                0,
                indices.Length / 2);
           
           DrawGround();

        }

then the BoneDisplay () sets up the bones to be displayed

  public void BoneDisplay ()
        {
            
            List<Bone> Bones = Form1.Skeleton;
            Transform3D[] boneTrans = new Transform3D[Bones.Count];

            for (int i = 0; i < Bones.Count; i++)
            {

                boneTrans[i] = new Transform3D();
                boneTrans[i].rotOrder = rotOrder;
                boneTrans[i].position = new Vector3D(Bones[i].Translation);
                boneTrans[i].setRotationInRad(new Vector3D(Bones[i].Rotation));
                boneTrans[i].scale = new Vector3D(Bones[i].Scale);

                if (Bones[i].ParentIndex >= 0)
                {
                    boneTrans[i].parent = boneTrans[Bones[i].ParentIndex];
                    Vector3D head = boneTrans[i].getGlobalOrigin();

                    if (boneTrans[Bones[i].ParentIndex] != null)
                    {
 
                        Vector3D tail = boneTrans[Bones[i].ParentIndex].getGlobalOrigin();
                        Vector3 Head = new Vector3(head.X, head.Y, head.Z);
                        
                        Vector3 Tail = new Vector3(tail.X, tail.Y, tail.Z);
                        RasterizerState rasterizerState = new RasterizerState();

                        if (i == Form1.selectedbone)
                        {
                            bonecolor = Color.Yellow;
                            Snap.oldPosition = Head;
                            Matrix3D posTrans = Matrix3D.generateTranslationMatrix(head.X, head.Y, head.Z);

                            Matrix3D parentRot = boneTrans[i].parent.getGlobalRotation();
                            Matrix3D Rot = boneTrans[i].getGlobalRotation();
                            Matrix3D invRot = Matrix3D.invert(Rot);
                            Matrix3D World = Matrix3D.CreateWorld(new Vector3D(0, 0, 0), new Vector3D(0, 0, -1), new Vector3D(0, 1, 0));
                            Matrix3D boneWorld =  posTrans * parentRot;
                            Matrix parentRotation = Matrix3D.MatrixConv(Rot);
                            //  Matrix boneWorldxna = Matrix3D.MatrixConv(boneWorld);
                            KeyboardState state = Keyboard.GetState();
                            if (state.IsKeyDown(Microsoft.Xna.Framework.Input.Keys.F))
                            { 
                            // Get the head and tail as strings
                            string headStr = $"Head: ({head.X}, {head.Y}, {head.Z})";
                            string tailStr = $"Tail: ({tail.X}, {tail.Y}, {tail.Z})";

                                // Get the parent rotation as a string
                                string parentRotationStr = "";
                                if (parentRotation != null)
                                {
                                    Matrix Rotation = parentRotation;
                                    parentRotationStr = "Bone Rotation:\n";
                                    parentRotationStr += $"M = [{Rotation.M11}, {Rotation.M12}, {Rotation.M13}, {Rotation.M14}; ";
                                    parentRotationStr += $"{Rotation.M21}, {Rotation.M22}, {Rotation.M23}, {Rotation.M24}; ";
                                    parentRotationStr += $"{Rotation.M31}, {Rotation.M32}, {Rotation.M33}, {Rotation.M34}; ";
                                    parentRotationStr += $"{Rotation.M41}, {Rotation.M42}, {Rotation.M43}, {Rotation.M44}];";
                                }

                                // Show the message box
                                string message = $"{headStr}\n{tailStr}\n{parentRotationStr}";
                            System.Windows.Forms.MessageBox.Show(message, "Bone Information");
                        }
  
                            Vector3D mxAxis3 = Matrix3D.matrixTimesVector3D(boneWorld, new Vector3D(0.1f, 0, 0));
                           // Vector3 mxAxis3 = Vector3.Transform(new Vector3(0.1f, 0, 0), boneWorldxna);
                              Vector3D myAxis3 = Matrix3D.matrixTimesVector3D(boneWorld, new Vector3D(0, 0.1f, 0));
                           // Vector3 myAxis3 = Vector3.Transform(new Vector3(0, 0.1f, 0), boneWorldxna);
                            Vector3D mzAxis3 = Matrix3D.matrixTimesVector3D(boneWorld, new Vector3D(0, 0, 0.1f));
                            //Vector3 mzAxis3 = Vector3.Transform(new Vector3(0, 0, 0.1f), boneWorldxna);
                            Vector3D Origin3 = Matrix3D.matrixTimesVector3D(boneWorld, new Vector3D(0, 0, 0));
                           // Vector3 Origin3 = Vector3.Transform( new Vector3(0, 0, 0), boneWorldxna);
                            VertexPositionColor[] MNvertices = new VertexPositionColor[6];
                            int[] indices = { 0, 1, 2, 3, 4, 5 };

                            Vector3 mxAxis = new Vector3(mxAxis3.X, mxAxis3.Y, mxAxis3.Z);
                            Vector3 myAxis = new Vector3(myAxis3.X, myAxis3.Y, myAxis3.Z);
                            Vector3 mzAxis = new Vector3(mzAxis3.X, mzAxis3.Y, mzAxis3.Z);
                            Vector3 Origin = new Vector3(Origin3.X, Origin3.Y, Origin3.Z);

                            MNvertices[0].Position = Origin;
                            MNvertices[0].Color = Color.Red;
                            MNvertices[1].Position = mxAxis;
                            MNvertices[1].Color = Color.Red;

                            MNvertices[2].Position = Origin;
                            MNvertices[2].Color = Color.Green;
                            MNvertices[3].Position = myAxis;
                            MNvertices[3].Color = Color.Green;

                            MNvertices[4].Position = Origin;
                            MNvertices[4].Color = Color.Blue;
                            MNvertices[5].Position = mzAxis;
                            MNvertices[5].Color = Color.Blue;
                            GraphicsDevice.DrawUserIndexedPrimitives(Microsoft.Xna.Framework.Graphics.PrimitiveType.LineList, MNvertices, 0, MNvertices.Length, indices, 0, indices.Length / 2);
                        }
                        else
                        {
                            bonecolor = Color.White;
                        }

                        if (isStickDisEnabled)
                        {
                            DrawStick(Head, Tail, bonecolor , rasterizerState);

                        }
                        else if (isOktaSolDisEnabled || isOktaWireDisEnabled)
                        {
                            DrawOctahedralBone(Tail, Head, bonecolor, rasterizerState);

                        }
                    }
                }
            }
        }
  private void DrawStick(Vector3 upperHead, Vector3 ParentPos, Color color , RasterizerState rasterizerState)
        {


            GraphicsDevice.BlendState = BlendState.AlphaBlend;
          
        
            rasterizerState.CullMode = CullMode.None;
            GraphicsDevice.RasterizerState = rasterizerState;

            VertexPositionColor[] lineVertices = new VertexPositionColor[2];
            lineVertices[0].Position = ParentPos;
            lineVertices[0].Color = Color.Crimson;
            lineVertices[1].Position = upperHead;
            lineVertices[1].Color = Color.Crimson;
            short[] lineIndices = new short[2];
            lineIndices[0] = 0;
            lineIndices[1] = 1;
            GraphicsDevice.DrawUserIndexedPrimitives(PrimitiveType.LineList, lineVertices, 0, 2, lineIndices, 0, 1);
            GraphicsDevice.BlendState = BlendState.Additive;
            Color colorWithOpacity = Color.FromNonPremultiplied(color.R, color.G, color.B, Alpha );
            Vector3 position = upperHead;
            int sphereResolution = 12;
            int numVertices = (sphereResolution + 1) * (sphereResolution + 1);
            VertexPositionColor[] sphereVertices = new VertexPositionColor[numVertices];
            int index = 0;
            float radius = 0.005f;
            for (int i = 0; i <= sphereResolution; i++)
            {
                float latitude = ((float)i / (float)sphereResolution) * MathHelper.Pi - MathHelper.Pi;
                for (int j = 0; j <= sphereResolution; j++)
                {
                    float longitude = ((float)j / (float)sphereResolution) * MathHelper.TwoPi;
                    sphereVertices[index].Position = new Vector3((float)Math.Sin(latitude) * (float)Math.Cos(longitude), (float)Math.Cos(latitude), (float)Math.Sin(latitude) * (float)Math.Sin(longitude)) * radius + position;

                    sphereVertices[index].Color = colorWithOpacity;
                    index++;
                }
            }
            int numIndices = sphereResolution * sphereResolution * 6;
            short[] sphereIndices = new short[numIndices];
            index = 0;
            for (int i = 0; i < sphereResolution; i++)
            {
                for (int j = 0; j < sphereResolution; j++)
                {
                    sphereIndices[index++] = (short)(i * (sphereResolution + 1) + j);
                    sphereIndices[index++] = (short)((i + 1) * (sphereResolution + 1) + j);
                    sphereIndices[index++] = (short)(i * (sphereResolution + 1) + j + 1);
                    sphereIndices[index++] = (short)((i + 1) * (sphereResolution + 1) + j);
                    sphereIndices[index++] = (short)((i + 1) * (sphereResolution + 1) + j + 1);
                    sphereIndices[index++] = (short)(i * (sphereResolution + 1) + j + 1);
                }
            }
            GraphicsDevice.DrawUserIndexedPrimitives(PrimitiveType.TriangleList, sphereVertices, 0, numVertices, sphereIndices, 0, numIndices / 3);
        }

I quickly check your code and I saw quite many “new” objects everywhere, that creates new instances, try to reduce those to not do “new”, reuse the old ones or cache it whenever is possible. Also in debugger there is a way to see what is using your memory so you can check which processes are increasing the use of memory.

1 Like

Agreed.

Creating a new basic effect every draw frame jumps out.

I believe basic effect needs to be disposed off when your done with it too.

Create 1 basic effect at a class level and use it (without creating a new one every frame)

Try and limit the number of new statements. Generally speaking if your creating something that uses gpu memory you have to also dispose of it yourself

i just moved

basicEffect = new BasicEffect(GraphicsDevice);

to the Initialize() method and this seems to fix it , i’ve rut it for an hour and the memory remained fixed under 100mb , thanks