コード例 #1
0
        public async Task CacheManager_Stats_Threaded <T>(T cache)
            where T : ICacheManager <object>
        {
            var puts       = cache.CacheHandles.Select(p => p.Stats.GetStatistic(CacheStatsCounterType.PutCalls));
            var adds       = cache.CacheHandles.Select(p => p.Stats.GetStatistic(CacheStatsCounterType.AddCalls));
            var threads    = 4;
            var iterations = 10;
            var putCounter = 0;

            using (cache)
            {
                var key = Guid.NewGuid().ToString();
                await ThreadTestHelper.RunAsync(
                    async() =>
                {
                    cache.Add(key, "hi");
                    cache.Put(key, "changed");
                    Interlocked.Increment(ref putCounter);
                    await Task.Delay(0);
                },
                    threads,
                    iterations);
            }

            await Task.Delay(20);

            putCounter.Should().Be(threads * iterations);
            puts.ShouldAllBeEquivalentTo(
                Enumerable.Repeat(threads * iterations, cache.CacheHandles.Count()));
        }
コード例 #2
0
        public void CacheManager_Stats_Threaded <T>(T cache)
            where T : ICacheManager <object>
        {
            var puts       = cache.CacheHandles.Select(p => p.Stats.GetStatistic(CacheStatsCounterType.PutCalls));
            var adds       = cache.CacheHandles.Select(p => p.Stats.GetStatistic(CacheStatsCounterType.AddCalls));
            var threads    = 5;
            var iterations = 10;

            using (cache)
            {
                var key = Guid.NewGuid().ToString();
                ThreadTestHelper.Run(
                    () =>
                {
                    cache.Add(key, "hi");
                    cache.Put(key, "changed");
                },
                    threads,
                    iterations);
            }

            // item should have been added only once (not true in back plate scenarios)
            if (!cache.Configuration.HasBackPlate)
            {
                adds.ShouldAllBeEquivalentTo(
                    Enumerable.Repeat(1, cache.CacheHandles.Count()));
            }

            puts.ShouldAllBeEquivalentTo(
                Enumerable.Repeat(threads * iterations, cache.CacheHandles.Count()));
        }
コード例 #3
0
        public async Task Redis_NoRaceCondition_WithUpdate()
        {
            using (var cache = CacheFactory.Build <RaceConditionTestElement>(settings =>
            {
                settings.WithMaxRetries(int.MaxValue);
                settings.WithUpdateMode(CacheUpdateMode.Up)
                .WithJsonSerializer()
                .WithRedisCacheHandle("default")
                .WithExpiration(ExpirationMode.Absolute, TimeSpan.FromMinutes(20));
                settings.WithRedisConfiguration("default", config =>
                {
                    config.WithAllowAdmin()
                    .WithDatabase(7)
                    .WithEndpoint("127.0.0.1", 6379);
                });
            }))
            {
                var key = Guid.NewGuid().ToString();
                cache.Remove(key);
                cache.Add(key, new RaceConditionTestElement()
                {
                    Counter = 0
                });
                int numThreads          = 5;
                int iterations          = 10;
                int numInnerIterations  = 10;
                int countCasModifyCalls = 0;

                // act
                await ThreadTestHelper.RunAsync(
                    async() =>
                {
                    for (int i = 0; i < numInnerIterations; i++)
                    {
                        cache.Update(
                            key,
                            (value) =>
                        {
                            value.Counter++;
                            Interlocked.Increment(ref countCasModifyCalls);
                            return(value);
                        },
                            int.MaxValue);

                        await Task.Delay(0);
                    }
                },
                    numThreads,
                    iterations);

                // assert
                await Task.Delay(100);

                var result = cache.Get(key);
                result.Should().NotBeNull();
                result.Counter.Should().Be(numThreads * numInnerIterations * iterations, "counter should be exactly the expected value");
                countCasModifyCalls.Should().BeGreaterThan((int)result.Counter, "we expect many version collisions, so cas calls should be way higher then the count result");
            }
        }
コード例 #4
0
        public async Task Memcached_NoRaceCondition_WithCasButTooFiewRetries()
        {
            // arrange
            using (var cache = CacheFactory.FromConfiguration <RaceConditionTestElement>(
                       TestManagers.BaseConfiguration.Builder
                       .WithUpdateMode(CacheUpdateMode.Up)
                       .WithMemcachedCacheHandle(Configuration)
                       .WithExpiration(ExpirationMode.Absolute, TimeSpan.FromHours(10))
                       .Build()))
            {
                cache.Remove("myCounter");
                cache.Add("myCounter", new RaceConditionTestElement()
                {
                    Counter = 0
                });
                int numThreads          = 5;
                int iterations          = 10;
                int numInnerIterations  = 10;
                int countCasModifyCalls = 0;
                int retries             = 0;

                // act
                await ThreadTestHelper.RunAsync(
                    async() =>
                {
                    for (int i = 0; i < numInnerIterations; i++)
                    {
                        RaceConditionTestElement newValue;
                        cache.TryUpdate(
                            "myCounter",
                            (value) =>
                        {
                            value.Counter++;
                            Interlocked.Increment(ref countCasModifyCalls);
                            return(value);
                        },
                            retries,
                            out newValue);
                    }

                    await Task.Delay(10);
                },
                    numThreads,
                    iterations);

                // assert
                var result = cache.Get("myCounter");
                result.Should().NotBeNull();
                Trace.TraceInformation("Counter increased to " + result.Counter + " cas calls needed " + countCasModifyCalls);
                result.Counter.Should().BeLessThan(
                    numThreads * numInnerIterations * iterations,
                    "counter should NOT be exactly the expected value");
                countCasModifyCalls.Should().Be(
                    numThreads * numInnerIterations * iterations,
                    "with one try, we exactly one update call per iteration");
            }
        }
コード例 #5
0
        public void Thread_Update(ICacheManager <object> cache)
        {
            using (cache)
            {
                var key        = Guid.NewGuid().ToString();
                var handleInfo = string.Join("\nh: ", cache.CacheHandles.Select(p => p.Configuration.HandleName + ":" + p.GetType().Name));

                cache.Remove(key);
                cache.Add(key, new RaceConditionTestElement()
                {
                    Counter = 0
                });
                int numThreads          = 5;
                int iterations          = 10;
                int numInnerIterations  = 10;
                int countCasModifyCalls = 0;

                // act
                ThreadTestHelper.Run(
                    () =>
                {
                    for (int i = 0; i < numInnerIterations; i++)
                    {
                        cache.Update(key, (value) =>
                        {
                            var val = (RaceConditionTestElement)value;
                            val.Counter++;
                            Interlocked.Increment(ref countCasModifyCalls);
                            return(value);
                        });
                    }
                },
                    numThreads,
                    iterations);

                // assert
                Thread.Sleep(10);
                for (var i = 0; i < cache.CacheHandles.Count(); i++)
                {
                    var handle = cache.CacheHandles.ElementAt(i);
                    var result = (RaceConditionTestElement)handle.Get(key);
                    if (i < cache.CacheHandles.Count() - 1)
                    {
                        // only the last one should have the item
                        result.Should().BeNull();
                    }
                    else
                    {
                        result.Should().NotBeNull(handleInfo + "\ncurrent: " + handle.Configuration.HandleName + ":" + handle.GetType().Name);
                        result.Counter.Should().Be(numThreads * numInnerIterations * iterations, handleInfo + "\ncounter should be exactly the expected value.");
                        countCasModifyCalls.Should().BeGreaterOrEqualTo((int)result.Counter, handleInfo + "\nexpecting no (if synced) or some version collisions.");
                    }
                }
            }
        }
コード例 #6
0
        public void Memcached_NoRaceCondition_WithCasButTooFiewRetries()
        {
            // arrange
            using (var cache = CacheFactory.Build <RaceConditionTestElement>(settings =>
            {
                settings.WithUpdateMode(CacheUpdateMode.Full)
                .WithMemcachedCacheHandle("default")
                .WithExpiration(ExpirationMode.Absolute, TimeSpan.FromHours(10));
            }))
            {
                cache.Remove("myCounter");
                cache.Add("myCounter", new RaceConditionTestElement()
                {
                    Counter = 0
                });
                int numThreads          = 5;
                int iterations          = 10;
                int numInnerIterations  = 10;
                int countCasModifyCalls = 0;
                int retries             = 0;

                // act
                ThreadTestHelper.Run(
                    () =>
                {
                    for (int i = 0; i < numInnerIterations; i++)
                    {
                        cache.Update(
                            "myCounter",
                            (value) =>
                        {
                            value.Counter++;
                            Interlocked.Increment(ref countCasModifyCalls);
                            return(value);
                        },
                            new UpdateItemConfig(retries, VersionConflictHandling.EvictItemFromOtherCaches));
                    }
                },
                    numThreads,
                    iterations);

                // assert
                Thread.Sleep(10);
                var result = cache.Get("myCounter");
                result.Should().NotBeNull();
                Trace.TraceInformation("Counter increased to " + result.Counter + " cas calls needed " + countCasModifyCalls);
                result.Counter.Should().BeLessThan(
                    numThreads * numInnerIterations * iterations,
                    "counter should NOT be exactly the expected value");
                countCasModifyCalls.Should().Be(
                    numThreads * numInnerIterations * iterations,
                    "with one try, we exactly one update call per iteration");
            }
        }
コード例 #7
0
        public async Task Memcached_NoRaceCondition_WithCasHandling()
        {
            // arrange
            using (var cache = CacheFactory.FromConfiguration <RaceConditionTestElement>(
                       TestManagers.BaseConfiguration.Builder
                       .WithMaxRetries(int.MaxValue)
                       .WithSystemRuntimeCacheHandle()
                       .WithExpiration(ExpirationMode.Absolute, TimeSpan.FromMilliseconds(1))
                       .And
                       .WithMemcachedCacheHandle(Configuration)
                       .WithExpiration(ExpirationMode.Absolute, TimeSpan.FromSeconds(60))
                       .Build()))
            {
                var key = Guid.NewGuid().ToString();
                cache.Remove(key);
                cache.Add(key, new RaceConditionTestElement()
                {
                    Counter = 0
                }).Should().BeTrue();
                int numThreads          = 5;
                int iterations          = 10;
                int numInnerIterations  = 10;
                int countCasModifyCalls = 0;

                // act
                await ThreadTestHelper.RunAsync(
                    async() =>
                {
                    for (int i = 0; i < numInnerIterations; i++)
                    {
                        cache.Update(
                            key,
                            (value) =>
                        {
                            value.Counter++;
                            Interlocked.Increment(ref countCasModifyCalls);
                            return(value);
                        });
                    }

                    await Task.Delay(10);
                },
                    numThreads,
                    iterations);

                // assert
                var result = cache.Get(key);
                result.Should().NotBeNull();
                Trace.WriteLine("Counter increased to " + result.Counter + " cas calls needed " + countCasModifyCalls);
                result.Counter.Should().Be(numThreads * numInnerIterations * iterations, "counter should be exactly the expected value");
                countCasModifyCalls.Should().BeGreaterThan((int)result.Counter, "we expect many version collisions, so cas calls should be way higher then the count result");
            }
        }
コード例 #8
0
        public void Memcached_NoRaceCondition_WithCasHandling_WithRegion()
        {
            // arrange
            using (var cache = CacheFactory.Build <RaceConditionTestElement>(settings =>
            {
                settings.WithUpdateMode(CacheUpdateMode.Up)
                .WithMemcachedCacheHandle(Configuration)
                .WithExpiration(ExpirationMode.Absolute, TimeSpan.FromMinutes(10));
            }))
            {
                var region = "region";
                var key    = "myKey";
                cache.Remove(key, region);
                cache.Add(key, new RaceConditionTestElement()
                {
                    Counter = 0
                }, region);
                int numThreads          = 5;
                int iterations          = 10;
                int numInnerIterations  = 10;
                int countCasModifyCalls = 0;

                // act
                ThreadTestHelper.Run(
                    () =>
                {
                    for (int i = 0; i < numInnerIterations; i++)
                    {
                        cache.Update(
                            key,
                            region,
                            (value) =>
                        {
                            value.Counter++;
                            Interlocked.Increment(ref countCasModifyCalls);
                            return(value);
                        },
                            500);
                    }
                },
                    numThreads,
                    iterations);

                // assert
                Thread.Sleep(10);
                var result = cache.Get(key, region);
                result.Should().NotBeNull();
                Trace.TraceInformation("Counter increased to " + result.Counter + " cas calls needed " + countCasModifyCalls);
                result.Counter.Should().Be(numThreads * numInnerIterations * iterations, "counter should be exactly the expected value");
                countCasModifyCalls.Should().BeGreaterThan((int)result.Counter, "we expect many version collisions, so cas calls should be way higher then the count result");
            }
        }
コード例 #9
0
        public void Memcached_NoRaceCondition_WithCasHandling()
        {
            // arrange
            using (var cache = CacheFactory.Build <RaceConditionTestElement>(settings =>
            {
                settings.WithUpdateMode(CacheUpdateMode.Full)
                .WithSystemRuntimeDefaultCacheHandle()
                .WithExpiration(ExpirationMode.Absolute, TimeSpan.FromMilliseconds(1))
                .And
                .WithMemcachedCacheHandle("default")
                .WithExpiration(ExpirationMode.Absolute, TimeSpan.FromSeconds(10));
            }))
            {
                cache.Remove("myCounter");
                cache.Add("myCounter", new RaceConditionTestElement()
                {
                    Counter = 0
                });
                int numThreads          = 5;
                int iterations          = 10;
                int numInnerIterations  = 10;
                int countCasModifyCalls = 0;

                // act
                ThreadTestHelper.Run(
                    () =>
                {
                    for (int i = 0; i < numInnerIterations; i++)
                    {
                        cache.Update(
                            "myCounter",
                            (value) =>
                        {
                            value.Counter++;
                            Interlocked.Increment(ref countCasModifyCalls);
                            return(value);
                        },
                            new UpdateItemConfig(50, VersionConflictHandling.EvictItemFromOtherCaches));
                    }
                },
                    numThreads,
                    iterations);

                // assert
                Thread.Sleep(10);
                var result = cache.Get("myCounter");
                result.Should().NotBeNull();
                Trace.WriteLine("Counter increased to " + result.Counter + " cas calls needed " + countCasModifyCalls);
                result.Counter.Should().Be(numThreads * numInnerIterations * iterations, "counter should be exactly the expected value");
                countCasModifyCalls.Should().BeGreaterThan((int)result.Counter, "we expect many version collisions, so cas calls should be way higher then the count result");
            }
        }
コード例 #10
0
        public async Task Redis_RaceCondition_WithoutUpdate()
        {
            using (var cache = CacheFactory.Build <RaceConditionTestElement>(settings =>
            {
                settings.WithUpdateMode(CacheUpdateMode.Up)
                .WithJsonSerializer()
                .WithRedisCacheHandle("default")
                .WithExpiration(ExpirationMode.Absolute, TimeSpan.FromMinutes(20));
                settings.WithRedisConfiguration("default", config =>
                {
                    config.WithAllowAdmin()
                    .WithDatabase(8)
                    .WithEndpoint("127.0.0.1", 6379);
                });
            }))
            {
                var key = Guid.NewGuid().ToString();
                cache.Add(key, new RaceConditionTestElement()
                {
                    Counter = 0
                });
                int numThreads         = 5;
                int iterations         = 10;
                int numInnerIterations = 10;

                // act
                await ThreadTestHelper.RunAsync(
                    async() =>
                {
                    for (int i = 0; i < numInnerIterations; i++)
                    {
                        var val = cache.Get(key);
                        val.Should().NotBeNull();
                        val.Counter++;

                        cache.Put(key, val);
                        await Task.Delay(1);
                    }
                },
                    numThreads,
                    iterations);

                // assert
                await Task.Delay(10);

                var result = cache.Get(key);
                result.Should().NotBeNull();
                result.Counter.Should().NotBe(numThreads * numInnerIterations * iterations);
            }
        }
コード例 #11
0
ファイル: RedisTests.cs プロジェクト: gopimails/CacheManager
        public void Redis_RaceCondition_WithoutUpdate()
        {
            using (var cache = CacheFactory.Build <RaceConditionTestElement>("myCache", settings =>
            {
                settings.WithUpdateMode(CacheUpdateMode.Full)
                .WithRedisCacheHandle("default")
                .WithExpiration(ExpirationMode.Absolute, TimeSpan.FromMinutes(20));
                settings.WithRedisConfiguration("default", config =>
                {
                    config.WithAllowAdmin()
                    .WithDatabase(8)
                    .WithEndpoint("127.0.0.1", 6379);
                });
            }))
            {
                var key = Guid.NewGuid().ToString();
                cache.Add(key, new RaceConditionTestElement()
                {
                    Counter = 0
                });
                int numThreads         = 5;
                int iterations         = 10;
                int numInnerIterations = 10;

                // act
                ThreadTestHelper.Run(() =>
                {
                    for (int i = 0; i < numInnerIterations; i++)
                    {
                        var val = cache.Get(key);
                        val.Should().NotBeNull();
                        val.Counter++;

                        cache.Put(key, val);
                    }
                }, numThreads, iterations);

                // assert
                Thread.Sleep(10);
                var result = cache.Get(key);
                result.Should().NotBeNull();
                Trace.TraceInformation("Counter increased to " + result.Counter);
                result.Counter.Should().NotBe(numThreads * numInnerIterations * iterations);
            }
        }
コード例 #12
0
        public async Task Memcached_RaceCondition_WithoutCasHandling()
        {
            // arrange
            using (var cache = CacheFactory.FromConfiguration <RaceConditionTestElement>(
                       TestManagers.BaseConfiguration.Builder
                       .WithUpdateMode(CacheUpdateMode.Up)
                       .WithMemcachedCacheHandle(Configuration)
                       .WithExpiration(ExpirationMode.Absolute, TimeSpan.FromMinutes(20))
                       .Build()))
            {
                var key = Guid.NewGuid().ToString();
                cache.Remove(key);
                cache.Add(key, new RaceConditionTestElement()
                {
                    Counter = 0
                });
                int numThreads         = 5;
                int iterations         = 10;
                int numInnerIterations = 10;

                // act
                await ThreadTestHelper.RunAsync(
                    async() =>
                {
                    for (int i = 0; i < numInnerIterations; i++)
                    {
                        var val = cache.Get(key);
                        val.Should().NotBeNull();
                        val.Counter++;

                        cache.Put(key, val);
                    }

                    await Task.Delay(10);
                },
                    numThreads,
                    iterations);

                // assert
                var result = cache.Get(key);
                result.Should().NotBeNull();
                Trace.TraceInformation("Counter increased to " + result.Counter);
                result.Counter.Should().NotBe(numThreads * numInnerIterations * iterations);
            }
        }
コード例 #13
0
        public void Memcached_RaceCondition_WithoutCasHandling()
        {
            // arrange
            using (var cache = CacheFactory.Build <RaceConditionTestElement>(settings =>
            {
                settings.WithUpdateMode(CacheUpdateMode.Up)
                .WithMemcachedCacheHandle(Configuration)
                .WithExpiration(ExpirationMode.Absolute, TimeSpan.FromMinutes(20));
            }))
            {
                cache.Remove("myCounter");
                cache.Add("myCounter", new RaceConditionTestElement()
                {
                    Counter = 0
                });
                int numThreads         = 5;
                int iterations         = 10;
                int numInnerIterations = 10;

                // act
                ThreadTestHelper.Run(
                    () =>
                {
                    for (int i = 0; i < numInnerIterations; i++)
                    {
                        var val = cache.Get("myCounter");
                        val.Should().NotBeNull();
                        val.Counter++;

                        cache.Put("myCounter", val);
                    }
                },
                    numThreads,
                    iterations);

                // assert
                Thread.Sleep(10);
                var result = cache.Get("myCounter");
                result.Should().NotBeNull();
                Trace.TraceInformation("Counter increased to " + result.Counter);
                result.Counter.Should().NotBe(numThreads * numInnerIterations * iterations);
            }
        }
コード例 #14
0
        public void CacheManager_Stats_Threaded <T>(T cache)
            where T : ICacheManager <object>
        {
            var puts       = cache.CacheHandles.Select(p => p.Stats.GetStatistic(CacheStatsCounterType.PutCalls));
            var adds       = cache.CacheHandles.Select(p => p.Stats.GetStatistic(CacheStatsCounterType.AddCalls));
            var threads    = 5;
            var iterations = 10;

            using (cache)
            {
                var key = Guid.NewGuid().ToString();
                ThreadTestHelper.Run(
                    () =>
                {
                    cache.Add(key, "hi");
                    cache.Put(key, "changed");
                },
                    threads,
                    iterations);
            }

            puts.ShouldAllBeEquivalentTo(
                Enumerable.Repeat(threads * iterations, cache.CacheHandles.Count()));
        }
コード例 #15
0
        public void Thread_RandomAccess(ICacheManager <object> cache)
        {
            NotNull(cache, nameof(cache));

            foreach (var handle in cache.CacheHandles)
            {
                Trace.TraceInformation("Using handle {0}", handle.GetType());
            }

            var blob = new byte[1024];

            using (cache)
            {
                Action test = () =>
                {
                    var hits   = 0;
                    var misses = 0;
                    var tId    = Thread.CurrentThread.ManagedThreadId;

                    try
                    {
                        for (var r = 0; r < 5; r++)
                        {
                            for (int i = 0; i < 5; i++)
                            {
                                string key    = "key" + i;
                                object value  = blob.Clone();
                                string region = "region" + r;

                                CacheItem <object> item = null;
                                if (r % 2 == 0)
                                {
                                    item = new CacheItem <object>(key, value, ExpirationMode.Sliding, TimeSpan.FromMilliseconds(10));
                                }
                                else
                                {
                                    item = new CacheItem <object>(key, region, value, ExpirationMode.Absolute, TimeSpan.FromMilliseconds(10));
                                }

                                cache.Put(item);
                                if (!cache.Add(item))
                                {
                                    cache.Put(item);
                                }

                                var result = cache.Get(key);
                                if (result == null)
                                {
                                    misses++;
                                }
                                else
                                {
                                    hits++;
                                }

                                if (!cache.Remove(key))
                                {
                                    misses++;
                                }
                                else
                                {
                                    hits++;
                                }

                                Thread.Sleep(0);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        Debug.WriteLine("{1} Error: {0}", ex.Message, tId);
                        throw;
                    }

                    Debug.WriteLine("Hits: {0}, Misses: {1}", hits, misses);
                };

                ThreadTestHelper.Run(test, 2, 1);
            }
        }