I'm writing a rather convoluted unit test that uses Parallel.ForEach
on a list of one million int
s.
Using JetBrains DotTrace, I noticed that a lot of garbage collection is going on in the code under test, it's taking up 10% of the total test running time and about 14% of the time spent in that method.
Here's a screenshot of the profiler:
The culprit, I guess, is a local variable that captures the current time. Here is the code:
public PatientQueryMessage CreateQueryMessage(string patientNumber)
{
var nowOffset = DateTimeOffset.Now; // GC nightmare?
return new PatientQueryMessage
{
MessageHeader = new MessageHeader
{
DateTimeMessage = new TimeStamp(nowOffset),
MessageControlId = $"{patientNumber}{nowOffset.Ticks.ToString().Substring(7, 5)}"
// More properties set, but filtered out for brevity
},
QueryDefinition = new QueryDefinition
{
QueryDateTime = new TimeStamp(nowOffset),
QueryId = $"{patientNumber}{nowOffset:MMddHHmmssf}"
// More properties set, but filtered out for brevity
}
};
}
Now, here are the important bits of the test code:
Parallel.ForEach(myNumberArray,
new ParallelOptions { MaxDegreeOfParallelism = maxThreads },
() => /* TLocal Init */,
(number, loopState, localResult) =>
{
var queryMessage = _queryMessageHelper.CreateQueryMessage(patientNumber);
// Brevity...
return localResult;
},
resultList =>
{
// Brevity...
}
);
In the loop body, is there any way I can temporarily shut down or otherwise restrain the Garbage Collector, so that it will only cleanup once everything has settled down?
Note that I care a lot more about the time it takes for the test to run than how much memory it consumes.