我有一个类,它包含两个大小相同的列表,需要转换为byte[]并将它们复制到另一个数组中。
实际上,我使用了以下代码:
var lenght = MyObject.firstList[i].Count;
for (var i = 0; i < MyObject.firstList.Count; i++)
{
BitConverter.GetBytes(MyObject.firstList[i]).CopyTo(bytes, i * sizeof(float));
BitConverter.GetBytes(MyObject.secondList[i]).CopyTo(bytes, i * sizeof(float) + lenght * sizeof(float));
}
这段代码的问题是,它总是分配大量内存,导致** GC *进行干预。
如何在不进行过多内存分配的情况下优化代码。是否有使用不安全或IntPtr或Span的最佳解决方案?
我尝试使用这个解决方案,但是出现了错误
System.AccessViolationException:‘试图读取或写入受保护的内存。这通常表明其他内存
前提:
发布于 2022-09-28 15:11:38
BitConverter.GetBytes
为每个转换的值创建一个新的字节数组,因此如果您经常使用此方法而不打算保留这些字节数组,则GC最终必须收集所有这些字节数组实例。
另一种不依赖于创建“临时”数组的方法是使用Span (Span)。现在,由于我们处理的是List而不是数组,所以将使用CollectionsMarshal.AsSpan
方法在List实例(即List实例中包含的数据)内部私有数组的使用部分上获得一个Span。
但是,这里处理的列表是List实例,因此产生的Span是一个span。Span不能直接复制到字节数组(即Span)中。因此,Span将被转换为使用MemoryMarshal.Cast
的Span。这样,列表内容的Span可以简单地复制到目标字节数组中:
using System.Runtime.InteropServices;
var bytes = new byte[(MyObject.firstList.Count + MyObject.secondList.Count) * sizeof(float)];
var list1AsByteSpan = MemoryMarshal.Cast<float, byte>(
CollectionsMarshal.AsSpan(MyObject.firstList)
);
var list2AsByteSpan = MemoryMarshal.Cast<float, byte>(
CollectionsMarshal.AsSpan(MyObject.secondList)
);
list1AsByteSpan.CopyTo(bytes);
list2AsByteSpan.CopyTo(bytes.AsSpan(MyObject.firstList.Count * sizeof(float)));
(请注意,单个浮动值的字节顺序取决于运行代码的主机系统CPU体系结构的安全性。)
我鼓励您阅读CollectionsMarshal.AsSpan和MemoryMarshal.Cast方法的链接文档,以便了解它们可能对它们的使用造成的任何限制(特别是在CollectionsMarshal.AsSpan方面)。如果您决定只复制“n”粘贴我的代码而不阅读文档,我认为这是完全没有问题的,但是忽略您可能会做的文档将是您自己的危险……;-)
https://stackoverflow.com/questions/73879731
复制相似问题