| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216 | // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.#if STRESSusing System;using System.Collections.Generic;using System.Diagnostics;using System.Threading;using System.Linq;namespace ReactiveTests.Stress{    public static class Helpers    {        public static void RunWithMemoryPressure(int minBytes, int maxBytes, double activePercent, Action a)        {            var started = new ManualResetEvent(false);            var stopped = 0;            var avg = (minBytes + maxBytes) / 2;            var MIN = avg / 1000;            var MAX = avg / 10;            var allocator = new Thread(() =>            {                var rand = new Random();                var roots = new List<byte[]>();                var bytes = 0;                while (bytes < avg)                {                    var n = rand.Next(MIN, MAX);                    bytes += n;                    roots.Add(new byte[n]);                }                started.Set();                long avgSum = 0;                long count = 0;                const int DEC = 0;                const int INC = 1;                var trendPhase = 0;                var trendLength = 0;                while (Thread.VolatileRead(ref stopped) == 0)                {                    if (trendLength-- == 0)                    {                        trendPhase = rand.Next(0, 1000) % 2;                        trendLength = rand.Next(1, 10);                    }                    var mem = TimeSpan.Zero;                    var sw = Stopwatch.StartNew();                    var busy = new Stopwatch();                    while (Thread.VolatileRead(ref stopped) == 0 && (double)mem.Ticks / (double)sw.ElapsedTicks < activePercent)                    {                        busy.Restart();                        var runFor = rand.Next(10, 100);                        while (busy.ElapsedMilliseconds < runFor)                        {                            if (trendPhase == INC)                            {                                if (bytes < maxBytes)                                {                                    var n = rand.Next(MIN, MAX);                                    bytes += n;                                    roots.Add(new byte[n]);                                    continue;                                }                                else                                {                                    trendPhase = DEC;                                }                            }                            if (trendPhase == DEC)                            {                                if (bytes > minBytes)                                {                                    if (roots.Count > 0)                                    {                                        var i = rand.Next(0, roots.Count);                                        bytes -= roots[i].Length;                                        roots.RemoveAt(i);                                    }                                    continue;                                }                                else                                {                                    trendPhase = INC;                                }                            }                        }                        mem += busy.Elapsed;                    }                    var sleepFor = rand.Next(100, 1000);                    Thread.Sleep(sleepFor);                    avgSum += bytes;                    count++;                    //Console.WriteLine(bytes + " - Avg = " + avgSum / count);                }            });            allocator.Start();            started.WaitOne();            try            {                a();            }            finally            {                Interlocked.Exchange(ref stopped, 1);                allocator.Join();            }        }        public static void RunWithProcessorPressure(int threadCount, int lockCount, double activePercent, double lockChancePercent, Action a)        {            var stopped = 0;            var started = new CountdownEvent(threadCount);            var ts = new Thread[threadCount];            var locks = Enumerable.Range(0, lockCount).Select(_ => new object()).ToArray();            for (int i = 0; i < threadCount; i++)            {                var id = i;                var t = ts[i] = new Thread(() =>                {                    var rand = new Random();                    started.Signal();                    var sw = Stopwatch.StartNew();                    var run = TimeSpan.Zero;                    while (Thread.VolatileRead(ref stopped) == 0)                    {                        var busy = new Stopwatch();                        while (Thread.VolatileRead(ref stopped) == 0 && (double)run.Ticks / (double)sw.ElapsedTicks < activePercent)                        {                            busy.Restart();                            const int RUN = 0;                            const int BLOCK = 1;                            var action = lockCount > 0 && rand.Next() % 100 <= lockChancePercent * 100 ? BLOCK : RUN;                            switch (action)                            {                                case RUN:                                    //Console.WriteLine("~" + id);                                    while (busy.ElapsedMilliseconds < 10)                                        ;                                    break;                                case BLOCK:                                    //Console.WriteLine("!" + id);                                    lock (locks[rand.Next(0, lockCount)])                                        Thread.Sleep(rand.Next(100, 1000));                                    break;                            }                            run += busy.Elapsed;                        }                        Thread.Sleep(rand.Next(100, 1000));                    }                });                t.Start();            }            started.Wait();            try            {                a();            }            finally            {                Interlocked.Exchange(ref stopped, 1);                foreach (var t in ts)                    t.Join();            }        }        public static void SleepOrSpin(int ms)        {            if (ms == 0)                return;            if (ms % 2 == 0)            {                var sw = Stopwatch.StartNew();                while (sw.Elapsed.TotalMilliseconds < ms)                    ;            }            else                Thread.Sleep(ms);        }    }}#endif
 |