【问题标题】:Memory taken from a c# object从 c# 对象中获取的内存
【发布时间】:2010-11-19 08:56:59
【问题描述】:

我想知道从“对象”继承并且没有字段/属性的对象占用多少内存?我猜方法不会。正确的 ?我说的是 .net 对象。

【问题讨论】:

  • 好问题。我会说创建几百万个,然后查看前后的内存差异。除非有人已经这样做了。
  • 这就是我问的原因。我需要知道具有数百万个对象的应用程序的内存使用情况。所以 32 位应用程序的答案是所有字段的大小 +8 字节。

标签: .net memory oop


【解决方案1】:

好的,因为 Andrew 和 Guffa 都给出了我认为是错误的答案...

所有对象都有 8 字节的开销(在 x86 上),但也有最小大小为 12 字节。我不知道为什么...但这意味着这两个类每个实例占用 12 个字节:

public class OneField
{
    private int field;
}

public class NoFields
{
}

测试:

using System;

public class OneField
{
    private int field;
}

public class NoFields {}

public class Test
{
    static void Main(string[] args)
    {
        int size = int.Parse(args[0]);
        switch (args[1])
        {
            case "NoFields":
                TestNoFields(size);
                break;
            case "OneField":
                TestOneField(size);
                break;
        }
    }

    static void TestNoFields(int size)
    {
        NoFields[] array = new NoFields[size];
        long start = GC.GetTotalMemory(true);
        for (int i=0; i < size; i++)
        {
            array[i] = new NoFields();
        }
        long end = GC.GetTotalMemory(true);
        GC.KeepAlive(array);
        Console.WriteLine("Size per instance: {0}",
                          (end-start) / (double)size);
    }

    static void TestOneField(int size)
    {
        OneField[] array = new OneField[size];
        long start = GC.GetTotalMemory(true);
        for (int i=0; i < size; i++)
        {
            array[i] = new OneField();
        }
        long end = GC.GetTotalMemory(true);
        GC.KeepAlive(array);
        Console.WriteLine("Size per instance: {0}",
                          (end-start) / (double)size);
    }
}

这很难看,因为我故意不使用任何泛型类型或任何其他可能导致问题的东西。一些测试运行:

>test 1000000 NoFields
Size per instance: 12.000024
>test 1000000 OneField
Size per instance: 12.000024
>test 1000 NoFields
Size per instance: 12
>test 1000 OneField
Size per instance: 12

(JITting 开销等解释了为什么这个数字并不总是一个精确的整数 - 因此我用浮点数进行除法。)

使用额外的 int 字段进行测试显示使用率高达 16,这证明它实际上在做一些明智的事情:)

【讨论】:

  • 关于最小 12 字节的好点,但我确实认为问题的精神与从System.Object“继承”的确切信息有关。你是对的,虽然在 x86 上,第一个字段可以说是“免费的”,但没有 System.Object 的开销,前 3 个字段可能是免费的 :) 不过,为这个重要的区别 +1 给你。跨度>
【解决方案2】:

一个对象有两个附加到它自己的数据的引用/指针。

因此,在 32 位系统上,对象需要 8 个字节,在 64 位系统上需要 16 个字节。

更正:
正如 Jon 所说,一个对象的最小大小是 12 个字节。到目前为止我发现的信息表明 GC 需要这个。

【讨论】:

  • 不——由于某种原因,x86 上的最小对象大小为 12 字节,但您会得到第一个字段“免费”:)
  • 根据msdn.microsoft.com/en-us/magazine/cc163791.aspx,由于某种原因,GC 要求对象至少为 12 个字节。
【解决方案3】:

引用类型会产生的唯一开销是类型对象指针的 4 个字节和同步块索引的 4 个字节。

所以总共有 8 个字节的开销。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多