PageRenderTime 45ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/base/Applications/Tests/MpStress/MpStress.cs

#
C# | 294 lines | 178 code | 68 blank | 48 comment | 22 complexity | 4c4e1e385ed3f0f168fb83f259edee91 MD5 | raw file
  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Microsoft Research Singularity
  4. //
  5. // Copyright (c) Microsoft Corporation. All rights reserved.
  6. //
  7. // Note: Perform short (bvt) and long running stress of multiprocessor
  8. // sensitive areas of the system. Used MonitorTest.cs as an
  9. // application template
  10. //
  11. using System;
  12. using System.Threading;
  13. using Microsoft.Singularity.UnitTest;
  14. using Microsoft.Singularity.Channels;
  15. using Microsoft.Contracts;
  16. using Microsoft.SingSharp.Reflection;
  17. using Microsoft.Singularity.Applications;
  18. using Microsoft.Singularity.Io;
  19. using Microsoft.Singularity.Configuration;
  20. [assembly: Transform(typeof(ApplicationResourceTransform))]
  21. namespace Microsoft.Singularity.Applications
  22. {
  23. [ConsoleCategory(DefaultAction=true)]
  24. internal class Parameters {
  25. [InputEndpoint("data")]
  26. public readonly TRef<UnicodePipeContract.Exp:READY> Stdin;
  27. [OutputEndpoint("data")]
  28. public readonly TRef<UnicodePipeContract.Imp:READY> Stdout;
  29. [LongParameter("cpucount", Default=2, HelpMessage="CPU Count for test")]
  30. internal long cpuCount;
  31. [LongParameter("passcount", Default=10, HelpMessage="Pass Count for test")]
  32. internal long passCount;
  33. reflective internal Parameters();
  34. internal int AppMain() {
  35. return MpStress.AppMain(this);
  36. }
  37. }
  38. public class MpStress
  39. {
  40. internal static int AppMain(Parameters! config)
  41. {
  42. int result;
  43. Console.WriteLine("Running MpStress for CPU Count {0}", config.cpuCount);
  44. ThreadTest tt = new ThreadTest();
  45. result = tt.RunTest(config.cpuCount, config.passCount);
  46. if (result != 0) {
  47. return result;
  48. }
  49. return 0;
  50. }
  51. }
  52. public class ThreadTest
  53. {
  54. public int RunTest(long cpuCount, long passCount) {
  55. // Start the thread create/destroy test
  56. //ThreadTestsThread threadTests = new ThreadTestsThread(cpuCount);
  57. // Run pulse tests
  58. PulseTestsThread pulseTests = new PulseTestsThread(cpuCount, passCount);
  59. pulseTests.RunThread();
  60. // Start the background threads
  61. //threadTests.RunThread();
  62. // Wait for pulse tests to complete
  63. ((!)pulseTests.Thread).Join();
  64. return 0;
  65. }
  66. }
  67. //
  68. // Implementation classes represent different thread creation
  69. // parameters, and actions
  70. //
  71. public class PrintThread : ThreadRunner
  72. {
  73. private long argValue;
  74. public PrintThread(long arg) : base() {
  75. argValue = arg;
  76. }
  77. public override void ThreadMain() {
  78. //System.Console.WriteLine("PrintThread: Thread {0}, ThreadIndex {1}\n", Thread.CurrentThread.GetThreadId(), argValue);
  79. // Call some additional "interesting" system calls here in order to disturb
  80. // the system state, cause lock contention, flesh out races and unprotected code
  81. // regions, etc.
  82. //
  83. // This exits the thread
  84. //Console.Write("-");
  85. return;
  86. }
  87. }
  88. public class ThreadTestsThread : ThreadRunner
  89. {
  90. private long cpuCount;
  91. public ThreadTestsThread(long cpuCount) : base() {
  92. this.cpuCount = cpuCount;
  93. }
  94. public override void ThreadMain() {
  95. const long Timeout = 1000 * 10; // 10 seconds
  96. long threadCount = 0;
  97. PrintThread[] threads;
  98. threadCount = cpuCount * 2;
  99. //
  100. // Run forever, process will exit when the ApMain thread
  101. // is done with the test sequence
  102. //
  103. for (;;) {
  104. //Console.Write(".");
  105. threads = new PrintThread[threadCount];
  106. if (threads == null) {
  107. System.Console.WriteLine("Error allocating Thread[]");
  108. return;
  109. }
  110. for (int i = 0; i < threadCount; i++) {
  111. threads[i] = new PrintThread(i);
  112. if (threads[i] == null) {
  113. System.Console.WriteLine("Error creating thread");
  114. return;
  115. }
  116. }
  117. // Start them running
  118. for (int i = 0; i < threadCount; i++) {
  119. ((!)threads[i]).RunThread();
  120. }
  121. TimeSpan timeout = TimeSpan.FromMilliseconds(Timeout);
  122. for (int i = 0; i < threadCount; i++) {
  123. if (!((!)(((!)threads[i]).Thread)).Join(timeout)) {
  124. Console.WriteLine("Timeout waiting for thread exit");
  125. return;
  126. }
  127. //Console.Write("+");
  128. }
  129. }
  130. }
  131. }
  132. public class PulseTestsThread : ThreadRunner
  133. {
  134. private long cpuCount;
  135. private long passes;
  136. private int threadCount;
  137. private int maxThreadCount;
  138. private const int threadsPerCpu = 64;
  139. public PulseTestsThread(long cpuCount, long passes) : base() {
  140. this.cpuCount = cpuCount;
  141. this.passes = passes;
  142. maxThreadCount = threadsPerCpu * (int)cpuCount;
  143. // Limit max threads, otherwise we will overflow the kernel's thread table
  144. if (maxThreadCount > 512) {
  145. maxThreadCount = 512;
  146. }
  147. }
  148. public override void ThreadMain() {
  149. System.Console.WriteLine("Running PulseTests: Thread {0}\n", Thread.CurrentThread.GetThreadId());
  150. Console.Write("passes={0}", passes);
  151. Console.WriteLine(" cpuCount={0}", cpuCount);
  152. for (int pass = 0; pass < passes; pass++) {
  153. Console.WriteLine("pass={0}", pass);
  154. UnitTest.Clear();
  155. threadCount = 0;
  156. for (int i = 0; i < cpuCount; i++) {
  157. // 50 threads
  158. if (!CheckMaxThreads(50)) {
  159. UnitTest.Add("Many Threads PulseAll",
  160. new UnitTest.TestDelegate(PulseAllTest.ManyThreadsTest));
  161. }
  162. // 8 threads
  163. if (!CheckMaxThreads(8)) {
  164. UnitTest.Add("Few Threads PulseAll",
  165. new UnitTest.TestDelegate(PulseAllTest.FewThreadsTest));
  166. }
  167. // 17 threads
  168. if (!CheckMaxThreads(17)) {
  169. UnitTest.Add("Low-density Pulse",
  170. new UnitTest.TestDelegate(PulseTest.LowDensityTest));
  171. }
  172. // 32 threads
  173. if (!CheckMaxThreads(32)) {
  174. UnitTest.Add("Medium-density Pulse",
  175. new UnitTest.TestDelegate(PulseTest.MediumDensityTest));
  176. }
  177. // 128 threads
  178. if (!CheckMaxThreads(128)) {
  179. UnitTest.Add("High-density Pulse",
  180. new UnitTest.TestDelegate(PulseTest.HighDensityTest));
  181. }
  182. }
  183. Console.WriteLine("{0} PulseThreads", threadCount);
  184. // Wait for the sub-threads to run
  185. if (UnitTest.Run(true) != UnitTest.Result.Passed) {
  186. Console.WriteLine("PulseTest failed!\n");
  187. }
  188. }
  189. // This exits the thread
  190. return;
  191. }
  192. // We must keep total thread count at a reasonable level
  193. // otherwise we overflow the kernel thread table that is
  194. // hardcoded at 1024. We will set 512 max threads for now.
  195. private bool CheckMaxThreads(int count)
  196. {
  197. if ((count + threadCount) <= maxThreadCount) {
  198. threadCount += count;
  199. return false;
  200. }
  201. return true;
  202. }
  203. }
  204. // Generic class that creates the thread
  205. public class ThreadRunner
  206. {
  207. private Thread thread;
  208. public ThreadRunner() {
  209. }
  210. public Thread Thread {
  211. get {
  212. return thread;
  213. }
  214. }
  215. // Creates thread, returns with it running
  216. public Thread RunThread() {
  217. thread = new Thread(new ThreadStart(ThreadMain));
  218. thread.Start();
  219. return thread;
  220. }
  221. public virtual void ThreadMain() {
  222. // This exits the thread
  223. return;
  224. }
  225. }
  226. }