Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/299.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#内存。Span异常慢_C# - Fatal编程技术网

C#内存。Span异常慢

C#内存。Span异常慢,c#,C#,在试验新的Span和Memory功能时,我发现与其他与字节数组交互的方法相比,使用Memory解析二进制数据要慢得多 我建立了一个基准测试套件,使用多种方法从数组中读取单个整数,发现内存是最慢的。正如预期的那样,它比Span慢,但令人惊讶的是,它也比直接使用阵列慢,以及我自己开发的版本,我希望内存在内部与之类似 //比较从数组读取偏移量int的各种方法的测试套件 公共类二进制测试 { 静态字节[]arr=新字节[]{0,1,2,3,4}; 静态内存mem=arr.AsMemory(); 静态Ho

在试验新的
Span
Memory
功能时,我发现与其他与字节数组交互的方法相比,使用
Memory
解析二进制数据要慢得多

我建立了一个基准测试套件,使用多种方法从数组中读取单个整数,发现内存是最慢的。正如预期的那样,它比Span慢,但令人惊讶的是,它也比直接使用阵列慢,以及我自己开发的版本,我希望内存在内部与之类似

//比较从数组读取偏移量int的各种方法的测试套件
公共类二进制测试
{
静态字节[]arr=新字节[]{0,1,2,3,4};
静态内存mem=arr.AsMemory();
静态HomeGrowthMemy memTest=新的HomeGrowthMemy(arr);
[基准]
公共int StraightArrayBitConverter()
{
将位转换器返回到32(arr,1);
}
[基准]
公共int MemorySlice()
{
返回BinaryPrimitives.ReadInt32LittleEndian(mem.Slice(1.Span));
}
[基准]
public int MemorySliceToSize()
{
返回BinaryPrimitives.ReadInt32LittleEndian(mem.Slice(1,4.Span));
}
[基准]
公共int MemorySpanSlice()
{
返回BinaryPrimitives.ReadInt32LittleEndian(mem.Span.Slice(1));
}
[基准]
public int MemorySpanSliceToSize()
{
返回BinaryPrimitives.ReadInt32LittleEndian(mem.Span.Slice(1,4));
}
[基准]
公共int HomegrownMemorySlice()
{
返回BinaryPrimitives.ReadInt32LittleEndian(memTest.Slice(1.Span));
}
[基准]
public int HomegrownMemorySliceToSize()
{
返回BinaryPrimitives.ReadInt32LittleEndian(memTest.Slice(1,4.Span));
}
[基准]
公共int HomegrownMemorySpanSlice()
{
返回BinaryPrimitives.ReadInt32LittleEndian(memTest.Span.Slice(1));
}
[基准]
public int HomegrownMemorySpanSliceToSize()
{
返回BinaryPrimitives.ReadInt32LittleEndian(memTest.Span.Slice(1,4));
}
[基准]
公共int SpanSlice()
{
返回BinaryPrimitives.ReadInt32LittleEndian(arr.AsSpan().Slice(1));
}
[基准]
public int slicetosize()
{
返回BinaryPrimitives.ReadInt32LittleEndian(arr.AsSpan().Slice(1,4));
}
}
//个人“实现”内存,用于测试
结构HomegrownMemory
{
字节[]_arr;
国际startPos;
整数长度;
公共家庭成长内存(字节[]b)
{
这个。_arr=b;
这是._startPos=0;
这个。_长度=b.长度;
}
公共跨距Span=>\u arr.AsSpan(开始:\u startPos,长度:\u length);
公共HomegrownMemory切片(int start)
{
返回新的HomegrownMemory()
{
_arr=_arr,
_startPos=_startPos+开始,
_长度=_长度-开始
};
}
公共HomegrownMemory切片(整数开始,整数长度)
{
返回新的HomegrownMemory()
{
_arr=_arr,
_startPos=_startPos+开始,
_长度=长度
};
}
}
以下是上述代码的BenchmarkNet结果:

BenchmarkDotNet=v0.11.5, OS=Windows 10.0.17134.765 (1803/April2018Update/Redstone4)
Intel Core i7-4790K CPU 4.00GHz (Haswell), 1 CPU, 8 logical and 4 physical cores
Frequency=3984652 Hz, Resolution=250.9629 ns, Timer=TSC
.NET Core SDK=2.1.700-preview-009618
  [Host]     : .NET Core 2.1.11 (CoreCLR 4.6.27617.04, CoreFX 4.6.27617.02), 64bit RyuJIT
  DefaultJob : .NET Core 2.1.11 (CoreCLR 4.6.27617.04, CoreFX 4.6.27617.02), 64bit RyuJIT
|                         Method |      Mean |     Error |    StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|------------------------------- |----------:|----------:|----------:|------:|------:|------:|----------:|
|      StraightArrayBitConverter | 1.0832 ns | 0.0323 ns | 0.0270 ns |     - |     - |     - |         - |
|                    MemorySlice | 5.8882 ns | 0.0654 ns | 0.0612 ns |     - |     - |     - |         - |
|              MemorySliceToSize | 6.0191 ns | 0.0983 ns | 0.0919 ns |     - |     - |     - |         - |
|                MemorySpanSlice | 5.0230 ns | 0.0626 ns | 0.0555 ns |     - |     - |     - |         - |
|          MemorySpanSliceToSize | 5.0189 ns | 0.0335 ns | 0.0313 ns |     - |     - |     - |         - |
|           HomegrownMemorySlice | 3.9217 ns | 0.0419 ns | 0.0392 ns |     - |     - |     - |         - |
|     HomegrownMemorySliceToSize | 1.5233 ns | 0.0199 ns | 0.0186 ns |     - |     - |     - |         - |
|       HomegrownMemorySpanSlice | 0.8301 ns | 0.0243 ns | 0.0227 ns |     - |     - |     - |         - |
| HomegrownMemorySpanSliceToSize | 0.8303 ns | 0.0223 ns | 0.0208 ns |     - |     - |     - |         - |
|                      SpanSlice | 0.6891 ns | 0.0241 ns | 0.0214 ns |     - |     - |     - |         - |
|                SpanSliceToSize | 0.6804 ns | 0.0174 ns | 0.0163 ns |     - |     - |     - |         - |
所有这些计时对我来说都很有意义,除了
内存
计时,它们都比我预期的慢

我的理解是,
Memory
只是
Span
的一个实现,它可以存在于堆上,例如。。不是ref结构

<>我本来希望它比跨度慢,但至少比平直数组实现快一点。我用国产版本获得的结果是我在
内存中所期望的结果

关于
内存的用例
,或者它试图实现的目标,我在这里缺少了一些基本的东西吗?看到这些结果后,我的理解似乎有些偏差

编辑: 在Cowen的评论之后,我找到了内存源代码并进行了查看。在检索span时,它似乎做了很多工作,特别是检查并强制转换它的泛型对象字段,以找出它是什么类型,以便正确地强制转换

我很惊讶他们没有提供不同的内存选项和/或提供内存工厂来构造具有更强类型的内部数据字段的类。相反,他们选择了一个字段,这个字段是一个必须不断检查/浇铸以获得跨度的对象,我觉得在使用过程中应该/将会不断发生这种情况


我仍然很好奇为什么他们会这样设计内存,更重要的是,用例是什么,它是这样设计的。我觉得很多使用Span/Memory的人都在追求速度优势,而通用对象字段似乎鼓励不要使用它。

您可能需要重新设计基准,以确定罪魁祸首。第2到第5种方法都调用Memory.Span。如果您查看该方法的源代码,它相当复杂。我怀疑这种方法占用了大部分时间。谢谢你的反馈。8) 我按照你的建议看了源代码后进行了编辑。那么有人知道内存的用途吗?