public async Task MemoizeAsync_CallsWithDifferentParams_UsesSeparateCacheSlots() { var dataSource = CreateDataSource(5); dataSource.ThingifyTaskThing("otherString").Returns(Task.FromResult(new Thing { Id = 7 })); IMemoizer memoizer = CreateMemoizer(); (await(Task <Thing>) memoizer.Memoize(dataSource, ThingifyTaskThing, new object[] { "someString" }, GetPolicy())).Id.ShouldBe(5); (await(Task <Thing>) memoizer.Memoize(dataSource, ThingifyTaskThing, new object[] { "otherString" }, GetPolicy())).Id.ShouldBe(7); (await(Task <Thing>) memoizer.Memoize(dataSource, ThingifyTaskThing, new object[] { "someString" }, GetPolicy())).Id.ShouldBe(5); (await(Task <Thing>) memoizer.Memoize(dataSource, ThingifyTaskThing, new object[] { "otherString" }, GetPolicy())).Id.ShouldBe(7); dataSource.Received(1).ThingifyTaskThing("someString"); dataSource.Received(1).ThingifyTaskThing("otherString"); }
public void SingleThreadedMemoizedDirectInvocationWithPolicy_Memoizer() { long startTime = DateTime.Now.Ticks; IMemoizer <string, long, string> memoizer = reallySlowNetworkInvocation1b.CacheFor(NETWORK_RESPONSE_LATENCY_IN_MILLIS * 3).Milliseconds.GetMemoizer(); // New function value, not yet cached var retVal = memoizer.InvokeWith("SingleThreadedMemoizedDirectInvocationWithPolicy_Memoizer", 15L); Assert.That(retVal, Is.EqualTo(METHOD_RESPONSE_ELEMENT + "SingleThreadedMemoizedDirectInvocationWithPolicy_Memoizer" + 15L)); long durationInMilliseconds = (DateTime.Now.Ticks - startTime) / TimeSpan.TicksPerMillisecond; Assert.That(durationInMilliseconds, Is.InRange(NETWORK_RESPONSE_LATENCY_IN_MILLIS, NETWORK_RESPONSE_LATENCY_IN_MILLIS + 50L)); Console.WriteLine("SingleThreadedMemoizedDirectInvocationWithPolicy_Memoizer: first non-memoized method invocation with latency " + NETWORK_RESPONSE_LATENCY_IN_MILLIS + " ms took " + durationInMilliseconds + " ms (should take >= " + NETWORK_RESPONSE_LATENCY_IN_MILLIS + " ms)"); // Memoized function within time span, should use cached value startTime = DateTime.Now.Ticks; retVal = memoizer.InvokeWith("SingleThreadedMemoizedDirectInvocationWithPolicy_Memoizer", 15L); Assert.That(retVal, Is.EqualTo(METHOD_RESPONSE_ELEMENT + "SingleThreadedMemoizedDirectInvocationWithPolicy_Memoizer" + 15L)); durationInMilliseconds = (DateTime.Now.Ticks - startTime) / TimeSpan.TicksPerMillisecond; Assert.That(durationInMilliseconds, Is.LessThan(10L)); Console.WriteLine("SingleThreadedMemoizedDirectInvocationWithPolicy_Memoizer: second memoized method invocation with latency " + NETWORK_RESPONSE_LATENCY_IN_MILLIS + " ms took " + durationInMilliseconds + " ms (should take < 10 ms)"); // New function value, not yet cached startTime = DateTime.Now.Ticks; retVal = memoizer.InvokeWith("SingleThreadedMemoizedDirectInvocationWithPolicy_Memoizer", 16L); Assert.That(retVal, Is.EqualTo(METHOD_RESPONSE_ELEMENT + "SingleThreadedMemoizedDirectInvocationWithPolicy_Memoizer" + 16L)); durationInMilliseconds = (DateTime.Now.Ticks - startTime) / TimeSpan.TicksPerMillisecond; Assert.That(durationInMilliseconds, Is.InRange(NETWORK_RESPONSE_LATENCY_IN_MILLIS, NETWORK_RESPONSE_LATENCY_IN_MILLIS + 50L)); Console.WriteLine("SingleThreadedMemoizedDirectInvocationWithPolicy_Memoizer: another first non-memoized method invocation with latency " + NETWORK_RESPONSE_LATENCY_IN_MILLIS + " ms took " + durationInMilliseconds + " ms (should take >= " + NETWORK_RESPONSE_LATENCY_IN_MILLIS + " ms)"); Console.WriteLine("SingleThreadedMemoizedDirectInvocationWithPolicy_Memoizer: waiting for memoizer cache item evictions ..."); Thread.Sleep(NETWORK_RESPONSE_LATENCY_IN_MILLIS * 3); // Memoized function evicted due to exceeded time span, should take its time (for re-memoization) startTime = DateTime.Now.Ticks; retVal = memoizer.InvokeWith("SingleThreadedMemoizedDirectInvocationWithPolicy_Memoizer", 15L); Assert.That(retVal, Is.EqualTo(METHOD_RESPONSE_ELEMENT + "SingleThreadedMemoizedDirectInvocationWithPolicy_Memoizer" + 15L)); durationInMilliseconds = (DateTime.Now.Ticks - startTime) / TimeSpan.TicksPerMillisecond; Assert.That(durationInMilliseconds, Is.InRange(NETWORK_RESPONSE_LATENCY_IN_MILLIS, NETWORK_RESPONSE_LATENCY_IN_MILLIS + 50L)); Console.WriteLine("SingleThreadedMemoizedDirectInvocationWithPolicy_Memoizer: third memoized (but evicted) method invocation with latency " + NETWORK_RESPONSE_LATENCY_IN_MILLIS + " ms took " + durationInMilliseconds + " ms (should take >= " + NETWORK_RESPONSE_LATENCY_IN_MILLIS + " ms)"); }
public async Task MemoizeAsync_BackgroundRefreshFails_LastGoodValueStillReturned() { TimeSpan refreshTime = TimeSpan.FromMinutes(1); var refreshTask = new TaskCompletionSource <Thing>(); var args = new object[] { "someString" }; var dataSource = CreateDataSource(5, refreshTask); IMemoizer memoizer = CreateMemoizer(CreateCache()); (await(Task <Thing>) memoizer.Memoize(dataSource, ThingifyTaskThing, args, GetPolicy())).Id.ShouldBe(5); // fake that refreshTime has passed TimeFake.UtcNow += refreshTime; // Refresh task hasn't finished, should get old value (5) (await(Task <Thing>) memoizer.Memoize(dataSource, ThingifyTaskThing, args, GetPolicy())).Id.ShouldBe(5); // value is not refreshed yet. it is running on background // Complete refresh task and verify new value refreshTask.SetException(new Exception("Boo!!")); (await(Task <Thing>) memoizer.Memoize(dataSource, ThingifyTaskThing, args, GetPolicy())).Id.ShouldBe(5); // new value is expected now }
public void ShouldBuildFullBlownMemoizerWithOnelineAndStillGetMemoization() { long startTime = DateTime.Now.Ticks; MemoizerFactory <long, long> slowSquareMemoizerFactory = slow500Square.Memoize(); IMemoizer <long, long> memoizedSlowSquare = slowSquareMemoizerFactory.GetMemoizer(); long durationInTicks = DateTime.Now.Ticks - startTime; Console.WriteLine("Memoizer construction: square.Memoize().Get() took " + durationInTicks / 10000 + " ms | " + durationInTicks + " ticks]"); Assert.That(durationInTicks / 10000, Is.LessThan(20)); // ms (MemoizerFactory and Memoizer creation) startTime = DateTime.Now.Ticks; long result = memoizedSlowSquare.InvokeWith(123); durationInTicks = DateTime.Now.Ticks - startTime; Console.WriteLine("Square(123) = " + result + " [memoized first time invocation took " + durationInTicks / 10000 + " ms | " + durationInTicks + " ticks]"); Assert.That(durationInTicks / 10000, Is.GreaterThanOrEqualTo(500)); // ms (not memoized invocation) startTime = DateTime.Now.Ticks; result = memoizedSlowSquare.InvokeWith(123); durationInTicks = DateTime.Now.Ticks - startTime; Console.WriteLine("Square(123) = " + result + " [memoized second time invocation took " + durationInTicks / 10000 + " ms | " + durationInTicks + " ticks]"); Assert.That(durationInTicks / 10000, Is.LessThan(10)); // ms (memoized invocation) slowSquareMemoizerFactory.InstrumentWith(Console.WriteLine); IMemoizer <long, long> memoizedSlowSquare2 = slowSquareMemoizerFactory.GetMemoizer(); startTime = DateTime.Now.Ticks; result = slowSquareMemoizerFactory.GetMemoizer().InvokeWith(123); //result = memoizedSlowSquare2.InvokeWith(123); durationInTicks = DateTime.Now.Ticks - startTime; Console.WriteLine("Square(123) = " + result + " [memoized first time (instrumented) invocation took " + durationInTicks / 10000 + " ms | " + durationInTicks + " ticks]"); Assert.That(durationInTicks / 10000, Is.LessThan(10)); // ms (memoized invocation) startTime = DateTime.Now.Ticks; result = memoizedSlowSquare2.InvokeWith(123); durationInTicks = DateTime.Now.Ticks - startTime; Console.WriteLine("Square(123) = " + result + " [memoized second time (instrumented) invocation took " + durationInTicks / 10000 + " ms | " + durationInTicks + " ticks]"); Assert.That(durationInTicks / 10000, Is.LessThan(10)); // ms (memoized invocation) }
public void Remove() { IMemoizer <long, string> standaloneMemoizer = myExpensiveFunction.CacheFor(30).Minutes.InstrumentWith(Console.WriteLine).CreateMemoizer(); MemoizerFactory <long, string> sharedMemoizer1 = myExpensiveFunction.CacheFor(30).Minutes.InstrumentWith(Console.WriteLine); MemoizerFactory <long, string> sharedMemoizer2 = myExpensiveFunction.Memoize().InstrumentWith(Console.WriteLine); MemoizerFactory <long, string> sharedMemoizer3 = typicalDatabaseInvocation_DelegatedFunc3.Memoize().InstrumentWith(Console.WriteLine); // The standalone memoizer instance is not cached yet AssertThat(standaloneMemoizer.InvokeWith, 1989L, Is.GreaterThanOrEqualTo(DATABASE_RESPONSE_LATENCY_IN_MILLIS)); // ...now it is AssertThat(standaloneMemoizer.InvokeWith, 1989L, Is.LessThan(10)); // The memoizer^2 registry instances are either cached, or not... sharedMemoizer1.GetMemoizer().InvokeWith(1989L); sharedMemoizer1.GetMemoizer().InvokeWith(2089L); sharedMemoizer2.GetMemoizer().InvokeWith(1989L); sharedMemoizer3.GetMemoizer().InvokeWith(1989L); // ...now they are AssertThat(sharedMemoizer1.GetMemoizer().InvokeWith, 1989L, Is.LessThan(10)); AssertThat(sharedMemoizer1.GetMemoizer().InvokeWith, 2089L, Is.LessThan(10)); AssertThat(sharedMemoizer2.GetMemoizer().InvokeWith, 1989L, Is.LessThan(10)); AssertThat(sharedMemoizer3.GetMemoizer().InvokeWith, 1989L, Is.LessThan(10)); // Removal from the standalone memoizer instance standaloneMemoizer.Remove(1989L); // Standalone memoizer must be re-cached AssertThat(standaloneMemoizer.InvokeWith, 1989L, Is.GreaterThanOrEqualTo(DATABASE_RESPONSE_LATENCY_IN_MILLIS)); AssertThat(standaloneMemoizer.InvokeWith, 1989L, Is.LessThan(10)); // Neither of the shared memoizer instances are affected AssertThat(sharedMemoizer1.GetMemoizer().InvokeWith, 1989L, Is.LessThan(10)); AssertThat(sharedMemoizer2.GetMemoizer().InvokeWith, 1989L, Is.LessThan(10)); AssertThat(sharedMemoizer3.GetMemoizer().InvokeWith, 1989L, Is.LessThan(10)); }
public async Task MemoizeAsync_BackgroundRefreshFails_NextRequestAfterDelayTriggersRefresh() { TimeSpan refreshTime = TimeSpan.FromMinutes(1); TimeSpan failedRefreshDelay = TimeSpan.FromSeconds(1); var refreshTask = new TaskCompletionSource <Thing>(); var args = new object[] { "someString" }; string firstValue = "first Value"; string secondValue = "second Value"; var dataSource = CreateDataSource(firstValue, refreshTask, secondValue); IMemoizer memoizer = CreateMemoizer(CreateCache()); (await(Task <Thing>) memoizer.Memoize(dataSource, ThingifyTaskThing, args, GetPolicy())).Id.ShouldBe(firstValue); // fake that refreshTime has passed TimeFake.UtcNow += refreshTime; // Should trigger refresh task that won't be completed yet, should get old value (5) (await(Task <Thing>) memoizer.Memoize(dataSource, ThingifyTaskThing, args, GetPolicy())).Id.ShouldBe(firstValue); // Fail the first refresh task and verify old value (5) still returned. // FailedRefreshDelay hasn't passed so shouldn't trigger refresh. refreshTask.SetException(new Exception("Boo!!")); (await(Task <Thing>) memoizer.Memoize(dataSource, ThingifyTaskThing, args, GetPolicy())).Id.ShouldBe(firstValue); TimeFake.UtcNow += TimeSpan.FromMilliseconds(failedRefreshDelay.TotalMilliseconds * 0.7); // FailedRefreshDelay still hasn't passed so shouldn't trigger refresh. (await(Task <Thing>) memoizer.Memoize(dataSource, ThingifyTaskThing, args, GetPolicy())).Id.ShouldBe(firstValue); TimeFake.UtcNow += TimeSpan.FromMilliseconds(failedRefreshDelay.TotalMilliseconds * 0.7); // FailedRefreshDelay passed so should trigger refresh. (await(Task <Thing>) memoizer.Memoize(dataSource, ThingifyTaskThing, args, GetPolicy())).Id.ShouldBe(firstValue); // Second refresh should succeed, should get new value (7); (await(Task <Thing>) memoizer.Memoize(dataSource, ThingifyTaskThing, args, GetPolicy())).Id.ShouldBe(secondValue); }
public async Task MemoizeAsync_CallAfterRefreshTime_RefreshOnBackground() { TimeSpan refreshTime = TimeSpan.FromMinutes(1); var refreshTask = new TaskCompletionSource <Thing>(); var args = new object[] { "someString" }; var dataSource = CreateDataSource(5, refreshTask); IMemoizer memoizer = CreateMemoizer(CreateCache()); (await(Task <Thing>) memoizer.Memoize(dataSource, ThingifyTaskThing, args, GetPolicy())).Id.ShouldBe(5); // fake that refreshTime has passed TimeFake.UtcNow += refreshTime; // Refresh task hasn't finished, should get old value (5) (await(Task <Thing>) memoizer.Memoize(dataSource, ThingifyTaskThing, args, GetPolicy())).Id.ShouldBe(5); // value is not refreshed yet. it is running on background // Complete refresh task and verify new value refreshTask.SetResult(new Thing { Id = 7, Name = "seven" }); (await(Task <Thing>) memoizer.Memoize(dataSource, ThingifyTaskThing, args, GetPolicy())).Id.ShouldBe(7); // new value is expected now }
/// <summary> /// Creates a new expression hasher with the specified object pool capacity and memoization cache factory. /// </summary> /// <param name="poolCapacity">The size of the internal object pool to keep data structures that are required to compute a hash code.</param> /// <param name="cacheFactory"></param> /// <remarks> /// The <paramref name="poolCapacity"/> parameter can be used to adjust the internal pool size when it's known that the /// hasher is used in specific configurations. For example, if the hasher is only used from a single thread, a pool size /// of <c>1</c> could suffice. In case one expects the overridden <see cref="GetHashCode(ObjectSlim)"/> method to reenter /// the hasher, the pool size could be adjusted to allow for such reentrancy. If possible, it is recommended to make such /// overridden <see cref="GetHashCode(ObjectSlim)"/> implementations call <see cref="GetHashCode(ExpressionSlim)"/> directly /// rather than causing the creation of a new hasher instance. /// /// Note that a pool size that's too small does not cause a functional regression; it merely can result in degraded hashing /// performance due to the allocation of internal data structures that cannot be reused. /// </remarks> public ExpressionSlimHasher(int poolCapacity, IMemoizationCacheFactory cacheFactory) { _pool = new ObjectPool <ExpressionHashingVisitor>(CreateHashingVisitor, poolCapacity); _memoizer = Memoizer.Create(cacheFactory); }
public MemberInfoSlimHashingVisitor(ExpressionSlimHasher parent, TypeSlimHashingVisitor typeHasher, IMemoizer memoizer) { _parent = parent; _typeHasher = typeHasher; // NB: We use reference equality for memoization in order to prevent the computation of another // hash code through the overridden GetHashCode implementation on MemberInfoSlim. The use // of reference equality is very effective within expressions and for reflection objects that // come from a shared reflection context where reference-equal objects are returned. _visitCache = memoizer.Memoize(base.Visit, MemoizationOptions.None, ReferenceEqualityComparer <MemberInfoSlim> .Instance); }
public void MultipleCacheItemPolicies_MemoizerFactoryIsMutable___OnGoing() { MemoizerFactory <long, string> myMessyMemoizerFactory = typicalDatabaseInvocation_InlinedFunc2.CacheFor(12).Hours .InstrumentWith(Console.WriteLine); IMemoizer <long, string> myMemoizedFunction = myMessyMemoizerFactory.GetMemoizer(); //Assert.That(LatencyInstrumentedRun(myMessyMemoizerFactory, DATABASE_RESPONSE_LATENCY_IN_MILLIS, "First method invocation", "(should take > " + DATABASE_RESPONSE_LATENCY_IN_MILLIS + " ms)"), // Is.GreaterThanOrEqualTo(DATABASE_RESPONSE_LATENCY_IN_MILLIS)); long startTime = DateTime.Now.Ticks; string retVal = myMemoizedFunction.InvokeWith(4224L); long durationInTicks = DateTime.Now.Ticks - startTime; long durationInMilliseconds = durationInTicks / TimeSpan.TicksPerMillisecond; Assert.That(retVal, Is.EqualTo(METHOD_RESPONSE_ELEMENT + 4224L)); Console.WriteLine("(4224) invocation with latency " + durationInMilliseconds + " ms took " + durationInMilliseconds + " ms | " + durationInTicks + " ticks " + "(should take > " + DATABASE_RESPONSE_LATENCY_IN_MILLIS + " ms)"); Assert.That(durationInMilliseconds, Is.GreaterThanOrEqualTo(DATABASE_RESPONSE_LATENCY_IN_MILLIS)); //Assert.That(LatencyInstrumentedRun(myMessyMemoizerFactory, DATABASE_RESPONSE_LATENCY_IN_MILLIS, "Second method invocation", "(cached, should take < 5 ms)"), // Is.LessThan(20)); // ms (20 ms just for LatencyInstrumentedRun method to finish...) startTime = DateTime.Now.Ticks; retVal = myMemoizedFunction.InvokeWith(4224L); durationInTicks = DateTime.Now.Ticks - startTime; durationInMilliseconds = durationInTicks / TimeSpan.TicksPerMillisecond; Assert.That(retVal, Is.EqualTo(METHOD_RESPONSE_ELEMENT + 4224L)); Console.WriteLine("(4224) invocation with latency " + durationInMilliseconds + " ms took " + durationInMilliseconds + " ms | " + durationInTicks + " ticks " + "(cached, should take < 5 ms)"); // TODO: hmm, takes its time... Assert.That(durationInMilliseconds, Is.LessThan(30)); // ms myMessyMemoizerFactory = myMessyMemoizerFactory.KeepItemsCachedFor(0).Milliseconds .InstrumentWith(Console.WriteLine) .KeepItemsCachedFor(120).Milliseconds; IMemoizer <long, string> myMemoizedFunction2 = myMessyMemoizerFactory.GetMemoizer(); //Assert.That(LatencyInstrumentedRun(myMessyMemoizerFactory, DATABASE_RESPONSE_LATENCY_IN_MILLIS, "Second method invocation", "(cached, should take < 5 ms)"), // Is.LessThan(20)); // ms (20 ms just for LatencyInstrumentedRun method to finish...) startTime = DateTime.Now.Ticks; retVal = myMemoizedFunction2.InvokeWith(123456L); durationInTicks = DateTime.Now.Ticks - startTime; durationInMilliseconds = durationInTicks / TimeSpan.TicksPerMillisecond; Assert.That(retVal, Is.EqualTo(METHOD_RESPONSE_ELEMENT + 123456L)); Console.WriteLine("(123456) invocation with latency " + durationInMilliseconds + " ms took " + durationInMilliseconds + " ms | " + durationInTicks + " ticks " + "(should take > " + DATABASE_RESPONSE_LATENCY_IN_MILLIS + " ms)"); Assert.That(durationInMilliseconds, Is.GreaterThanOrEqualTo(DATABASE_RESPONSE_LATENCY_IN_MILLIS)); startTime = DateTime.Now.Ticks; retVal = myMemoizedFunction2.InvokeWith(123456); durationInTicks = DateTime.Now.Ticks - startTime; durationInMilliseconds = durationInTicks / TimeSpan.TicksPerMillisecond; Assert.That(retVal, Is.EqualTo(METHOD_RESPONSE_ELEMENT + 123456)); Console.WriteLine("(123456) invocation with latency " + durationInMilliseconds + " ms took " + durationInMilliseconds + " ms | " + durationInTicks + " ticks " + "(cached, should take < 5 ms)"); Assert.That(durationInMilliseconds, Is.LessThan(5)); // ms Thread.Sleep(300); //Assert.That(LatencyInstrumentedRun(myMessyMemoizerFactory, DATABASE_RESPONSE_LATENCY_IN_MILLIS, "Third method invocation", "(cached, should take < 5 ms)"), // Is.LessThan(20)); // ms (20 ms just for LatencyInstrumentedRun method to finish...) // Previous memoizer still intact startTime = DateTime.Now.Ticks; retVal = myMemoizedFunction.InvokeWith(4224L); durationInTicks = DateTime.Now.Ticks - startTime; durationInMilliseconds = durationInTicks / TimeSpan.TicksPerMillisecond; Assert.That(retVal, Is.EqualTo(METHOD_RESPONSE_ELEMENT + 4224L)); Console.WriteLine("(4224) invocation with latency " + durationInMilliseconds + " ms took " + durationInMilliseconds + " ms | " + durationInTicks + " ticks " + "(cached, should take < 5 ms)"); Assert.That(durationInMilliseconds, Is.LessThan(5)); // ms startTime = DateTime.Now.Ticks; retVal = myMemoizedFunction2.InvokeWith(123456L); durationInTicks = DateTime.Now.Ticks - startTime; durationInMilliseconds = durationInTicks / TimeSpan.TicksPerMillisecond; Assert.That(retVal, Is.EqualTo(METHOD_RESPONSE_ELEMENT + 123456L)); Console.WriteLine("(123456L) invocation with latency " + durationInMilliseconds + " ms took " + durationInMilliseconds + " ms | " + durationInTicks + " ticks " + "(should take > " + DATABASE_RESPONSE_LATENCY_IN_MILLIS + " ms)"); Assert.That(durationInMilliseconds, Is.GreaterThanOrEqualTo(DATABASE_RESPONSE_LATENCY_IN_MILLIS)); }
private async Task <Revocable <Thing> > CallWithMemoize(IMemoizer memoizer, IThingFrobber dataSource) { return(await(Task <Revocable <Thing> >) memoizer.Memoize(dataSource, ThingifyTaskRevokabkle, new object[] { "someString" }, GetPolicy())); }
public HandleCreateOrder(IDocumentRepository couch, IMemoizer mementoProvider, IAgent <Order> orderAgent) { Couch = couch; MementoProvider = mementoProvider; OrderAgent = orderAgent; }
public DefaultContextProvider(IEventConfiguration configuration, IMemoizer memoizer, IEventPublisher publisher) { Configuration = configuration; Memoizer = memoizer; Publisher = publisher; }
public HandeMenuItemAdd(IDocumentRepository couch, IMemoizer mementoProvider) { Couch = couch; MementoProvider = mementoProvider; }
public void NoArgumentsMemoizer() { Func <string> expensiveNoArgsInvocationFunc = delegate { Console.WriteLine("TypicalReferenceDataStaticInvocation invoked..."); Thread.Sleep(1345); Console.WriteLine("TypicalReferenceDataStaticInvocation returns..."); return("Some no-arguments-one-time-only-invocation data stuff"); }; IMemoizer <string> memoizer = expensiveNoArgsInvocationFunc.CacheFor(1).Seconds.GetMemoizer(); // Cached-for-1-second memoizer long startTime = DateTime.Now.Ticks; string retVal = memoizer.Invoke(); long durationInTicks = DateTime.Now.Ticks - startTime; long durationInMilliseconds = durationInTicks / TimeSpan.TicksPerMillisecond; Assert.That(retVal, Is.EqualTo("Some no-arguments-one-time-only-invocation data stuff")); Assert.That(durationInMilliseconds, Is.GreaterThanOrEqualTo(1345)); // ms Console.WriteLine("One-time-invocation took " + durationInMilliseconds + " ms | " + durationInTicks + " ticks"); startTime = DateTime.Now.Ticks; retVal = memoizer.Invoke(); durationInTicks = DateTime.Now.Ticks - startTime; durationInMilliseconds = durationInTicks / TimeSpan.TicksPerMillisecond; Assert.That(retVal, Is.EqualTo("Some no-arguments-one-time-only-invocation data stuff")); Assert.That(durationInMilliseconds, Is.LessThan(5)); // ms Console.WriteLine("One-time-invocation took " + durationInMilliseconds + " ms | " + durationInTicks + " ticks"); // Cached-for-1-second-on-the-fly function - should be cached already startTime = DateTime.Now.Ticks; retVal = expensiveNoArgsInvocationFunc.CacheFor(1).Seconds.GetMemoizer().Invoke(); durationInTicks = DateTime.Now.Ticks - startTime; durationInMilliseconds = durationInTicks / TimeSpan.TicksPerMillisecond; Assert.That(retVal, Is.EqualTo("Some no-arguments-one-time-only-invocation data stuff")); Assert.That(durationInMilliseconds, Is.LessThan(5)); // ms Console.WriteLine("One-time-invocation took " + durationInMilliseconds + " ms | " + durationInTicks + " ticks"); // Function only - not yet cached startTime = DateTime.Now.Ticks; retVal = expensiveNoArgsInvocationFunc.CachedInvoke(); durationInTicks = DateTime.Now.Ticks - startTime; durationInMilliseconds = durationInTicks / TimeSpan.TicksPerMillisecond; Assert.That(retVal, Is.EqualTo("Some no-arguments-one-time-only-invocation data stuff")); Assert.That(durationInMilliseconds, Is.GreaterThanOrEqualTo(1345)); // ms Console.WriteLine("One-time-invocation took " + durationInMilliseconds + " ms | " + durationInTicks + " ticks"); startTime = DateTime.Now.Ticks; retVal = expensiveNoArgsInvocationFunc.CachedInvoke(); durationInTicks = DateTime.Now.Ticks - startTime; durationInMilliseconds = durationInTicks / TimeSpan.TicksPerMillisecond; Assert.That(retVal, Is.EqualTo("Some no-arguments-one-time-only-invocation data stuff")); Assert.That(durationInMilliseconds, Is.LessThan(5)); // ms Console.WriteLine("One-time-invocation took " + durationInMilliseconds + " ms | " + durationInTicks + " ticks"); expensiveNoArgsInvocationFunc.RemoveFromCache(); startTime = DateTime.Now.Ticks; retVal = expensiveNoArgsInvocationFunc.CachedInvoke(); durationInTicks = DateTime.Now.Ticks - startTime; durationInMilliseconds = durationInTicks / TimeSpan.TicksPerMillisecond; Assert.That(retVal, Is.EqualTo("Some no-arguments-one-time-only-invocation data stuff")); Assert.That(durationInMilliseconds, Is.GreaterThanOrEqualTo(1345)); // ms Console.WriteLine("One-time-invocation took " + durationInMilliseconds + " ms | " + durationInTicks + " ticks"); startTime = DateTime.Now.Ticks; retVal = expensiveNoArgsInvocationFunc.CachedInvoke(); durationInTicks = DateTime.Now.Ticks - startTime; durationInMilliseconds = durationInTicks / TimeSpan.TicksPerMillisecond; Assert.That(retVal, Is.EqualTo("Some no-arguments-one-time-only-invocation data stuff")); Assert.That(durationInMilliseconds, Is.LessThan(5)); // ms Console.WriteLine("One-time-invocation took " + durationInMilliseconds + " ms | " + durationInTicks + " ticks"); expensiveNoArgsInvocationFunc.UnMemoize(); startTime = DateTime.Now.Ticks; retVal = expensiveNoArgsInvocationFunc.CacheFor(1).Seconds.GetMemoizer().Invoke(); durationInTicks = DateTime.Now.Ticks - startTime; durationInMilliseconds = durationInTicks / TimeSpan.TicksPerMillisecond; Assert.That(retVal, Is.EqualTo("Some no-arguments-one-time-only-invocation data stuff")); Assert.That(durationInMilliseconds, Is.GreaterThanOrEqualTo(1345)); // ms Console.WriteLine("One-time-invocation took " + durationInMilliseconds + " ms | " + durationInTicks + " ticks"); startTime = DateTime.Now.Ticks; retVal = expensiveNoArgsInvocationFunc.CacheFor(1).Seconds.GetMemoizer().Invoke(); durationInTicks = DateTime.Now.Ticks - startTime; durationInMilliseconds = durationInTicks / TimeSpan.TicksPerMillisecond; Assert.That(retVal, Is.EqualTo("Some no-arguments-one-time-only-invocation data stuff")); Assert.That(durationInMilliseconds, Is.LessThan(5)); // ms Console.WriteLine("One-time-invocation took " + durationInMilliseconds + " ms | " + durationInTicks + " ticks"); Thread.Sleep(1000); startTime = DateTime.Now.Ticks; retVal = expensiveNoArgsInvocationFunc.CacheFor(55).Seconds.GetMemoizer().Invoke(); durationInTicks = DateTime.Now.Ticks - startTime; durationInMilliseconds = durationInTicks / TimeSpan.TicksPerMillisecond; Assert.That(retVal, Is.EqualTo("Some no-arguments-one-time-only-invocation data stuff")); Assert.That(durationInMilliseconds, Is.GreaterThanOrEqualTo(1345)); // ms Console.WriteLine("One-time-invocation took " + durationInMilliseconds + " ms | " + durationInTicks + " ticks"); startTime = DateTime.Now.Ticks; retVal = expensiveNoArgsInvocationFunc.CacheFor(55).Seconds.GetMemoizer().Invoke(); durationInTicks = DateTime.Now.Ticks - startTime; durationInMilliseconds = durationInTicks / TimeSpan.TicksPerMillisecond; Assert.That(retVal, Is.EqualTo("Some no-arguments-one-time-only-invocation data stuff")); Assert.That(durationInMilliseconds, Is.LessThan(5)); // ms Console.WriteLine("One-time-invocation took " + durationInMilliseconds + " ms | " + durationInTicks + " ticks"); }
public static U Memoize <U>(this IMemoizer memo, Func <U> f) where U : class { return(memo.Memoize(memo, x => f())); }
public void ShouldBuildFullBlownMemoizedFuncsWithOnelineAndStillGetMemoization() { long startTime = DateTime.Now.Ticks; long result = Slow500Square(40); long durationInTicks = DateTime.Now.Ticks - startTime; Console.WriteLine("Square(40) = " + result + " [ordinary method invocation took " + durationInTicks / 10000 + " ms | " + durationInTicks + " ticks]"); Assert.That(durationInTicks / 10000, Is.GreaterThanOrEqualTo(500)); // ms startTime = DateTime.Now.Ticks; result = (long)slow500Square.DynamicInvoke(40); durationInTicks = DateTime.Now.Ticks - startTime; Console.WriteLine("Square(40) = " + result + " [non-memoized dynamic func invocation took " + durationInTicks / 10000 + " ms | " + durationInTicks + " ticks]"); Assert.That(durationInTicks / 10000, Is.GreaterThanOrEqualTo(500)); // ms startTime = DateTime.Now.Ticks; result = slow500Square.Invoke(40); durationInTicks = DateTime.Now.Ticks - startTime; Console.WriteLine("Square(40) = " + result + " [non-memoized func invocation took " + durationInTicks / 10000 + " ms | " + durationInTicks + " ticks]"); Assert.That(durationInTicks / 10000, Is.GreaterThanOrEqualTo(500)); // ms startTime = DateTime.Now.Ticks; result = slow500Square.Memoize().InstrumentWith(Console.WriteLine).GetMemoizer().InvokeWith(40); durationInTicks = DateTime.Now.Ticks - startTime; Console.WriteLine("Square(40) = " + result + " [first time 'on-the-spot-memoized', instrumented invocation took " + durationInTicks / 10000 + " ms | " + durationInTicks + " ticks]"); Assert.That(durationInTicks / 10000, Is.GreaterThanOrEqualTo(500)); // ms (not memoized invocation) startTime = DateTime.Now.Ticks; result = slow500Square.Memoize().InstrumentWith(Console.WriteLine).GetMemoizer().InvokeWith(40); durationInTicks = DateTime.Now.Ticks - startTime; Console.WriteLine("Square(40) = " + result + " [second time time 'on-the-spot-memoized' instrumented invocation took " + durationInTicks / 10000 + " ms | " + durationInTicks + " ticks]"); Assert.That(durationInTicks / 10000, Is.LessThan(20)); // ms (memoized invocation) startTime = DateTime.Now.Ticks; result = slow500Square.Memoize().InstrumentWith(Console.WriteLine).GetMemoizer().InvokeWith(50); durationInTicks = DateTime.Now.Ticks - startTime; Console.WriteLine("Square(50) = " + result + " [first time 'on-the-spot-memoized' instrumented invocation took " + durationInTicks / 10000 + " ms | " + durationInTicks + " ticks]"); Assert.That(durationInTicks / 10000, Is.GreaterThanOrEqualTo(500)); // ms (not memoized invocation) startTime = DateTime.Now.Ticks; result = slow500Square.Memoize().InstrumentWith(Console.WriteLine).GetMemoizer().InvokeWith(60); durationInTicks = DateTime.Now.Ticks - startTime; Console.WriteLine("Square(60) = " + result + " [first time 'on-the-spot-memoized' instrumented invocation took " + durationInTicks / 10000 + " ms | " + durationInTicks + " ticks]"); Assert.That(durationInTicks / 10000, Is.GreaterThanOrEqualTo(500)); // ms (not memoized invocation) startTime = DateTime.Now.Ticks; result = slow500Square.Memoize().InstrumentWith(Console.WriteLine).GetMemoizer().InvokeWith(50); durationInTicks = DateTime.Now.Ticks - startTime; Console.WriteLine("Square(50) = " + result + " [second time time 'on-the-spot-memoized' instrumented invocation took " + durationInTicks / 10000 + " ms | " + durationInTicks + " ticks]"); Assert.That(durationInTicks / 10000, Is.LessThan(20)); // ms (memoized invocation) startTime = DateTime.Now.Ticks; result = slow500Square.Memoize().InstrumentWith(Console.WriteLine).GetMemoizer().InvokeWith(60); durationInTicks = DateTime.Now.Ticks - startTime; Console.WriteLine("Square(60) = " + result + " [second time time 'on-the-spot-memoized' instrumented invocation took " + durationInTicks / 10000 + " ms | " + durationInTicks + " ticks]"); Assert.That(durationInTicks / 10000, Is.LessThan(20)); // ms (memoized invocation) // TODO: fails!! startTime = DateTime.Now.Ticks; IMemoizer <long, long> slow1000PowerOfThreeMemoizer1 = slow1000PowerOfThree.Memoize().InstrumentWith(Console.WriteLine).GetMemoizer(); result = slow1000PowerOfThree.Memoize().InstrumentWith(Console.WriteLine).GetMemoizer().InvokeWith(40); durationInTicks = DateTime.Now.Ticks - startTime; Console.WriteLine("PowerOfThree(40) = " + result + " [first time 'on-the-spot-memoized' instrumented invocation took " + durationInTicks / 10000 + " ms | " + durationInTicks + " ticks]"); Assert.That(durationInTicks / 10000, Is.GreaterThanOrEqualTo(1000)); // ms (not memoized invocation) startTime = DateTime.Now.Ticks; IMemoizer <long, long> slow1000PowerOfThreeMemoizer2 = slow1000PowerOfThree.Memoize().InstrumentWith(Console.WriteLine).GetMemoizer(); result = slow1000PowerOfThree.Memoize().InstrumentWith(Console.WriteLine).GetMemoizer().InvokeWith(40); durationInTicks = DateTime.Now.Ticks - startTime; Console.WriteLine("PowerOfThree(40) = " + result + " [second time time 'on-the-spot-memoized' instrumented invocation took " + durationInTicks / 10000 + " ms | " + durationInTicks + " ticks]"); Assert.That(slow1000PowerOfThreeMemoizer1, Is.SameAs(slow1000PowerOfThreeMemoizer2)); Assert.That(durationInTicks / 10000, Is.LessThan(10)); // ms (memoized invocation) startTime = DateTime.Now.Ticks; result = slow1000PowerOfThree.CachedInvoke <long, long>(40); durationInTicks = DateTime.Now.Ticks - startTime; Console.WriteLine("PowerOfThree(40) = " + result + " [third time time 'on-the-spot-memoized' not-instrumented invocation took " + durationInTicks / 10000 + " ms | " + durationInTicks + " ticks]"); Assert.That(durationInTicks / 10000, Is.LessThan(10)); // ms (memoized invocation) }