Helpers.cs 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. // Licensed to the .NET Foundation under one or more agreements.
  2. // The .NET Foundation licenses this file to you under the MIT License.
  3. // See the LICENSE file in the project root for more information.
  4. #if STRESS
  5. using System;
  6. using System.Collections.Generic;
  7. using System.Diagnostics;
  8. using System.Threading;
  9. using System.Linq;
  10. namespace ReactiveTests.Stress
  11. {
  12. public static class Helpers
  13. {
  14. public static void RunWithMemoryPressure(int minBytes, int maxBytes, double activePercent, Action a)
  15. {
  16. var started = new ManualResetEvent(false);
  17. var stopped = 0;
  18. var avg = (minBytes + maxBytes) / 2;
  19. var MIN = avg / 1000;
  20. var MAX = avg / 10;
  21. var allocator = new Thread(() =>
  22. {
  23. var rand = new Random();
  24. var roots = new List<byte[]>();
  25. var bytes = 0;
  26. while (bytes < avg)
  27. {
  28. var n = rand.Next(MIN, MAX);
  29. bytes += n;
  30. roots.Add(new byte[n]);
  31. }
  32. started.Set();
  33. long avgSum = 0;
  34. long count = 0;
  35. const int DEC = 0;
  36. const int INC = 1;
  37. var trendPhase = 0;
  38. var trendLength = 0;
  39. while (Thread.VolatileRead(ref stopped) == 0)
  40. {
  41. if (trendLength-- == 0)
  42. {
  43. trendPhase = rand.Next(0, 1000) % 2;
  44. trendLength = rand.Next(1, 10);
  45. }
  46. var mem = TimeSpan.Zero;
  47. var sw = Stopwatch.StartNew();
  48. var busy = new Stopwatch();
  49. while (Thread.VolatileRead(ref stopped) == 0 && (double)mem.Ticks / (double)sw.ElapsedTicks < activePercent)
  50. {
  51. busy.Restart();
  52. var runFor = rand.Next(10, 100);
  53. while (busy.ElapsedMilliseconds < runFor)
  54. {
  55. if (trendPhase == INC)
  56. {
  57. if (bytes < maxBytes)
  58. {
  59. var n = rand.Next(MIN, MAX);
  60. bytes += n;
  61. roots.Add(new byte[n]);
  62. continue;
  63. }
  64. else
  65. {
  66. trendPhase = DEC;
  67. }
  68. }
  69. if (trendPhase == DEC)
  70. {
  71. if (bytes > minBytes)
  72. {
  73. if (roots.Count > 0)
  74. {
  75. var i = rand.Next(0, roots.Count);
  76. bytes -= roots[i].Length;
  77. roots.RemoveAt(i);
  78. }
  79. continue;
  80. }
  81. else
  82. {
  83. trendPhase = INC;
  84. }
  85. }
  86. }
  87. mem += busy.Elapsed;
  88. }
  89. var sleepFor = rand.Next(100, 1000);
  90. Thread.Sleep(sleepFor);
  91. avgSum += bytes;
  92. count++;
  93. //Console.WriteLine(bytes + " - Avg = " + avgSum / count);
  94. }
  95. });
  96. allocator.Start();
  97. started.WaitOne();
  98. try
  99. {
  100. a();
  101. }
  102. finally
  103. {
  104. Interlocked.Exchange(ref stopped, 1);
  105. allocator.Join();
  106. }
  107. }
  108. public static void RunWithProcessorPressure(int threadCount, int lockCount, double activePercent, double lockChancePercent, Action a)
  109. {
  110. var stopped = 0;
  111. var started = new CountdownEvent(threadCount);
  112. var ts = new Thread[threadCount];
  113. var locks = Enumerable.Range(0, lockCount).Select(_ => new object()).ToArray();
  114. for (int i = 0; i < threadCount; i++)
  115. {
  116. var id = i;
  117. var t = ts[i] = new Thread(() =>
  118. {
  119. var rand = new Random();
  120. started.Signal();
  121. var sw = Stopwatch.StartNew();
  122. var run = TimeSpan.Zero;
  123. while (Thread.VolatileRead(ref stopped) == 0)
  124. {
  125. var busy = new Stopwatch();
  126. while (Thread.VolatileRead(ref stopped) == 0 && (double)run.Ticks / (double)sw.ElapsedTicks < activePercent)
  127. {
  128. busy.Restart();
  129. const int RUN = 0;
  130. const int BLOCK = 1;
  131. var action = lockCount > 0 && rand.Next() % 100 <= lockChancePercent * 100 ? BLOCK : RUN;
  132. switch (action)
  133. {
  134. case RUN:
  135. //Console.WriteLine("~" + id);
  136. while (busy.ElapsedMilliseconds < 10)
  137. ;
  138. break;
  139. case BLOCK:
  140. //Console.WriteLine("!" + id);
  141. lock (locks[rand.Next(0, lockCount)])
  142. Thread.Sleep(rand.Next(100, 1000));
  143. break;
  144. }
  145. run += busy.Elapsed;
  146. }
  147. Thread.Sleep(rand.Next(100, 1000));
  148. }
  149. });
  150. t.Start();
  151. }
  152. started.Wait();
  153. try
  154. {
  155. a();
  156. }
  157. finally
  158. {
  159. Interlocked.Exchange(ref stopped, 1);
  160. foreach (var t in ts)
  161. t.Join();
  162. }
  163. }
  164. public static void SleepOrSpin(int ms)
  165. {
  166. if (ms == 0)
  167. return;
  168. if (ms % 2 == 0)
  169. {
  170. var sw = Stopwatch.StartNew();
  171. while (sw.Elapsed.TotalMilliseconds < ms)
  172. ;
  173. }
  174. else
  175. Thread.Sleep(ms);
  176. }
  177. }
  178. }
  179. #endif