C#将变量复制到缓冲区而不创建垃圾?
在C#.Net(3.5及以上版本)中,是否可以将变量复制到byte[]缓冲区,而不在过程中创建任何垃圾 例如:C#将变量复制到缓冲区而不创建垃圾?,c#,.net,buffer,C#,.net,Buffer,在C#.Net(3.5及以上版本)中,是否可以将变量复制到byte[]缓冲区,而不在过程中创建任何垃圾 例如: int variableToCopy = 9861; byte[] buffer = new byte[1024]; byte[] bytes = BitConverter.GetBytes(variableToCopy); Buffer.BlockCopy(bytes, 0, buffer, 0, 4); float anotherVariableToCopy = 6743897
int variableToCopy = 9861;
byte[] buffer = new byte[1024];
byte[] bytes = BitConverter.GetBytes(variableToCopy);
Buffer.BlockCopy(bytes, 0, buffer, 0, 4);
float anotherVariableToCopy = 6743897.6377f;
bytes = BitConverter.GetBytes(anotherVariableToCopy);
Buffer.BlockCopy(bytes, 0, buffer, 4, sizeof(float));
...
创建字节[]字节中间对象,该对象将成为垃圾(假定不再保留引用)
我想知道是否可以使用位运算符将变量直接复制到缓冲区中,而不创建中间字节[]?为什么不能执行以下操作:
byte[] buffer = BitConverter.GetBytes(variableToCopy);
请注意,这里的数组不是原始Int32的间接存储,它实际上是一个副本
您可能担心示例中的字节
等同于:
unsafe
{
byte* bytes = (byte*) &variableToCopy;
}
。。但我向你保证,事实并非如此;它是源Int32中字节的逐字节副本
编辑:
根据您的编辑,我认为您需要这样的内容(需要不安全的上下文):
public不安全静态void CopyBytes(int值,byte[]目标,int偏移量)
{
如果(目标==null)
抛出新的ArgumentNullException(“目标”);
if(偏移量<0 | |(偏移量+sizeof(int)>destination.Length))
抛出新ArgumentOutOfRangeException(“偏移量”);
固定(字节*ptrToStart=目的地)
{
*(int*)(ptrToStart+offset)=值;
}
}
使用指针是最好、最快的方法:
您可以使用任意数量的变量执行此操作,没有浪费内存,fixed语句有一点开销,但它太小了
int v1 = 123;
float v2 = 253F;
byte[] buffer = new byte[1024];
fixed (byte* pbuffer = buffer)
{
//v1 is stored on the first 4 bytes of the buffer:
byte* scan = pbuffer;
*(int*)(scan) = v1;
scan += 4; //4 bytes per int
//v2 is stored on the second 4 bytes of the buffer:
*(float*)(scan) = v2;
scan += 4; //4 bytes per float
}
因为与我的示例不同,我的缓冲区需要保存许多变量——我将更新我的问题是的,这是可能的,但在我看来,您似乎在过早地进行优化。在方法调用中创建的垃圾(如小字节数组等)都是Gen 0对象,很可能在几毫秒内或更短时间内收集。CLR中的临时对象分配和收集非常有效。第0代对象是什么?(出于您的担忧-我不认为优化还为时过早-我不确定自己听起来是什么样子-我正在编写一个供手机使用的库,并使用缓冲区100,可能每秒使用数千次-GC关注的是此类资源受限的设备)。这是一个问题,但直到你测量它。如果你没有测量它,你就不知道。即使是最好的工程师也常常对测量后的真正性能瓶颈感到惊讶。Gen0是“一代”GC用于跟踪最新创建的对象。大多数工作负载都有分配、使用大量对象然后超出范围的模式。在执行GC而不是整个堆时,查看这组受限制的对象是有意义的。.Net这样做,以及GC分配和收集对象的速度这是一个惊人的模式。请看:也许有什么值得一提的:注意所有固定(固定)对象。它们可能会导致堆碎片,最终可能会使用更多内存。
int v1 = 123;
float v2 = 253F;
byte[] buffer = new byte[1024];
fixed (byte* pbuffer = buffer)
{
//v1 is stored on the first 4 bytes of the buffer:
byte* scan = pbuffer;
*(int*)(scan) = v1;
scan += 4; //4 bytes per int
//v2 is stored on the second 4 bytes of the buffer:
*(float*)(scan) = v2;
scan += 4; //4 bytes per float
}