【问题标题】:Why content manager is taking so much heap size?为什么内容管理器占用这么大的堆大小?
【发布时间】:2017-01-18 19:45:49
【问题描述】:

应用程序是用 MonoGame API 用 C# 编写的。 这些应用程序是为 android 设计的,但我决定对其进行一些优化,因此我将其移植到 Windows 以使其与 CLRProfiler 一起使用,我发现 Heap 位于 77% Microsoft.Xna.Framework.Content.ContentManager->System 中。字节[]。有什么办法可以避免我的应用程序中的 GC 收集?这是它有问题的一部分:

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace Game1
{
    public struct FPS_counter
    {
        float fps_from;
        int fps;
        public int fps_toshow;
        public float in_Secs;

        public void add_frame()
        {
            fps_from += in_Secs;  //(float)gameTime.ElapsedGameTime.TotalSeconds;
            if (fps_from > 1)
            {
                fps_toshow = fps;
                fps = 0;
                fps_from = 0;
            }
            fps++;
        }
    }

    public struct numbers
    {

        public Texture2D[] texture;
        public int num1, num2;
        public Vector2 pos1, pos2, origin;
        public int number;

        public void update()
        {

            num1 = 0;
            num2 = 0;
            int nuu = number;
            if (nuu > 10)
            {
                for (int i = 0; i < 10; i++)
                {
                    if (number >= (i * 10))
                    {
                        num1 = i;
                    }
                    else break;
                }
            }
            nuu -= num1 * 10;
            for (int i = 0; i < 10; i++)
            {
                if (nuu >= i)
                {
                    num2 = i;
                }
                else break;
            }

        }
        public void draw()
        {
            if (number > 9) Game1.spriteBatch.Draw(texture[num1], pos1, origin: origin);
            Game1.spriteBatch.Draw(texture[num2], pos2, origin: origin);
        }
    }

    public class Game1 : Game
    {
        GraphicsDeviceManager graphics;
        public static SpriteBatch spriteBatch;
        FPS_counter counter;
        numbers Numb;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            counter = new FPS_counter();
            Numb = new numbers();
        }

        protected override void Initialize()
        {
            base.Initialize();
        }

        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);
            Numb.texture = new Texture2D[10];
            for (int i = 0; i < 10; i++)
            {
                Numb.texture[i] = Content.Load<Texture2D>(("" + i));
            }
            Numb.num1 = 0;
            Numb.num2 = 0;
            Numb.number = 22;
            Numb.pos1 = new Vector2(250, 50);
            Numb.pos2 = new Vector2(270, 50);
            Numb.origin = new Vector2(10, 10);

        }

        protected override void UnloadContent()
        {
        }

        protected override void Update(GameTime gameTime)
        {
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
                Exit();

            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            spriteBatch.Begin();
            counter.in_Secs = (float)gameTime.ElapsedGameTime.TotalSeconds;
            counter.add_frame();
            Numb.number = counter.fps_toshow;
            Numb.update();
            Numb.draw();
            spriteBatch.End();

            base.Draw(gameTime);
        }
    }
}

抱歉英语不好,我来自波兰。

【问题讨论】:

  • 考虑到内容管理器处理的是什么,即资产,它占用大量堆空间也就不足为奇了。这是可以预料的。您是否有理由认为这是您的问题?
  • Gc 收藏每 1.5 分钟就会落后一次,所以是的。
  • 我什至尝试这些:MONO_GC_PARAMS=nursery-size=32m MONO_GC_PARAMS=soft-heap-limit=128m 但是 dalvikvm gc concurrent 也在做同样的事情
  • 或者如果有什么办法可以避免GC,我会试试的。

标签: c# mono garbage-collection xna monogame


【解决方案1】:

简而言之,你可能运气不好

但是,有些事情你可以尝试。

与每个图形程序一样,存储的资产可能会堆积如山。因此,提高性能的最佳方法是仅从内容管理器加载您需要的内容。考虑到您的程序在垃圾收集方面滞后,您希望在完成资产后将超出您需要的内容加载到堆中而不释放它。因此,当 GC 时间到来时,它必须清除占用的 77% 的堆,并在您的代码请求该内存时重新分配它。

那你应该怎么解决呢?

您可能需要编写一个内存管理器。保留对您的内容管理器的静态引用,但具有请求将资产加载到您的堆中的方法。这应该有望减少任何额外的堆使用,但是您还应该包含逻辑以在完成使用它们时从堆中清除或替换这些资产。 您不想避免垃圾收集,但要对其进行优化。我会厌倦任何时候调用 new 对象创建,因为您可能能够存储以前未更改的资产(纹理、图形、数据...)在您的内存管理器中。这可以避免不必要的堆填充并防止垃圾收集的负担。

使用图形程序进行内存管理可能会很棘手,但我希望这能帮助您找到正确的方向。

【讨论】:

    猜你喜欢
    • 2018-11-23
    • 2020-02-25
    • 1970-01-01
    • 1970-01-01
    • 2015-02-13
    • 1970-01-01
    • 2021-01-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多