示例#1
0
        public void MetricsErrorCacheEntry_Simple()
        {
            try
            {
                throw new Exception();
            }
            catch (Exception ex)
            {
                var entry = new MetricsErrorCacheEntry <int, int>(42, ex);

                Assert.AreEqual(42, entry.Key);
                Assert.AreSame(ex, entry.Exception);

                var stack = ex.StackTrace;
                try
                {
                    _ = entry.Value;
                }
                catch (Exception ex2)
                {
                    Assert.AreSame(ex, ex2);
                    Assert.AreEqual(stack, ex2.StackTrace.Substring(0, stack.Length));
                }

                Assert.AreEqual(0, entry.HitCount);
                Assert.AreEqual(0L, entry.CreationTime.Ticks);
                Assert.AreEqual(0L, entry.InvokeDuration.Ticks);
                Assert.AreEqual(0L, entry.LastAccessTime.Ticks);
                Assert.AreEqual(0L, entry.TotalDuration.Ticks);

                //
                // NB: AverageAccessTime and SpeedupFactor throw DivideByZeroException until values are
                //     initialized. Accesses to those properties is guaranteed to happen after the hit
                //     count has been incremented to 1, so this is not an issue.
                //

                Assert.ThrowsException <DivideByZeroException>(() => entry.AverageAccessTime);
                Assert.ThrowsException <DivideByZeroException>(() => entry.SpeedupFactor);

                entry.HitCount++;
                Assert.AreEqual(0L, entry.AverageAccessTime.Ticks);
                Assert.IsTrue(double.IsNaN(entry.SpeedupFactor)); // can only happen if access time is zero

                entry.TotalDuration = TimeSpan.FromTicks(27182818284590451L);
                Assert.AreEqual(27182818284590451L, entry.AverageAccessTime.Ticks);
                Assert.AreEqual(0.0, entry.SpeedupFactor);

                entry.InvokeDuration = TimeSpan.FromTicks(31415926535897931L);
                Assert.AreEqual(27182818284590451L, entry.AverageAccessTime.Ticks);
                Assert.AreEqual((double)31415926535897931L / 27182818284590451L, entry.SpeedupFactor);

                entry.HitCount++;
                Assert.AreEqual(27182818284590451L / 2, entry.AverageAccessTime.Ticks);
                Assert.AreEqual((double)31415926535897931L / (27182818284590451L / 2), entry.SpeedupFactor);

                var sb = new StringBuilder();
                entry.ToDebugView(sb, "");
                Assert.IsTrue(sb.ToString().Contains("="));
            }
        }
示例#2
0
                public Cache(Func <T, R> function, Func <IMemoizationCacheEntryMetrics, TMetric> ranker, int maxCapacity, bool descending, double ageThreshold, bool cacheError, IStopwatchFactory stopwatchFactory)
                {
                    _function = args =>
                    {
                        var weakArgs = WeakReferenceExtensions.Create(args);

                        var invokeDuration = default(TimeSpan);
#if DEBUG
                        Interlocked.Increment(ref _invocationCount);
#endif
                        Trim();

                        var res = default(IMetricsCacheEntry <WeakReference <T>, R>);
                        try
                        {
                            var swInvokeStart = _stopwatch.ElapsedTicks;

                            var value = function(args);

                            invokeDuration = new TimeSpan(_stopwatch.ElapsedTicks - swInvokeStart);

                            res = new MetricsValueCacheEntry <WeakReference <T>, R>(weakArgs, value);
                        }
                        catch (Exception ex) when(_cacheError)
                        {
                            res = new MetricsErrorCacheEntry <WeakReference <T>, R>(weakArgs, ex);
                        }

                        res.CreationTime   = new TimeSpan(_stopwatch.ElapsedTicks);
                        res.InvokeDuration = invokeDuration;

                        _lock.EnterWriteLock();
                        try
                        {
                            _entries.Add(res);
                        }
                        finally
                        {
                            _lock.ExitWriteLock();
                        }

                        return(res);
                    };

                    _cache     = new WeakCacheDictionary <T, IMetricsCacheEntry <WeakReference <T>, R> >();
                    _lock      = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion);
                    _entries   = new HashSet <IMetricsCacheEntry <WeakReference <T>, R> >();
                    _stopwatch = stopwatchFactory.StartNew();

                    //
                    // Exclude newest items which have statically irrelevant data, so they get a chance to become relevant.
                    //
                    var candidates = _entries.OrderBy(e => _stopwatch.ElapsedTicks - e.CreationTime.Ticks).Take(Math.Max(1, (int)(maxCapacity * ageThreshold)));
                    _ranker = descending ? candidates.OrderByDescending(e => ranker(e)) : candidates.OrderBy(e => ranker(e));

                    _maxCapacity = maxCapacity;
                    _cacheError  = cacheError;
                }
示例#3
0
                public Cache(Func <T, R> function, Func <IMemoizationCacheEntryMetrics, TMetric> ranker, int maxCapacity, bool descending, double ageThreshold, IEqualityComparer <T> comparer, bool cacheError, IStopwatchFactory stopwatchFactory)
                {
                    _function = args =>
                    {
                        var invokeDuration = default(TimeSpan);
#if DEBUG
                        _invocationCount++;
#endif
                        Trim();

                        var res = default(IMetricsCacheEntry <T, R>);
                        try
                        {
                            var swInvokeStart = _stopwatch.ElapsedTicks;

                            var value = function(args);

                            invokeDuration = new TimeSpan(_stopwatch.ElapsedTicks - swInvokeStart);

                            res = new MetricsValueCacheEntry <T, R>(args, value);
                        }
                        catch (Exception ex) when(_cacheError)
                        {
                            res = new MetricsErrorCacheEntry <T, R>(args, ex);
                        }

                        res.CreationTime   = new TimeSpan(_stopwatch.ElapsedTicks);
                        res.InvokeDuration = invokeDuration;

                        return(res);
                    };

                    _cache     = new CacheDictionary <T, IMetricsCacheEntry <T, R> >(comparer);
                    _stopwatch = stopwatchFactory.StartNew();

                    //
                    // Exclude newest items which have statically irrelevant data, so they get a chance to become relevant.
                    //
                    var candidates = _cache.Values.OrderBy(e => _stopwatch.ElapsedTicks - e.CreationTime.Ticks).Take(Math.Max(1, (int)(maxCapacity * ageThreshold)));
                    _ranker = descending ? candidates.OrderByDescending(e => ranker(e)) : candidates.OrderBy(e => ranker(e));

                    _maxCapacity = maxCapacity;
                    _cacheError  = cacheError;
                }