【问题标题】:GC Alloc for unknown reasonGC Alloc 原因不明
【发布时间】:2017-10-17 11:46:23
【问题描述】:

我有这个问题:

 public void WriteArgs(object[] args)
    {
        for (var i = 0; i < args.Length; i++)
        {
            Stream.WriteObject(args[i]);
        }
    }

它为 50 个调用 (screen) 分配 2 KB。这怎么可能?这个方法的哪一部分是分配内存? (在此屏幕上,您可以看到 Stream.WriteObject(args[i]); 正在分配 9.4,所以 2KB 是由 WriteArgs 自己分配的)

【问题讨论】:

  • 你正在使用Stream,这是一个非托管资源
  • Stream是什么类型的?
  • 你为什么关心2KB?您是否在内存受限的环境中运行?
  • 这是 MemoryStream
  • @mjwills 它是每个对象的每帧,我必须关心每一个字节;)

标签: c# unity3d memory memory-management garbage-collection


【解决方案1】:

一个大嫌疑人是object[] args 参数中的object。这看起来像是装箱和拆箱问题。

当您调用WriteArgs 函数并向其传递一些内容时,它会执行装箱 将该参数转换为object


不确定Stream.WriteObject 是什么或者你从哪里得到的,但是如果它也将object 作为参数并且当它进入WriteArgs 函数时,它也会执行拆箱为了使用传递给它的变量。 装箱拆箱都分配内存。

修复

删除 object[] args 并为您的 WriteArgs 函数创建多个重载,这些重载可以处理不同的对象类型作为参数。

此外,如果您编写了 Stream.WriteObject,请对其执行相同操作或为其找到替代功能。您可以阅读更多关于 boxingunboxing here.

编辑:

上述装箱和拆箱问题仅适用于Value Types。如果您已经将Reference Type 传递给该函数,那么这里唯一的问题就是Stream.WriteObject 函数。

【讨论】:

  • 只有当相关对象是值类型时才会进行装箱和拆箱。
  • @Servy 是的,但我们不知道传递给该函数的是什么。OP 没有在问题中显示这一点。
  • 然而你说这个值是always装箱的,而always是unboxed的,这是完全错误的。如果您认为问题没有包含足够的信息来发布正确的答案,那么不要发布答案,直到问题得到足够的澄清可以回答。
  • 谢谢,我不能赞成您的回答,但您的怀疑可能是正确的,因为 'object[] args' 包含对象。
  • @Servy 我没有收到关于您最后评论的通知。请注意,我没有像您在评论中提到的那样说“总是”。我只是错过了提及我添加的值类型,但这并不意味着“总是”。该问题代码+屏幕截图日志中的内容足以让我回答。请阅读以下内容:
猜你喜欢
  • 1970-01-01
  • 2016-03-31
  • 1970-01-01
  • 2014-05-12
  • 2022-06-24
  • 2021-12-19
  • 2014-04-12
  • 1970-01-01
  • 2010-11-11
相关资源
最近更新 更多