public void WindowDirectAndIndirectSpanOpBenchmark() { Settings.DoAdditionalCorrectnessChecks = false; var count = 100000; var width = 20; var sm = new SortedMap <int, double>(); sm.Add(0, 0); // make irregular, it's faster but more memory for (int i = 2; i <= count; i++) { sm.Add(i, i); } var op = new WindowOnlineOp <int, double, SortedMapCursor <int, double> >(); var spanOp = new SpanOpCount <int, double, Range <int, double, SortedMapCursor <int, double> >, SortedMapCursor <int, double>, WindowOnlineOp <int, double, SortedMapCursor <int, double> > >(20, false, op); var window = new SpanOpImpl <int, double, Range <int, double, SortedMapCursor <int, double> >, SpanOpCount <int, double, Range <int, double, SortedMapCursor <int, double> >, SortedMapCursor <int, double>, WindowOnlineOp <int, double, SortedMapCursor <int, double> > >, SortedMapCursor <int, double> >(sm.GetEnumerator(), spanOp).Source .Map(x => { var sum = 0.0; var c = 0; foreach (var keyValuePair in x.Source) { sum += keyValuePair.Value; c++; } return(sum / c); // x.CursorDefinition.Count TODO }); var spanOpCombined = new SpanOp <int, double, Range <int, double, SortedMapCursor <int, double> >, SortedMapCursor <int, double>, WindowOnlineOp <int, double, SortedMapCursor <int, double> > >(20, false, op, sm.comparer); var windowCombined = new SpanOpImpl <int, double, Range <int, double, SortedMapCursor <int, double> >, SpanOp <int, double, Range <int, double, SortedMapCursor <int, double> >, SortedMapCursor <int, double>, WindowOnlineOp <int, double, SortedMapCursor <int, double> > >, SortedMapCursor <int, double> >(sm.GetEnumerator(), spanOpCombined).Source .Map(x => { var sum = 0.0; var c = 0; foreach (var keyValuePair in x.Source) { sum += keyValuePair.Value; c++; } return(sum / c); // x.CursorDefinition.Count TODO }); var windowExtension = sm.Window(width).Map(x => { var sum = 0.0; var c = 0; foreach (var keyValuePair in x) { sum += keyValuePair.Value; c++; } return(sum / c); // x.CursorDefinition.Count TODO }); for (int round = 0; round < 20; round++) { double sum1 = 0.0; using (Benchmark.Run("Window SpanOpCount", count * width)) { foreach (var keyValuePair in window) { sum1 += keyValuePair.Value; } } double sum2 = 0.0; using (Benchmark.Run("Window SpanOp", count * width)) { foreach (var keyValuePair in windowCombined) { sum2 += keyValuePair.Value; } } double sum3 = 0.0; using (Benchmark.Run("Window Extension", count * width)) { foreach (var keyValuePair in windowExtension) { sum3 += keyValuePair.Value; } } Assert.AreEqual(sum1, sum2); Assert.AreEqual(sum1, sum3); } Benchmark.Dump($"The window width is {width}."); }
public void CouldCalculateSMAWithCount() { var count = 20; var sm = new SortedMap <int, double>(); for (int i = 1; i <= count; i++) { sm.Add(i, i); } DoTest(true); DoTest(false); DoTestViaSpanOpCount(true); DoTestViaSpanOpCount(false); void DoTest(bool allowIncomplete) { // TODO separate tests/cases for true/false var smaOp = new MAvgCount <int, double, SortedMapCursor <int, double> >(10, allowIncomplete); var smaCursor = new SpanOpImpl <int, double, double, MAvgCount <int, double, SortedMapCursor <int, double> >, SortedMapCursor <int, double> >(sm.GetEnumerator(), smaOp); // this monster type must be hidden in the same way Lag hides its implementation Series <int, double, SpanOpImpl <int, double, double, MAvgCount <int, double, SortedMapCursor <int, double> >, SortedMapCursor <int, double> > > smaSeries; smaSeries = smaCursor.Source; var sm2 = smaSeries.ToSortedMap(); Assert.AreEqual(sm2.First, smaSeries.First); Assert.AreEqual(sm2.Last, smaSeries.Last); Assert.True(SeriesContract.MoveAtShouldWorkOnLazySeries(smaSeries)); Assert.True(SeriesContract.ClonedCursorsAreIndependent(smaSeries)); if (!allowIncomplete) { var trueSma = sm.Window(10).Map(x => x.Values.Average()); Assert.True(trueSma.Keys.SequenceEqual(smaSeries.Keys)); Assert.True(trueSma.Values.SequenceEqual(smaSeries.Values)); } Debug.WriteLine("SMA"); foreach (var keyValuePair in smaSeries) { Debug.WriteLine($"{keyValuePair.Key} - {keyValuePair.Value}"); } } void DoTestViaSpanOpCount(bool allowIncomplete) { // TODO separate tests/cases for true/false var onlineOp = new SumAvgOnlineOp <int, double, SortedMapCursor <int, double> >(); var smaOp = new SpanOpCount <int, double, double, SortedMapCursor <int, double>, SumAvgOnlineOp <int, double, SortedMapCursor <int, double> > >(10, allowIncomplete, onlineOp); var smaCursor = new SpanOpImpl <int, double, double, SpanOpCount <int, double, double, SortedMapCursor <int, double>, SumAvgOnlineOp <int, double, SortedMapCursor <int, double> > >, SortedMapCursor <int, double> >(sm.GetEnumerator(), smaOp); // this monster type must be hidden in the same way Lag hides its implementation Series <int, double, SpanOpImpl <int, double, double, SpanOpCount <int, double, double, SortedMapCursor <int, double>, SumAvgOnlineOp <int, double, SortedMapCursor <int, double> > >, SortedMapCursor <int, double> > > smaSeries; smaSeries = smaCursor.Source; var sm2 = smaSeries.ToSortedMap(); Assert.AreEqual(sm2.First, smaSeries.First); Assert.AreEqual(sm2.Last, smaSeries.Last); Assert.True(SeriesContract.MoveAtShouldWorkOnLazySeries(smaSeries)); Assert.True(SeriesContract.ClonedCursorsAreIndependent(smaSeries)); if (!allowIncomplete) { var trueSma = sm.Window(10).Map(x => x.Values.Average()); Assert.True(trueSma.Keys.SequenceEqual(smaSeries.Keys)); Assert.True(trueSma.Values.SequenceEqual(smaSeries.Values)); } Debug.WriteLine("SMA"); foreach (var keyValuePair in smaSeries) { Debug.WriteLine($"{keyValuePair.Key} - {keyValuePair.Value}"); } } }