The stackdump tool mentioned above creates a nice stacktrace for each managed thread executing in the chosen process. I wanted to add some information giving me a hint of which thread is causing the problem in case of a CPU load problem.
Adding this and getting reliable results was a little trickier than I imagined. As a result of this a need to generate a test load arised. This lead me, once again, into dealing with the not so perfect timing functions of .NET. The best I could come up with was to use Thread.Sleep() combined with a self adjusting for loop that produced the load. I also found the best way available method for measuring time was the Stopwatch class.
The code below produces a good enough result for producing the desired load in one thread. You can also fire it up in multiple threads if needed.
private static void ThreadLoop(int percentLoad)
{
int loopMax = 1000;
long ixStable = 0;
var stopwatch = new Stopwatch();
stopwatch.Start();
var workPeriod = percentLoad * IntervalTargetTicks / 100;
var idlePeriod = IntervalTargetTicks - workPeriod;
while (!ThreadsAborted)
{
var t1 = stopwatch.Elapsed.Ticks;
for (int i = 0; i < loopMax; i++)
{
count++;
}
var t2 = stopwatch.Elapsed.Ticks;
var tLoop = t2 - t1;
// Do the sleep
Thread.Sleep((int)(idlePeriod / TimeSpan.TicksPerMillisecond));
var tMeasuredSleep = stopwatch.Elapsed.Ticks - t2;
if (tLoop < workPeriod - workPeriod / 4) loopMax += loopMax / 4;
else if (tLoop > workPeriod + workPeriod / 4) loopMax -= loopMax / 4;
else
{
ixStable++;
}
if (ixStable == 50)
{
Console.Out.WriteLine(
"OS Thread ID {0}({1}%): Stable with expected sleep {2} ms, loop {3} ms, actual sleep {4} ms",
AppDomain.GetCurrentThreadId(),
percentLoad,
(float)idlePeriod / TimeSpan.TicksPerMillisecond,
(float)tLoop / TimeSpan.TicksPerMillisecond,
(float)tMeasuredSleep / TimeSpan.TicksPerMillisecond);
}
}
}