简体   繁体   English

C#数组循环按位索引vs空检查

[英]c# array looping bitwise index vs null checking

In my project I am working with an array of objects(object[]) of a user decided length. 在我的项目中,我正在处理用户确定长度的对象数组(object [])。 It is also looped through at least a couple hundred times a second in the course of the application. 在应用过程中,它还每秒至少循环几百次。 This array also has a class associated with it that assures that any additions to it will fill the first open spot using an array that has a bit set for each occupied element. 该数组还有一个与之关联的类,该数组确保使用数组为每个占用的元素设置了位的数组添加到该数组中的所有空白。 Once assigned array entries stay where they are as it would effect tracking of the elements to move them so gaps are possible.The number of elements that may be removed or added is unknown. 一旦分配的数组条目停留在原处,将影响对元素的追踪以移动它们,因此可能存在间隙。可以删除或添加的元素数量未知。 Addition and removal happen much less frequently than the elements are looped through and accessed. 与元素循环和访问相比,添加和删除的发生频率要低得多。

What I need to know is which would provide better average performance when looping though this array... 我需要知道的是,通过该数组循环时,哪种方法可以提供更好的平均性能...

  1. Check each entry for null 检查每个条目是否为空

or 要么

  1. Call the following code to get the next index in a loop checking for the -1 to stop. 调用以下代码以获取循环中的下一个索引,以检查-1是否停止。 Tracker contains the bitwise locations of the elements. 跟踪器包含元素的按位位置。 The function only needs to run once per filled element. 该功能只需要为每个填充的元素运行一次。 The &= line and the subtraction on the following line yields the integer value of the lowest bit set. &=行和下一行的减法产生最低位集的整数值。 The DeBruijn sequence bit performs a log base 2 to get the bit position. DeBruijn序列位执行对数基数2以获取位位置。

     private List<Int32> Tracker = new List<Int32>(); private int EnumTemp; private int EnumTemp2; private int EnumResult; private int EnumIndex = -1; //from http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogDeBruijn protected internal static readonly Int32[] MultiplyDeBruijnBitPosition2 = { 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9 }; public int NextIndex() { if (EnumIndex == -1) { EnumTemp = Tracker[0]; EnumIndex = 0; } while (EnumTemp == 0) { if (EnumIndex == Tracker.Count -1) { EnumIndex = -1; return -1; } EnumIndex++; EnumTemp = Tracker[EnumIndex]; } EnumTemp2 &= EnumTemp - 1; EnumResult = Engine.MultiplyDeBruijnBitPosition2[(UInt32)((EnumTemp-EnumTemp2) * 0x077CB531U) >> 27]; EnumResult += (EnumIndex * 32); EnumTemp = EnumTemp2; return EnumResult; } } 

    Assume the the array element will be accessed and stored in a temporary variable in both cases. 假定在两种情况下都将访问数组元素并将其存储在一个临时变量中。

There is a point where the speed of checking x null-rows for null will be slower as quickstepping with the tracker. 有时候,随着跟踪器的快速执行,检查x个空行是否为空的速度会变慢。 You need to have some idea of how large the gaps will be. 您需要对差距有多大的了解。 But my gut feeling says there should be pretty large gaps (say 5 times more empty rows as filled rows) before this will help. 但是我的直觉认为应该有很大的空隙(例如,空行是填充行的5倍),这才有帮助。 As for why I think this; 至于我为什么这么认为;

  • Array access is sequentially and perfectly prefetched. 顺序访问和完美地预取数组访问。 So the first y entries after a filled one are in cache already. 因此,已填充条目之后的前y个条目已在缓存中。 Skipping them will not prevent memory accesses 跳过它们不会阻止内存访问

  • Null checks are very fast. 空检查非常快。 The tracker is 'complex' when compared to that 与之相比,跟踪器是“复杂的”

  • Your code becomes much more complex for possible very little gain. 您的代码变得非常复杂,可能获得的收益很少。

  • I think a doublylinkedlist might be faster in your case as it will feature no gaps at all and can be looped through efficiently. 我认为双向链表在您的情况下可能会更快,因为它根本没有任何间隙,并且可以高效地遍历。 You do not need the spot in the array then as you can remove the object using the linkedlistreference. 这样就不需要阵列中的点,因为可以使用linkedlistreference删除对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM