private void FlushTimings(SqlCeResultSet resultSet) { foreach(KeyValuePair<int, List<long>> timingKvp in m_timings) { if(timingKvp.Value.Count == 0) continue; int funcOrdinal = resultSet.GetOrdinal("FunctionId"); int minOrdinal = resultSet.GetOrdinal("RangeMin"); int maxOrdinal = resultSet.GetOrdinal("RangeMax"); int hitsOrdinal = resultSet.GetOrdinal("HitCount"); for(int t = 0; t < timingKvp.Value.Count; ++t) { bool foundBin = true; long time = timingKvp.Value[t]; if(!resultSet.Seek(DbSeekOptions.BeforeEqual, timingKvp.Key, time)) { foundBin = false; } if(foundBin) { resultSet.Read(); var id = resultSet.GetInt32(funcOrdinal); if(id != timingKvp.Key) { if(!resultSet.Read()) { foundBin = false; } } if(foundBin) { var min = resultSet.GetInt64(minOrdinal); var max = resultSet.GetInt64(maxOrdinal); if(id != timingKvp.Key || time < min || time > max) foundBin = false; } } if(foundBin) { //we've got a usable bin, increment and move on var hits = resultSet.GetInt32(hitsOrdinal); resultSet.SetInt32(hitsOrdinal, hits + 1); resultSet.Update(); continue; } //didn't find a bin, create a new one for this entry var row = resultSet.CreateRecord(); row[funcOrdinal] = timingKvp.Key; row[minOrdinal] = time; row[maxOrdinal] = time; row[hitsOrdinal] = 1; resultSet.Insert(row, DbInsertOptions.KeepCurrentPosition); //we need to bin-merge //start by seeking to the first record for this function if(!resultSet.Seek(DbSeekOptions.BeforeEqual, timingKvp.Key, 0.0f)) resultSet.ReadFirst(); else resultSet.Read(); var mergeId = resultSet.GetInt32(funcOrdinal); if(mergeId != timingKvp.Key) resultSet.Read(); mergeId = resultSet.GetInt32(funcOrdinal); //we know at least one exists, cause we just inserted one Debug.Assert(mergeId == timingKvp.Key); //Search for the merge that produces the smallest merged bucket long lastMin = resultSet.GetInt64(minOrdinal); int lastHits = resultSet.GetInt32(hitsOrdinal); bool shouldMerge = resultSet.Read(); //these store all the data about the best merge so far long smallestRange = long.MaxValue; long bestMin = 0; long bestMax = 0; int mergedHits = 0; for(int b = 0; b < kTimingBuckets && shouldMerge; ++b) { long max = resultSet.GetInt64(maxOrdinal); long range = max - lastMin; if(range < smallestRange) { smallestRange = range; bestMin = lastMin; bestMax = max; mergedHits = lastHits + resultSet.GetInt32(hitsOrdinal); } lastMin = resultSet.GetInt64(minOrdinal); lastHits = resultSet.GetInt32(hitsOrdinal); //if this read fails, we have insufficient buckets to bother merging shouldMerge = resultSet.Read(); } if(shouldMerge) { //seek to the first (lower) bin resultSet.Seek(DbSeekOptions.FirstEqual, timingKvp.Key, bestMin); resultSet.Read(); //expand this bin to include the next one resultSet.SetInt64(maxOrdinal, bestMax); resultSet.SetInt32(hitsOrdinal, mergedHits); //go to the now redundant bin resultSet.Update(); resultSet.Read(); //delete the bin resultSet.Delete(); } } #if FALSE //DEBUG ONLY HACK: display buckets if(!resultSet.Seek(DbSeekOptions.BeforeEqual, timingKvp.Key, 0.0f)) resultSet.ReadFirst(); else resultSet.Read(); var tempId = resultSet.GetInt32(funcOrdinal); if(tempId != timingKvp.Key) resultSet.Read(); Console.WriteLine("Buckets for function {0}:", timingKvp.Key); for(int b = 0; b < kTimingBuckets; ++b) { long min = resultSet.GetInt64(minOrdinal); long max = resultSet.GetInt64(maxOrdinal); int hits = resultSet.GetInt32(hitsOrdinal); Console.WriteLine("[{0}, {1}]: {2}", min, max, hits); resultSet.Read(); } #endif } }
private void FlushTimings(SqlCeResultSet resultSet) { foreach (KeyValuePair <int, List <long> > timingKvp in m_timings) { if (timingKvp.Value.Count == 0) { continue; } int funcOrdinal = resultSet.GetOrdinal("FunctionId"); int minOrdinal = resultSet.GetOrdinal("RangeMin"); int maxOrdinal = resultSet.GetOrdinal("RangeMax"); int hitsOrdinal = resultSet.GetOrdinal("HitCount"); for (int t = 0; t < timingKvp.Value.Count; ++t) { bool foundBin = true; long time = timingKvp.Value[t]; if (!resultSet.Seek(DbSeekOptions.BeforeEqual, timingKvp.Key, time)) { foundBin = false; } if (foundBin) { resultSet.Read(); var id = resultSet.GetInt32(funcOrdinal); if (id != timingKvp.Key) { if (!resultSet.Read()) { foundBin = false; } } if (foundBin) { var min = resultSet.GetInt64(minOrdinal); var max = resultSet.GetInt64(maxOrdinal); if (id != timingKvp.Key || time < min || time > max) { foundBin = false; } } } if (foundBin) { //we've got a usable bin, increment and move on var hits = resultSet.GetInt32(hitsOrdinal); resultSet.SetInt32(hitsOrdinal, hits + 1); resultSet.Update(); continue; } //didn't find a bin, create a new one for this entry var row = resultSet.CreateRecord(); row[funcOrdinal] = timingKvp.Key; row[minOrdinal] = time; row[maxOrdinal] = time; row[hitsOrdinal] = 1; resultSet.Insert(row, DbInsertOptions.KeepCurrentPosition); //we need to bin-merge //start by seeking to the first record for this function if (!resultSet.Seek(DbSeekOptions.BeforeEqual, timingKvp.Key, 0.0f)) { resultSet.ReadFirst(); } else { resultSet.Read(); } var mergeId = resultSet.GetInt32(funcOrdinal); if (mergeId != timingKvp.Key) { resultSet.Read(); } mergeId = resultSet.GetInt32(funcOrdinal); //we know at least one exists, cause we just inserted one Debug.Assert(mergeId == timingKvp.Key); //Search for the merge that produces the smallest merged bucket long lastMin = resultSet.GetInt64(minOrdinal); int lastHits = resultSet.GetInt32(hitsOrdinal); bool shouldMerge = resultSet.Read(); //these store all the data about the best merge so far long smallestRange = long.MaxValue; long bestMin = 0; long bestMax = 0; int mergedHits = 0; for (int b = 0; b < kTimingBuckets && shouldMerge; ++b) { long max = resultSet.GetInt64(maxOrdinal); long range = max - lastMin; if (range < smallestRange) { smallestRange = range; bestMin = lastMin; bestMax = max; mergedHits = lastHits + resultSet.GetInt32(hitsOrdinal); } lastMin = resultSet.GetInt64(minOrdinal); lastHits = resultSet.GetInt32(hitsOrdinal); //if this read fails, we have insufficient buckets to bother merging shouldMerge = resultSet.Read(); } if (shouldMerge) { //seek to the first (lower) bin resultSet.Seek(DbSeekOptions.FirstEqual, timingKvp.Key, bestMin); resultSet.Read(); //expand this bin to include the next one resultSet.SetInt64(maxOrdinal, bestMax); resultSet.SetInt32(hitsOrdinal, mergedHits); //go to the now redundant bin resultSet.Update(); resultSet.Read(); //delete the bin resultSet.Delete(); } } #if FALSE //DEBUG ONLY HACK: display buckets if (!resultSet.Seek(DbSeekOptions.BeforeEqual, timingKvp.Key, 0.0f)) { resultSet.ReadFirst(); } else { resultSet.Read(); } var tempId = resultSet.GetInt32(funcOrdinal); if (tempId != timingKvp.Key) { resultSet.Read(); } Console.WriteLine("Buckets for function {0}:", timingKvp.Key); for (int b = 0; b < kTimingBuckets; ++b) { long min = resultSet.GetInt64(minOrdinal); long max = resultSet.GetInt64(maxOrdinal); int hits = resultSet.GetInt32(hitsOrdinal); Console.WriteLine("[{0}, {1}]: {2}", min, max, hits); resultSet.Read(); } #endif } }