public void Value_HashCheck() { byte partitionBits = 1; int id = 1253432; // Get Value, Hash, and Partition Index Value idValue = Value.Create(id); int hash = idValue.GetHashCode(); int partition = PartitionMask.IndexOfHash(hash, partitionBits); // Verify Matches reports consistently with IndexOfHash PartitionMask mask = PartitionMask.BuildSet(partitionBits)[partition]; string maskName = mask.ToString(); Assert.IsTrue(mask.Matches(hash)); // Verify Value.Assign hash is consistent Value n = Value.Create(null); n.Assign(id); int hashViaAssign = n.GetHashCode(); Assert.AreEqual(hash, hashViaAssign); // Get Hash of unwrapped value [debuggability] int wrongHash = id.GetHashCode(); int wrongPartition = PartitionMask.IndexOfHash(wrongHash, partitionBits); }
/// <summary> /// Creates a new table large enough to hold the number of items specified /// </summary> /// <param name="tableName">name of the table</param> /// <param name="requiredItemCount">number of items the table is required to hold (it may be capable of holding more); this will dictate the partition count</param> public Table(string tableName, long requiredItemCount) : this() { this.Name = tableName; // Translate the item limit to a number of partition bits (64k items per partition) _partitionBits = (byte)Math.Max(Math.Ceiling(Math.Log(requiredItemCount, 2)) - 16, 0); // Create the partitions PartitionMask[] maskSet = PartitionMask.BuildSet(_partitionBits); _partitions.Clear(); for (int i = 0; i < maskSet.Length; ++i) { Partition p = new Partition(maskSet[i]); _partitions.Add(p); } }
/// <summary> /// Creates a new table large enough to hold the number of items specified /// </summary> /// <param name="tableName">name of the table</param> /// <param name="requiredItemCount">number of items the table is required to hold (it may be capable of holding more); this will dictate the partition count</param> public Table(string tableName, long requiredItemCount) : this() { this.Name = tableName; // Pad the min row count by 5% to account for imperfect distribution of items // based on the hashing algorithm. long paddedMinItemCount = (long)(requiredItemCount * 1.05); // Translate the item limit to a number of partition bits (64k items per partition) _partitionBits = (byte)Math.Max(Math.Ceiling(Math.Log(requiredItemCount, 2)) - 16, 0); // Create the partitions PartitionMask[] maskSet = PartitionMask.BuildSet(_partitionBits); _partitions.Clear(); for (int i = 0; i < maskSet.Length; ++i) { Partition p = new Partition(maskSet[i]); _partitions.Add(p); } }
public void PartitionMask_GetHashIndex() { const byte bitsPerByte = 8; byte bitCount = 2; Assert.AreEqual("00, 01, 10, 11", String.Join(", ", (IEnumerable <PartitionMask>)PartitionMask.BuildSet(bitCount))); for (byte b = 0; b < byte.MaxValue; ++b) { int value = b << (32 - bitsPerByte); // shift so the test value is in the highest bits int expectedIndex = b >> (8 - bitCount); Assert.AreEqual(expectedIndex, PartitionMask.IndexOfHash(value, bitCount)); } }
public void PartitionMask_BuildSet() { Assert.AreEqual("", String.Join(", ", (IEnumerable <PartitionMask>)PartitionMask.BuildSet(0))); Assert.AreEqual("0, 1", String.Join(", ", (IEnumerable <PartitionMask>)PartitionMask.BuildSet(1))); Assert.AreEqual("00, 01, 10, 11", String.Join(", ", (IEnumerable <PartitionMask>)PartitionMask.BuildSet(2))); }