public void CacheReadReference(string cacheBlock) { this.refreshCounter++; //increment the refresh counter this.totalCacheReferences++; //Increment the total number of references we've seen in the cache so far Int32 blockIndex = -1; byte[] hashedByteValue = this.Murmur3HashFunction.ComputeHash(System.Text.Encoding.UTF8.GetBytes(cacheBlock)); UInt64 hashedValue = IntHelpers.GetUInt64(hashedByteValue, 8); if ((hashedValue & (this.modulusP - 1)) < this.thresholdT) { this.totalProcessedReferences++; GhostCacheElement ghostBlock = null; if (this.hashTableLookup.TryGetValue(hashedValue, out ghostBlock)) //O(1) { //hit, it's in the ghost cache blockIndex = this.distanceTree.IndexOfKey(ghostBlock.refreshCounter); // O(log n) Int32 scaledReuseDistance = (Int32)Math.Round((double)blockIndex / this.samplingRateR); ghostBlock.refreshCounter = this.refreshCounter; //update counter in the block //update the counter at its current depth Debug.Assert(this.reuseAccessHistogram[scaledReuseDistance] + 1 < UInt32.MaxValue); //make sure we don't overflow the counter this.reuseAccessHistogram[scaledReuseDistance] += 1; //Move it to the right place in the stack (new counter value == "0th position") this.distanceTree.RemoveAt(blockIndex); //O(log n) this.distanceTree.Add(this.refreshCounter, ghostBlock); //O(log n) } else { this.Evict(); //check if we need to free up space (should rarely have to...) ghostBlock = new GhostCacheElement(refreshCounter, hashedValue); this.distanceTree.Add(refreshCounter, ghostBlock); this.hashTableLookup.Add(hashedValue, ghostBlock); this.coldMisses++; //this is only true (ie: a cold miss) until the ghost cache has to start evicting things } } }
public byte[] ComputeHash(byte[] bb) { ulong h1 = 0L; ulong h2 = 0L; h1 = seed; ulong length = 0L; int pos = 0; ulong remaining = (ulong)bb.Length; // read 128 bits, 16 bytes, 2 longs in eacy cycle while (remaining >= READ_SIZE) { ulong k1 = IntHelpers.GetUInt64(bb, pos); pos += 8; ulong k2 = IntHelpers.GetUInt64(bb, pos); pos += 8; length += READ_SIZE; remaining -= READ_SIZE; //Used to be MixBody(k1, k2); k1 *= C1; k1 = IntHelpers.RotateLeft(k1, 31); k1 *= C2; h1 ^= k1; //was h1 ^= MixKey1(k1); h1 = IntHelpers.RotateLeft(h1, 27); h1 += h2; h1 = h1 * 5 + 0x52dce729; k2 *= C2; k2 = IntHelpers.RotateLeft(k2, 33); k2 *= C1; h2 ^= k2; //was h2 ^= MixKey2(k2); h2 = IntHelpers.RotateLeft(h2, 31); h2 += h1; h2 = h2 * 5 + 0x38495ab5; } // if the input MOD 16 != 0 if (remaining > 0) { //ProcessBytesRemaining(bb, remaining, pos); ulong j1 = 0; ulong j2 = 0; length += remaining; // little endian (x86) processing switch (remaining) { case 15: j2 ^= (ulong)bb[pos + 14] << 48; // fall through goto case 14; case 14: j2 ^= (ulong)bb[pos + 13] << 40; // fall through goto case 13; case 13: j2 ^= (ulong)bb[pos + 12] << 32; // fall through goto case 12; case 12: j2 ^= (ulong)bb[pos + 11] << 24; // fall through goto case 11; case 11: j2 ^= (ulong)bb[pos + 10] << 16; // fall through goto case 10; case 10: j2 ^= (ulong)bb[pos + 9] << 8; // fall through goto case 9; case 9: j2 ^= (ulong)bb[pos + 8]; // fall through goto case 8; case 8: j1 ^= bb.GetUInt64(pos); break; case 7: j1 ^= (ulong)bb[pos + 6] << 48; // fall through goto case 6; case 6: j1 ^= (ulong)bb[pos + 5] << 40; // fall through goto case 5; case 5: j1 ^= (ulong)bb[pos + 4] << 32; // fall through goto case 4; case 4: j1 ^= (ulong)bb[pos + 3] << 24; // fall through goto case 3; case 3: j1 ^= (ulong)bb[pos + 2] << 16; // fall through goto case 2; case 2: j1 ^= (ulong)bb[pos + 1] << 8; // fall through goto case 1; case 1: j1 ^= (ulong)bb[pos]; // fall through break; default: throw new Exception("Something went wrong with remaining bytes calculation."); } j1 *= C1; j1 = IntHelpers.RotateLeft(j1, 31); j1 *= C2; h1 ^= j1; j2 *= C2; j2 = IntHelpers.RotateLeft(j2, 33); j2 *= C1; h2 ^= j2; } ///////////////////////////////////// //// BELOW WAS ALL return Hash; ///////////////////////////////////// h1 ^= length; h2 ^= length; h1 += h2; h2 += h1; //h1 = Murmur3.MixFinal(h1); h1 ^= h1 >> 33; h1 *= 0xff51afd7ed558ccdL; h1 ^= h1 >> 33; h1 *= 0xc4ceb9fe1a85ec53L; h1 ^= h1 >> 33; //h2 = Murmur3.MixFinal(h2); h2 ^= h2 >> 33; h2 *= 0xff51afd7ed558ccdL; h2 ^= h2 >> 33; h2 *= 0xc4ceb9fe1a85ec53L; h2 ^= h2 >> 33; h1 += h2; h2 += h1; var hash = new byte[Murmur3.READ_SIZE]; Array.Copy(BitConverter.GetBytes(h1), 0, hash, 0, 8); Array.Copy(BitConverter.GetBytes(h2), 0, hash, 8, 8); return(hash); }