public void CouldEnumerateChangingSM() { var count = 1000000; var sw = new Stopwatch(); sw.Start(); var sm = new SortedMap <DateTime, double>(); //sm.IsSynchronized = true; var c = sm.GetCursor(); for (int i = 0; i < count; i++) { sm.Add(DateTime.UtcNow.Date.AddSeconds(i), i); var version = sm.Version; //if (i > 10) { // sm.Add(DateTime.UtcNow.Date.AddSeconds(i - 10), i - 10 + 1); // Assert.IsTrue(sm.Version > version); //} c.MoveNext(); Assert.AreEqual(i, c.CurrentValue); } sw.Stop(); Console.WriteLine("Elapsed msec: {0}", sw.ElapsedMilliseconds - 50); Console.WriteLine("Ops: {0}", Math.Round(0.000001 * count * 1000.0 / (sw.ElapsedMilliseconds * 1.0), 2)); }
public void CouldNotEnumerateChangingSM() { var count = 1000000; var sw = new Stopwatch(); sw.Start(); var sm = new SortedMap <DateTime, double>(); var c = sm.GetCursor(); Assert.Throws <OutOfOrderKeyException <DateTime> >(() => { for (int i = 0; i < count; i++) { sm.Add(DateTime.UtcNow.Date.AddSeconds(i), i); var version = sm.version; if (i > 10) { sm[DateTime.UtcNow.Date.AddSeconds(i - 10)] = i - 10 + 1; Assert.IsTrue(sm.version > version); } c.MoveNext(); Assert.AreEqual(i, c.CurrentValue); } }); sw.Stop(); Console.WriteLine("Elapsed msec: {0}", sw.ElapsedMilliseconds - 50); Console.WriteLine("Ops: {0}", Math.Round(0.000001 * count * 1000.0 / (sw.ElapsedMilliseconds * 1.0), 2)); }
public void CouldMoveNextAsyncWhenChangingOrder_NoSemaphore() { var cts = new CancellationTokenSource(); var ct = cts.Token; var sm = new SortedMap <int, int>(); sm.IsSynchronized = true; var tcs = new TaskCompletionSource <bool>(); var sumTask = Task.Run(async() => { var c = sm.GetCursor(); tcs.SetResult(true); Assert.IsTrue(await c.MoveNext(ct)); // here we change order Assert.IsTrue(await c.MoveNext(ct)); Assert.IsFalse(await c.MoveNext(ct)); }); tcs.Task.Wait(ct); sm.Add(1, 1); Thread.Sleep(100); //sm.Add(0, 0); // will through OOO sm.Add(2, 2); //sm.Add(3, 3); sm.Complete(); sumTask.Wait(ct); }
public void DeadCursorDoesntCauseEndlessLoopInNotifyUpdate() { var sm = new SortedMap <int, int>(); sm.Add(1, 1); var cursor = sm.GetCursor(); Assert.True(cursor.MoveNext()); Assert.False(cursor.MoveNext()); var cts = new CancellationTokenSource(); cursor.MoveNext(cts.Token); cursor = null; GC.Collect(2, GCCollectionMode.Forced, true); GC.Collect(2, GCCollectionMode.Forced, true); //var t = Task.Run(() => cursor.MoveNext(cts.Token)); sm.Add(2, 2); sm.Add(3, 3); Assert.True(sm.Count == 3); }
public void CouldReadSortedMapNewValuesWhileTheyAreAddedUsingCursor_StartEmpty() { var count = 1000000; var sw = new Stopwatch(); sw.Start(); var sm = new SortedMap <DateTime, double>(); sm.IsSynchronized = true; var addTask = Task.Run(async() => { await Task.Delay(50); for (int i = 0; i < count; i++) { sm.Add(DateTime.UtcNow.Date.AddSeconds(i), i); //await Task.Delay(1); } }); double sum = 0.0; var sumTask = Task.Run(async() => { var c = sm.GetCursor(); while (c.MoveNext()) { sum += c.CurrentValue; } Assert.AreEqual(0, sum); var stop = DateTime.UtcNow.Date.AddSeconds(count - 1); //await Task.Delay(50); while (await c.MoveNext(CancellationToken.None)) { sum += c.CurrentValue; //Console.WriteLine("Current key: {0}", c.CurrentKey); if (c.CurrentKey == stop) { break; } } }); sumTask.Wait(); addTask.Wait(); sw.Stop(); double expectedSum = 0.0; for (int i = 0; i < count; i++) { expectedSum += i; } Assert.AreEqual(expectedSum, sum); Console.WriteLine("Elapsed msec: {0}", sw.ElapsedMilliseconds - 50); Console.WriteLine("Ops: {0}", Math.Round(0.000001 * count * 1000.0 / (sw.ElapsedMilliseconds * 1.0), 2)); }
public void CouldMoveAsyncOnEmptySM() { var sm = new SortedMap<DateTime, double>(); var c = sm.GetCursor(); var moveTask = c.MoveNext(CancellationToken.None); sm.Add(DateTime.UtcNow.Date.AddSeconds(0), 0); var result = moveTask.Result; Assert.IsTrue(result); }
public void CouldMoveAsyncOnEmptySM() { var sm = new SortedMap <DateTime, double>(); var c = sm.GetCursor(); var moveTask = c.MoveNext(CancellationToken.None); sm.Add(DateTime.UtcNow.Date.AddSeconds(0), 0); var result = moveTask.Result; Assert.IsTrue(result); }
public void IsSyncedIsSetAutomaticallyForCursor() { var sm = new SortedMap <long, long>(); sm.Add(1, 1); Task.Run(() => { var c = sm.GetCursor(); c.MoveNext(); }).Wait(); Assert.IsTrue(sm.IsSynchronized); }
public async Task AddSpeed() { const int count = 5_000_000; for (int r = 0; r < 10; r++) { var sl = new SortedList <int, int>(); var sm = new SortedMap <int, int>(); var scm = new SortedChunkedMap <int, int>(); var c = sm.GetCursor(); sm._isSynchronized = false; scm._isSynchronized = false; using (Benchmark.Run("SL", count)) { for (int i = 0; i < count; i++) { if (i != 2) { sl.Add(i, i); } } } using (Benchmark.Run("SM", count)) { for (int i = 0; i < count; i++) { if (i != 2) { await sm.TryAdd(i, i); } } } using (Benchmark.Run("SCM", count)) { for (int i = 0; i < count; i++) { if (i != 2) { await scm.TryAdd(i, i); } } } scm.Dispose(); } Benchmark.Dump(); }
public void CouldMoveAtLE() { var scm = new SortedMap <long, long>(); for (long i = int.MaxValue; i < int.MaxValue * 4L; i = i + int.MaxValue) { scm[i] = i; } var cursor = scm.GetCursor(); var shouldBeFalse = cursor.MoveAt(0, Lookup.LE); Assert.IsFalse(shouldBeFalse); }
public void ContinuationOnMNAIsSynchronous() { var sm = new SortedMap <int, int>(); var cursor = sm.GetCursor(); var task = cursor.MoveNextAsync(); // Both continuations must run on the thread pool task.ContinueWith(delegate { Assert.AreEqual(threadPoolThreadName, Identify()); }); task.ContinueWith(delegate { Assert.AreEqual(threadPoolThreadName, Identify()); }, TaskContinuationOptions.ExecuteSynchronously); sm.Add(1, 1); task.Wait(); Thread.Sleep(100); }
public void CouldEnumerateGrowingSM() { var count = 1000000; var sw = new Stopwatch(); sw.Start(); var sm = new SortedMap<DateTime, double>(); var c = sm.GetCursor(); for (int i = 0; i < count; i++) { sm.Add(DateTime.UtcNow.Date.AddSeconds(i), i); c.MoveNext(); Assert.AreEqual(i, c.CurrentValue); } sw.Stop(); Console.WriteLine("Elapsed msec: {0}", sw.ElapsedMilliseconds - 50); Console.WriteLine("Ops: {0}", Math.Round(0.000001 * count * 1000.0 / (sw.ElapsedMilliseconds * 1.0), 2)); }
public void MoveNextAsyncBenchmark() { // this benchmark shows that simple async enumeration gives 13+ mops, // this means than we should use parallel enumeration on joins. // the idea is that a chain of calculations could be somewhat heavy, e.g. rp(ma(log(zipLag(c p -> c/p)))) // but they are optimized for single thread: when movenext is called on the outer cursor, // the whole chain enumerates synchronously. // During joins, we must make these evaluations parallel. The net overhead of tasks over existing data is visible // but not too big, while on real-time stream there is no alternative at all. // Join algos should be paralell and task-based by default var count = 10000000; var sw = new Stopwatch(); var sm = new SortedMap <DateTime, double>(); for (int i = 0; i < count; i++) { sm.Add(DateTime.UtcNow.Date.AddSeconds(i), i); } sm.Complete(); sw.Start(); double sum = 0.0; var c = sm.GetCursor(); Task.Run(async() => { while (await c.MoveNext(CancellationToken.None)) { sum += c.CurrentValue; } }).Wait(); sw.Stop(); double expectedSum = 0.0; for (int i = 0; i < count; i++) { expectedSum += i; } Assert.AreEqual(expectedSum, sum); Console.WriteLine("Elapsed msec: {0}", sw.ElapsedMilliseconds); Console.WriteLine("Ops: {0}", Math.Round(0.000001 * count * 1000.0 / (sw.ElapsedMilliseconds * 1.0), 2)); }
public void CouldMoveAtGE() { var scm = new SortedMap<int, int>(50); for (int i = 0; i < 100; i++) { scm[i] = i; } var cursor = scm.GetCursor(); cursor.MoveAt(-100, Lookup.GE); Assert.AreEqual(0, cursor.CurrentKey); Assert.AreEqual(0, cursor.CurrentValue); var shouldBeFalse = cursor.MoveAt(-100, Lookup.LE); Assert.IsFalse(shouldBeFalse); }
public void CouldEnumerateGrowingSM() { var count = 1000000; var sw = new Stopwatch(); sw.Start(); var sm = new SortedMap <DateTime, double>(); var c = sm.GetCursor(); for (int i = 0; i < count; i++) { sm.Add(DateTime.UtcNow.Date.AddSeconds(i), i); c.MoveNext(); Assert.AreEqual(i, c.CurrentValue); } sw.Stop(); Console.WriteLine("Elapsed msec: {0}", sw.ElapsedMilliseconds - 50); Console.WriteLine("Ops: {0}", Math.Round(0.000001 * count * 1000.0 / (sw.ElapsedMilliseconds * 1.0), 2)); }
public void CouldMoveAtGE() { var scm = new SortedMap <int, int>(50); for (int i = 0; i < 100; i++) { scm[i] = i; } var cursor = scm.GetCursor(); cursor.MoveAt(-100, Lookup.GE); Assert.AreEqual(0, cursor.CurrentKey); Assert.AreEqual(0, cursor.CurrentValue); var shouldBeFalse = cursor.MoveAt(-100, Lookup.LE); Assert.IsFalse(shouldBeFalse); }
public void CouldMoveAtGE() { var sm = new SortedMap <int, int>(50); for (int i = 0; i < 100; i++) { sm[i] = i; } Assert.IsTrue(sm.IsRegular); Assert.AreEqual(99, sm.rkLast); var cursor = sm.GetCursor(); cursor.MoveAt(-100, Lookup.GE); Assert.AreEqual(0, cursor.CurrentKey); Assert.AreEqual(0, cursor.CurrentValue); var shouldBeFalse = cursor.MoveAt(-100, Lookup.LE); Assert.IsFalse(shouldBeFalse); }
public void CouldCancelMNA() { var sm = new SortedMap <int, int>(); sm.Add(1, 1); var cursor = sm.GetCursor(); Assert.True(cursor.MoveNext()); Assert.False(cursor.MoveNext()); var cts = new CancellationTokenSource(); var t = Task.Run(() => cursor.MoveNext(cts.Token)); cts.Cancel(); Thread.Sleep(100); Assert.True(t.IsCanceled); }
public void CancelledCursorDoesntCauseEndlessLoopInNotifyUpdate() { var sm = new SortedMap <int, int>(); sm.Add(1, 1); var cursor = sm.GetCursor(); Assert.True(cursor.MoveNext()); Assert.False(cursor.MoveNext()); var cts = new CancellationTokenSource(); cursor.MoveNext(cts.Token); cts.Cancel(); sm.Add(2, 2); sm.Add(3, 3); Assert.True(sm.Count == 3); }
public void CancelledCursorThrowsOperationCancelledException() { var sm = new SortedMap <int, int>(); sm.Add(1, 1); var cursor = sm.GetCursor(); Assert.True(cursor.MoveNext()); Assert.False(cursor.MoveNext()); var cts = new CancellationTokenSource(); var t = Task.Run(() => { Thread.Sleep(100); var task = cursor.MoveNext(cts.Token); Assert.True(task.IsCanceled); //task.Wait(); }); cts.Cancel(); t.Wait(); }
public void CouldCancelDoAfter() { var sm = new SortedMap <int, int>(); sm.Add(1, 1); var cursor = sm.GetCursor(); Assert.True(cursor.MoveNext()); Assert.False(cursor.MoveNext()); var cts = new CancellationTokenSource(); var t = sm.Range(int.MinValue, 2, true, true).Do((k, v) => { Console.WriteLine($"{k} - {v}"); }, cts.Token); cts.Cancel(); Thread.Sleep(1000); Assert.True(t.IsCanceled); }
public void CouldMoveAtFromDict() { var sm = new SortedMap <int, int>(new Dictionary <int, int>() { { 1, 1 }, //{ 2, 2}, { 3, 3 }, //{ 4, 4}, { 5, 5 } }); Assert.IsTrue(sm.IsRegular); Assert.AreEqual(5, sm.rkLast); var cursor = sm.GetCursor(); cursor.MoveAt(-100, Lookup.GE); Assert.AreEqual(1, cursor.CurrentKey); Assert.AreEqual(1, cursor.CurrentValue); var shouldBeFalse = cursor.MoveAt(-100, Lookup.LE); Assert.IsFalse(shouldBeFalse); }
public void CursorContractsTests() { var notEmpty = false; /// Independent cursors moves var tc = _testSeries.GetCursor(); var tc2 = _testSeries.GetCursor(); var mc = _materializedSeries.GetCursor(); while (mc.MoveNext()) { notEmpty = true; Assert.IsTrue(tc.MoveNext(), "Independent cursors moves"); Assert.IsTrue(tc2.MoveNext(), "Independent cursors moves"); Assert.AreEqual(mc.Current, tc.Current, "Independent cursors moves: kvps are not equal after similar moves"); Assert.AreEqual(tc.Current, tc2.Current, "Independent cursors moves: kvps are not equal after similar moves"); } // one of the key contract is that MoveNext() does not destroy state after returning false, // because we could either spin or switch to MoveNextAsync() Assert.IsFalse(mc.MoveNext(), "MN after false MN should be false"); Assert.IsFalse(tc.MoveNext(), "MN after false MN should be false"); Assert.IsFalse(tc2.MoveNext(), "MN after false MN should be false"); if (notEmpty) { Assert.AreEqual(tc.Current, tc2.Current, "MN after false MN should be false and keep current key/value"); } /// we must be able to MP after false MN while (mc.MovePrevious()) { Assert.IsTrue(tc.MovePrevious(), "Independent cursors moves"); Assert.IsTrue(tc2.MovePrevious(), "Independent cursors moves"); Assert.AreEqual(mc.Current, tc.Current, "Independent cursors moves: kvps are not equal after similar moves"); Assert.AreEqual(tc.Current, tc2.Current, "Independent cursors moves: kvps are not equal after similar moves"); } Assert.IsFalse(mc.MovePrevious()); Assert.IsFalse(tc.MovePrevious()); Assert.IsFalse(tc2.MovePrevious()); if (notEmpty) { Assert.AreEqual(tc.Current, tc2.Current); } if (notEmpty) { // could move first Assert.IsTrue(mc.MoveFirst()); Assert.IsTrue(tc.MoveFirst()); Assert.IsTrue(tc2.MoveFirst()); Assert.AreEqual(mc.Current, tc.Current); Assert.AreEqual(tc.Current, tc2.Current); Lookup dir = Lookup.EQ; // could at the first key var key = mc.CurrentKey; var firstKey = key; Assert.IsTrue(mc.MoveAt(key, dir)); Assert.IsTrue(tc.MoveAt(key, dir)); Assert.IsTrue(tc2.MoveAt(key, dir)); Assert.AreEqual(mc.Current, tc.Current); Assert.AreEqual(tc.Current, tc2.Current); // could at or after the first key dir = Lookup.GE; Assert.IsTrue(mc.MoveAt(key, dir)); Assert.IsTrue(tc.MoveAt(key, dir)); Assert.IsTrue(tc2.MoveAt(key, dir)); Assert.AreEqual(mc.Current, tc.Current); Assert.AreEqual(tc.Current, tc2.Current); // could at first key if (_materializedSeries.Count > 1) { dir = Lookup.GT; Assert.IsTrue(mc.MoveAt(key, dir)); Assert.IsTrue(tc.MoveAt(key, dir)); Assert.IsTrue(tc2.MoveAt(key, dir)); Assert.AreEqual(mc.Current, tc.Current); Assert.AreEqual(tc.Current, tc2.Current); dir = Lookup.EQ; // could move at the first key after moving away from it key = firstKey; Assert.IsTrue(mc.MoveAt(key, dir)); Assert.IsTrue(tc.MoveAt(key, dir)); Assert.IsTrue(tc2.MoveAt(key, dir)); Assert.AreEqual(mc.Current, tc.Current); Assert.AreEqual(tc.Current, tc2.Current); } // could move last Assert.IsTrue(mc.MoveLast()); Assert.IsTrue(tc.MoveLast()); Assert.IsTrue(tc2.MoveLast()); Assert.AreEqual(mc.Current, tc.Current); Assert.AreEqual(tc.Current, tc2.Current); dir = Lookup.EQ; // could move at the last key key = mc.CurrentKey; var lastKey = key; Assert.IsTrue(mc.MoveAt(key, dir)); Assert.IsTrue(tc.MoveAt(key, dir)); Assert.IsTrue(tc2.MoveAt(key, dir)); Assert.AreEqual(mc.Current, tc.Current); Assert.AreEqual(tc.Current, tc2.Current); // could at or before the last key dir = Lookup.LE; Assert.IsTrue(mc.MoveAt(key, dir)); Assert.IsTrue(tc.MoveAt(key, dir)); Assert.IsTrue(tc2.MoveAt(key, dir)); Assert.AreEqual(mc.Current, tc.Current); Assert.AreEqual(tc.Current, tc2.Current); // could move before the last key if (_materializedSeries.Count > 1) { dir = Lookup.LT; Assert.IsTrue(mc.MoveAt(key, dir)); Assert.IsTrue(tc.MoveAt(key, dir)); Assert.IsTrue(tc2.MoveAt(key, dir)); Assert.AreEqual(mc.Current, tc.Current); Assert.AreEqual(tc.Current, tc2.Current); dir = Lookup.EQ; // could move at the last key after moving away from it key = lastKey; Assert.IsTrue(mc.MoveAt(key, dir)); Assert.IsTrue(tc.MoveAt(key, dir)); Assert.IsTrue(tc2.MoveAt(key, dir)); Assert.AreEqual(mc.Current, tc.Current); Assert.AreEqual(tc.Current, tc2.Current); } } }
public void CouldMoveAtLE() { var scm = new SortedMap<long, long>(); for (long i = int.MaxValue; i < int.MaxValue*4L; i = i + int.MaxValue) { scm[i] = i; } var cursor = scm.GetCursor(); var shouldBeFalse = cursor.MoveAt(0, Lookup.LE); Assert.IsFalse(shouldBeFalse); }
public async Task CouldReadDataStreamWhileWritingFromManyThreads() { var map = new SortedMap <int, int>(); var count = 1_000_000; var rounds = 5; var writeTask = Task.Run(async() => { using (Benchmark.Run("Write", count * rounds, true)) { for (int j = 0; j < rounds; j++) { var t1 = Task.Run(async() => { try { for (int i = j * count; i < (j + 1) * count; i++) { await map.TryAddLast(i, i); Thread.SpinWait(10); } } catch (Exception e) { Console.WriteLine(e); throw; } }); await t1; } } }); AsyncCursor <int, int, SortedMapCursor <int, int> > cursor = null; var cnt = 0L; var readTask = Task.Run(async() => { for (int r = 0; r < 1; r++) { using (cursor = new AsyncCursor <int, int, SortedMapCursor <int, int> >(map.GetCursor())) { using (Benchmark.Run("Read", count * rounds, true)) { try { while (await cursor.MoveNextAsync()) { Interlocked.Increment(ref cnt); } } catch (Exception e) { Console.WriteLine(e); throw; } // Left from coreclr 19161 tests, TODO remove when everything works OK // here is a strong reference to cursor with side effects of printing to console // Console.WriteLine("Last value: " + cursor.Current.Key); // another strong reference after while loop, we dereference it's value and return from task // lastKey1 = cursor.CurrentKey; } } } }); var monitor = true; var t = Task.Run(async() => { try { while (monitor) { await Task.Delay(1000); Console.WriteLine($"Key {cursor.CurrentKey}"); cursor.TryComplete(false); } } catch (Exception e) { Console.WriteLine(e); throw; } }); await writeTask; await map.Complete(); map.NotifyUpdate(true); Console.WriteLine("Read after map complete:" + Interlocked.Read(ref cnt)); await readTask; Console.WriteLine("Read after finish:" + Interlocked.Read(ref cnt)); // Console.WriteLine("Last key: " + lastKey); Benchmark.Dump(); map.Dispose(); monitor = false; }
public void CouldReadSortedMapNewValuesWhileTheyAreAddedUsingCursor_NoSemaphore() { var cts = new CancellationTokenSource(); var ct = CancellationToken.None; // cts.Token; // var count = 10000000; var sw = new Stopwatch(); sw.Start(); var sm = new SortedMap <DateTime, double>(); sm.IsSynchronized = true; //var sm = new SortedChunkedMap<DateTime, double>(); //sm.Add(DateTime.UtcNow.Date.AddSeconds(-2), 0); for (int i = 0; i < 5; i++) { sm.Add(DateTime.UtcNow.Date.AddSeconds(i), i); } var histogram = new LongHistogram(TimeSpan.TicksPerMillisecond * 100 * 1000, 3); double sum = 0; var cnt = 0; var histogram1 = new LongHistogram(TimeSpan.TicksPerMillisecond * 100 * 1000, 3); var sumTask = Task.Run(async() => { var c = sm.GetCursor(); var startTick = sw.ElapsedTicks; while (await c.MoveNext(ct)) { sum += c.CurrentValue; if ((int)c.CurrentValue != cnt) { //Console.WriteLine("Wrong sequence"); //Assert.Fail($"Wrong sequence: {c.CurrentValue} != {cnt}"); Trace.WriteLine($"Wrong sequence1: {c.CurrentValue} != {cnt}; thread {Thread.CurrentThread.ManagedThreadId}"); } else { //Console.WriteLine("Async move"); } cnt++; var ticks = sw.ElapsedTicks - startTick; var nanos = (long)(1000000000.0 * (double)ticks / Stopwatch.Frequency); try { histogram1.RecordValue(nanos); } catch (Exception e) { Console.WriteLine($"Nanos: {nanos}; " + e.Message); } startTick = sw.ElapsedTicks; } }); double sum2 = 0; var cnt2 = 0; var histogram2 = new LongHistogram(TimeSpan.TicksPerMillisecond * 100 * 1000, 3); var sumTask2 = Task.Run(async() => { var c = sm.GetCursor(); var startTick = sw.ElapsedTicks; while (await c.MoveNext(ct)) { sum2 += c.CurrentValue; if ((int)c.CurrentValue != cnt2) { //Console.WriteLine("Wrong sequence"); //Assert.Fail($"Wrong sequence: {c.CurrentValue} != {cnt}"); Trace.WriteLine($"Wrong sequence2: {c.CurrentValue} != {cnt2}; thread {Thread.CurrentThread.ManagedThreadId}"); } else { //Console.WriteLine("Async move"); } cnt2++; var ticks = sw.ElapsedTicks - startTick; var nanos = (long)(1000000000.0 * (double)ticks / Stopwatch.Frequency); try { histogram2.RecordValue(nanos); } catch (Exception e) { Console.WriteLine($"Nanos: {nanos}; " + e.Message); } startTick = sw.ElapsedTicks; } }); double sum3 = 0; var cnt3 = 0; var histogram3 = new LongHistogram(TimeSpan.TicksPerMillisecond * 100 * 1000, 3); var sumTask3 = Task.Run(async() => { var c = sm.GetCursor(); var startTick = sw.ElapsedTicks; while (await c.MoveNext(ct)) { sum3 += c.CurrentValue; if ((int)c.CurrentValue != cnt3) { //Console.WriteLine("Wrong sequence"); //Assert.Fail($"Wrong sequence: {c.CurrentValue} != {cnt}"); Trace.WriteLine($"Wrong sequence3: {c.CurrentValue} != {cnt3}; thread {Thread.CurrentThread.ManagedThreadId}"); } else { //Console.WriteLine("Async move"); } cnt3++; var ticks = sw.ElapsedTicks - startTick; var nanos = (long)(1000000000.0 * (double)ticks / Stopwatch.Frequency); try { histogram3.RecordValue(nanos); } catch (Exception e) { Console.WriteLine($"Nanos: {nanos}; " + e.Message); } startTick = sw.ElapsedTicks; } }); Thread.Sleep(1); var addTask = Task.Run(() => { //Console.WriteLine($"Adding from thread {Thread.CurrentThread.ManagedThreadId}"); try { for (int i = 5; i < count; i++) { sm.Add(DateTime.UtcNow.Date.AddSeconds(i), i); } sm.Complete(); } catch (Exception ex) { Console.WriteLine(ex); Environment.FailFast(ex.Message, ex); } }); while (!sumTask.Wait(2000)) { OptimizationSettings.Verbose = true; Trace.WriteLine($"cnt: {cnt}"); } while (!sumTask2.Wait(2000)) { //OptimizationSettings.Verbose = true; Trace.WriteLine($"cnt2: {cnt2}"); } while (!sumTask3.Wait(2000)) { //OptimizationSettings.Verbose = true; Trace.WriteLine($"cnt3: {cnt3}"); } addTask.Wait(); histogram.Add(histogram1); histogram.Add(histogram2); histogram.Add(histogram3); histogram.OutputPercentileDistribution( writer: Console.Out, percentileTicksPerHalfDistance: 3, outputValueUnitScalingRatio: OutputScalingFactor.None); sw.Stop(); Trace.Write($"Elapsed msec: {sw.ElapsedMilliseconds}; "); Trace.WriteLine($"Ops: {Math.Round(0.000001 * count * 1000.0 / (sw.ElapsedMilliseconds * 1.0), 2)}"); double expectedSum = 0.0; for (int i = 0; i < count; i++) { expectedSum += i; } if (expectedSum != sum) { Trace.WriteLine("Sum 1 is wrong"); } if (expectedSum != sum2) { Trace.WriteLine("Sum 2 is wrong"); } if (expectedSum != sum3) { Trace.WriteLine("Sum 3 is wrong"); } Assert.AreEqual(expectedSum, sum, "Sum 1"); Assert.AreEqual(expectedSum, sum2, "Sum 2"); Assert.AreEqual(expectedSum, sum3, "Sum 3"); //sm.Dispose(); }
public void MoveNextAsyncBenchmark() { // this benchmark shows that simple async enumeration gives 13+ mops, // this means than we should use parallel enumeration on joins. // the idea is that a chain of calculations could be somewhat heavy, e.g. rp(ma(log(zipLag(c p -> c/p)))) // but they are optimized for single thread: when movenext is called on the outer cursor, // the whole chain enumerates synchronously. // During joins, we must make these evaluations parallel. The net overhead of tasks over existing data is visible // but not too big, while on real-time stream there is no alternative at all. // Join algos should be paralell and task-based by default var count = 10000000; var sw = new Stopwatch(); var sm = new SortedMap<DateTime, double>(); //sm.IsSynchronized = true; for (int i = 0; i < count; i++) { sm.Add(DateTime.UtcNow.Date.AddSeconds(i), i); } sm.Complete(); sw.Start(); double sum = 0.0; var c = sm.GetCursor(); Task.Run(async () => { while (await c.MoveNext(CancellationToken.None)) { sum += c.CurrentValue; } }).Wait(); sw.Stop(); double expectedSum = 0.0; for (int i = 0; i < count; i++) { expectedSum += i; } Assert.AreEqual(expectedSum, sum); Console.WriteLine("Elapsed msec: {0}", sw.ElapsedMilliseconds); Console.WriteLine("Ops: {0}", Math.Round(0.000001 * count * 1000.0 / (sw.ElapsedMilliseconds * 1.0), 2)); }
public void CouldZipMillionIntsMovePreviousBenchmark() { var sw = new Stopwatch(); var sm1 = new SortedMap<int, int>(); sm1.Add(0, 0); for (int i = 2; i < 1000000; i++) { sm1.Add(i, i); } var series = new[] { sm1, sm1, sm1, sm1, sm1, };// sm1, sm1, sm1, sm1, sm1, sm1, sm1, sm1, sm1, sm1, sm1, sm1, sm1, sm1, sm1, }; sw.Start(); var cur = series.Zip((k, varr) => varr.Sum()).GetCursor(); var totalSum = 0L; while (cur.MovePrevious()) { totalSum += cur.CurrentValue; } var expectedTotalSum = 0L; var cur2 = sm1.GetCursor(); while (cur2.MovePrevious()) { expectedTotalSum += cur2.CurrentValue; } expectedTotalSum *= 5; sw.Stop(); Assert.AreEqual(expectedTotalSum, totalSum, "Sums are not equal"); Console.WriteLine("Elapsed msec: {0}", sw.ElapsedMilliseconds); Console.WriteLine("Total sum: {0}", totalSum); }
public void CouldNotMoveAsyncContinuousOnEmptyZip() { var sm1 = new SortedMap<int, int>(); var sm2 = new SortedMap<int, int>(); sm1.IsMutable = false; sm2.IsMutable = false; var zipped = sm1.Repeat() + sm2.Repeat(); var c1 = zipped.GetCursor(); Assert.IsFalse(sm1.GetCursor().MoveNext(CancellationToken.None).Result); Assert.IsFalse(sm2.GetCursor().MoveNext(CancellationToken.None).Result); Assert.IsFalse(c1.MoveNext()); Assert.IsFalse(c1.MoveFirst()); var task = c1.MoveNext(CancellationToken.None); task.Wait(); Assert.AreEqual(TaskStatus.RanToCompletion, task.Status); Assert.IsFalse(task.Result); }