【发布时间】:2011-08-11 00:45:37
【问题描述】:
我一直在寻找返回基本上由 ArraySegment 在偏移和计数方面持有的段的方法。尽管 ArraySegment 拥有完整的原始数组,但它只是将它与对段的任何更改都会反映到原始数组中这一事实来界定它。 ArraySegment 的问题或限制是它不会将段本身作为一个整体返回,我必须遍历这些值。将细分市场作为一个整体返回的最佳方式是什么?
byte[] input = new byte[5]{1,2,3,4,5};
ArraySegment<byte> delimited = new ArraySegment<byte>(input,0,2);
byte[] segment = HERE I NEED SOMETHING THAT WILL RETURN THE SEGMENT i.e. [0,1,2]
最重要的一点,segment不能是副本,而应该引用原始数组。如果对段进行了任何更改,它们必须反映在原始数组中。
非常感谢任何提示,谢谢!
分配基准:在Thomas 和digEmAll 的一些回答之后
好的,我对来自 digEmAll 和 Thomas 的代码进行了一些基准测试,令我惊讶的是,代码的速度要快得多。正是我拼命寻找的东西。这是结果。
Construct Size Elements assigned Iterations Time
_______________________________________________________________________________
ArraySegmentWrapper 1500 1500 1000000 396.3 ms
Array.Copy 1500 1500 1000000 4389.04 ms
正如你所看到的巨大差异,我很清楚我将使用 ArraySegment 的代码。以下是基准测试代码。请注意,这可能有点 偏见,因为人们会争论为什么“新”被放入循环中。我只是试图重现我目前手头的情况,尽可能多地解决它,而无需移动大部分代码。这让我很开心!
namespace ArraySegmentWrapped
{
class Program
{
public static Stopwatch stopWatch = new Stopwatch();
public static TimeSpan span = new TimeSpan();
public static double totalTime = 0.0;
public static int iterations = 1000000;
static void Main(string[] args)
{
int size = 1500;
int startIndex = 0;
int endIndex = 1499;
byte[] array1 = new byte[size];
byte[] array2 = null;
for (int index = startIndex; index < size; index++)
{
array1[index] = (byte)index;
}
ArraySegmentWrapper<byte> arraySeg;
for (int index = 0; index < iterations; index++)
{
stopWatch.Start();
arraySeg = new ArraySegmentWrapper<byte>(array1, startIndex, endIndex);
stopWatch.Stop();
totalTime += stopWatch.Elapsed.TotalMilliseconds;
}
Console.WriteLine("ArraySegment:{0:F6}", totalTime / iterations);
stopWatch.Reset();
totalTime = 0.0;
for (int index = 0; index < iterations; index++)
{
stopWatch.Start();
array2 = new byte[endIndex - startIndex + 1];
Array.Copy(array1, startIndex, array2, 0, endIndex);
stopWatch.Stop();
totalTime += stopWatch.Elapsed.TotalMilliseconds;
}
Console.WriteLine("Array.Copy:{0:F6}", totalTime / iterations);
}
}
// Code for ArraySegmentWrapper goes here
}
访问基准(更新) 因此,在Thomas 指出基准并表示访问简单数组会比 ArraySegment 更快之后,他完全正确。但是随着 digEmAll 指出我应该在发布模式下进行测试(对不起,在调试模式下测试的旧错误),我留下的代码几乎与上面相同(迭代减少了两个零 - 不能等待很长时间才能输出来吧,对不起)和一些修改以访问相同数量的元素,下面是我得到的。
Construct Size Elements accessed Iterations Time
_______________________________________________________________________________
ArraySegmentWrapper 1500 1500 1000000 5268.3 ms
Array.Copy 1500 1500 1000000 4812.4 ms
得出的结论是虽然assingment非常快,但通过ArraySegments访问却很慢。
【问题讨论】:
-
您的基准测试并没有真正意义:您只是创建了一个 ArraySegmentWrapper 实例,它不执行任何实际工作,因此它当然比在两个数组之间复制数据要快...您应该衡量的是通过 ArraySegmentWrapper 访问数据与直接在复制的数组中访问数据的性能。数组可能会更快,但当然你必须先复制数据,这不是免费的。所以你必须在创建时间和访问时间之间做出选择……
-
@Thomas,那么当我创建 ArraySegmentWrapper 的实例时,段不是也在创建吗?将段放入arraySeg。据我所知,这就是工作正在进行的地方。
-
@Wajih,创建该段的成本 nothing :它只存储对数组的引用、偏移量和计数......它实际上并不 做任何事。
-
@Thomas,准确地说,准确,这就是我们所需要的 :)
-
@Wajih:好吧,优化器和抖动毕竟可以发挥作用:D