内存中为新对象保留的字节

发布于 2024-12-14 20:25:46 字数 292 浏览 2 评论 0原文

AFAIK,所有类型均源自

 System.Object class.

考虑到这一点,我如何计算以下代码占用了多少字节:

Employee emp = new Employee("emp_name");

以及

 List<string> empList = new List<string>();

计算它们占用的字节的最佳和适当的方法是什么?

AFAIK, all types are derived from

 System.Object class.

Considering this, how can I calculate how many bytes the following code is taking:

Employee emp = new Employee("emp_name");

and

 List<string> empList = new List<string>();

What is the best and appropriate method to calculate the bytes they are taking?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

烟花易冷人易散 2024-12-21 20:25:46

您可以使用 C# sizeof 运算符,但它非常有限,因为您必须在编译时指定类型,并且它只能用于内置类型。对于您的Employee类,您可以将它们添加在一起以确定类的大小。但是,Employee 类中的所有引用类型(如 String)都是在堆上单独分配的,您必须添加这些对象的大小才能获得总大小。

通过一些 IL 技巧,您可以使用以下方法来计算值类型 (struct) 需要多少字节。对于引用类型,它将始终返回引用的大小(32 位上为 4 个字节):

public int GetSizeOf(Type type) {
  // Create a new method.
  var method = new DynamicMethod(
    "GetSizeOf",
    typeof(UInt32),
    new Type[0],
    GetType(),
    false
  );

  // Call sizeof(type) and return the result.
  ILGenerator generator = method.GetILGenerator();
  generator.Emit(OpCodes.Sizeof, type);
  generator.Emit(OpCodes.Ret);

  // Invoke the method.
  var func = (Func<UInt32>) method.CreateDelegate(typeof(Func<UInt32>));
  return checked((Int32) func());
}

但是,即使使用 sizeof 来计算字节也不完全准确。堆上的对象将有一个附加的类型句柄,类似于 C++ 中的 vtable 指针。具体如何完成此操作是 .NET 运行时的实现细节。

You can use the C# sizeof operator but it is quite limited because you have to specify the type at compile time and it can only be used on built-in types. For you Employee class you can add these together to determine the size of class. However, all reference types in the Employee class (like String) are separately allocated on the heap and you will have to add the size of these objects to get the total size.

With some IL trickery you can use the following method to compute how many bytes a value type (struct) requires. For reference types it will always return the size of a reference (4 bytes on 32 bit):

public int GetSizeOf(Type type) {
  // Create a new method.
  var method = new DynamicMethod(
    "GetSizeOf",
    typeof(UInt32),
    new Type[0],
    GetType(),
    false
  );

  // Call sizeof(type) and return the result.
  ILGenerator generator = method.GetILGenerator();
  generator.Emit(OpCodes.Sizeof, type);
  generator.Emit(OpCodes.Ret);

  // Invoke the method.
  var func = (Func<UInt32>) method.CreateDelegate(typeof(Func<UInt32>));
  return checked((Int32) func());
}

However, even using sizeof to compute bytes isn't entirely accurate. Objects on the heap will have an additional type handle which is like a vtable pointer in C++. Exactly how this is done is an implementation detail of the .NET runtime.

对岸观火 2024-12-21 20:25:46

好吧,根据 万斯·莫里森,没有官方方法可以确定这一点。不过,我们并没有失去所有希望,而且您确实有一些选择(在我的脑海中):

  • 二进制序列化/反序列化(如 Royi Namir 所描述)
  • 反射(递归地添加所有字段大小,直到完全发现对象图) ;或
  • 暴力(创建一个大的对象数组,使用 GC.GetTotalMemory() 静态方法在分配之前/之后测量分配的内存,然后除以数组大小)

不幸的是,所有这些解决方案只能近似分配大小,直到(如果有的话)微软正式添加这样的功能。

Well, according to none other than Vance Morrison, there is no official way to determine this. All hope is not lost though, and you do have a few options (off the top of my head):

  • binary serialization/deserialization (as described by Royi Namir)
  • reflection (recursively add up all field sizes until the object graph is fully discovered); or
  • brute force (create a large array of your objects, measure allocated memory before/after your allocation using the GC.GetTotalMemory() static method, and divide by the array size)

All of these solutions can only approximate the allocation size, unfortunately, until (if at all) Microsoft officially adds such a feature.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文