如何确定 C# 中非托管数组的 sizeof?
我正在尝试优化一些代码,其中我有大量包含不同大小的结构但基于相同接口的数组。在某些情况下,结构体更大并容纳更多数据,有时它们是小结构体,有时我更愿意保留 null 作为值以节省内存。
我的第一个问题是。做这样的事情是个好主意吗?我以前有一个完整数据结构的数组,但是在测试混合它时,我实际上能够节省大量内存。还有其他缺点吗?
我一直在尝试不同的东西,在制作通用接口的数组时,它似乎工作得很好,但我不确定我是否正确检查了数组的大小。
使示例变得相当简单。但在这里我向数组添加不同的结构。但我无法使用传统的 Marshal.SizeOf 方法确定大小。简单地迭代集合并计算集合中每个值的 sizeof 是否正确?
IComparable[] myCollection = new IComparable[1000];
myCollection[0] = null;
myCollection[1] = (int)1;
myCollection[2] = "helloo world";
myCollection[3] = long.MaxValue;
System.Runtime.InteropServices.Marshal.SizeOf(myCollection);
最后一行将抛出此异常:
Type 'System.IComparable[]' cannot be marshaled as an unmanaged structure; no meaningful size or offset can be computed.
请原谅这篇长文章:
- 这是一个最佳且可用的解决方案吗?
- 我怎样才能确定尺寸 我的阵列?
I'm trying to optimize some code where I have a large number of arrays containing structs of different size, but based on the same interface. In certain cases the structs are larger and hold more data, othertimes they are small structs, and othertimes I would prefer to keep null as a value to save memory.
My first question is. Is it a good idea to do something like this? I've previously had an array of my full data struct, but when testing mixing it up I would virtually be able to save lots of memory. Are there any other downsides?
I've been trying out different things, and it seams to work quite well when making an array of a common interface, but I'm not sure I'm checking the size of the array correctly.
To simplified the example quite a bit. But here I'm adding different structs to an array. But I'm unable to determine the size using the traditional Marshal.SizeOf method. Would it be correct to simply iterate through the collection and count the sizeof for each value in the collection?
IComparable[] myCollection = new IComparable[1000];
myCollection[0] = null;
myCollection[1] = (int)1;
myCollection[2] = "helloo world";
myCollection[3] = long.MaxValue;
System.Runtime.InteropServices.Marshal.SizeOf(myCollection);
The last line will throw this exception:
Type 'System.IComparable[]' cannot be marshaled as an unmanaged structure; no meaningful size or offset can be computed.
Excuse the long post:
- Is this an optimal and usable solution?
- How can I determine the size
of my array?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我可能是错的,但在我看来你的 IComparable[] 数组是一个托管数组?如果是这样,那么您可以使用此代码来获取长度
如果您正在 C# 和 C++ 之间进行平台互操作,那么您的问题标题“我可以找到非托管数组的长度”的答案是否定的,这是不可能的。 C++/C 中数组的函数签名往往遵循以下模式。
在 .NET 中,数组本身是一种类型,具有一些基本信息,例如其大小、运行时类型等...因此,
每当使用平台调用时, 我们都可以使用它要在 C# 和 C++ 之间进行互操作,您需要将数组的长度传递给接收函数,并固定数组(但这是另一个主题)。
这能回答你的问题吗?如果不是,那么请你澄清一下
I may be wrong but it looks to me like your IComparable[] array is a managed array? If so then you can use this code to get the length
If you are doing platform interop between C# and C++ then the answer to your question headline "Can I find the length of an unmanaged array" is no, its not possible. Function signatures with arrays in C++/C tend to follow the following pattern
In .NET the array itself is a type which has some basic information, such as its size, its runtime type etc... Therefore we can use this
Whenever using platform invoke to interop between C# and C++ you will need to pass the length of the array to the receiving function, as well as pin the array (but that's a different topic).
Does this answer your question? If not, then please can you clarify
最优性始终取决于您的要求。如果您确实需要存储不同类/结构的许多元素,那么您的解决方案是完全可行的。
但是,我猜您对数据结构的期望可能会产生误导:数组元素每个定义都具有相同的大小。在您的情况下也是如此:您的数组不存储元素本身,而是存储对它们的引用(指针)。这些元素分配在 VM 堆上的某个位置。所以你的数据结构实际上是这样的:它是一个包含 1000 个指针的数组,每个指针都指向一些数据。每个特定元素的大小当然可以变化。
这引出了下一个问题:数组的大小。你打算用这个尺寸做什么?您是否需要知道将数据序列化到某些持久存储时要分配多少字节?这取决于序列化格式...或者您是否只需要粗略估计您的结构消耗了多少内存?在后一种情况下,您需要考虑数组本身以及每个特定元素的大小。您在示例中给出的数组消耗的大小大约是引用大小的 1000 倍(在 32 位计算机上应为 4 字节,在 64 位计算机上应为 8 字节)。要计算每个元素的大小,您确实可以迭代数组并对特定元素的大小求和。请注意,这只是一个估计:虚拟机增加了一些内存管理开销,很难准确确定......
Optimality always depends on your requirements. If you really need to store many elements of different classes/structs, your solution is completely viable.
However, I guess your expectations on the data structure might be misleading: Array elements are per definition all of the same size. This is even true in your case: Your array doesn't store the elements themselves but references (pointers) to them. The elements are allocated somewhere on the VM heap. So your data structure actually goes like this: It is an array of 1000 pointers, each pointer pointing to some data. The size of each particular element may of course vary.
This leads to the next question: The size of your array. What are you intending to do with the size? Do you need to know how many bytes to allocate when you serialize your data to some persistent storage? This depends on the serialization format... Or do you need just a rough estimate on how much memory your structure is consuming? In the latter case you need to consider the array itself and the size of each particular element. The array which you gave in your example consumes approximately 1000 times the size of a reference (should be 4 bytes on a 32 bit machine and 8 bytes on a 64 bit machine). To compute the sizes of each element, you can indeed iterate over the array and sum up the size of the particular elements. Please be aware that this is only an estimate: The virtual machine adds some memory management overhead which is hard to determine exactly...