Skip to content

Commit 5a96218

Browse files
authored
[Bundle] Parallel bundle perf improvements (#3727)
* Switch from Task.WaitAll to Task.WhenAll * Removing calls to GC
1 parent e34b3f6 commit 5a96218

File tree

3 files changed

+4
-38
lines changed

3 files changed

+4
-38
lines changed

src/Microsoft.Health.Fhir.Core/Features/Persistence/Orchestration/BundleOrchestratorOperation.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@ private async Task<IDictionary<DataStoreOperationIdentifier, DataStoreOperationO
316316
// The database will be responsible for handling it internally.
317317
MergeOptions mergeOptions = new MergeOptions(enlistTransaction: false);
318318

319-
// 2 - Merge all resources in the data base.
319+
// 2 - Merge all resources in the database.
320320
IDictionary<DataStoreOperationIdentifier, DataStoreOperationOutcome> response = await _dataStore.MergeAsync(_resources.Values.ToList(), mergeOptions, cancellationToken);
321321

322322
SetStatusSafe(BundleOrchestratorOperationStatus.Completed);

src/Microsoft.Health.Fhir.Shared.Api/Features/Resources/Bundle/BundleHandler.cs

-26
Original file line numberDiff line numberDiff line change
@@ -589,15 +589,8 @@ private static void AddHeaderIfNeeded(string headerKey, string headerValue, Http
589589

590590
private async Task<EntryComponent> ExecuteRequestsWithSingleHttpVerbInSequenceAsync(Hl7.Fhir.Model.Bundle responseBundle, HTTPVerb httpVerb, EntryComponent throttledEntryComponent, BundleHandlerStatistics statistics, CancellationToken cancellationToken)
591591
{
592-
const int GCCollectTrigger = 150;
593-
594592
foreach (ResourceExecutionContext resourceContext in _requests[httpVerb])
595593
{
596-
if (resourceContext.Index % GCCollectTrigger == 0 && resourceContext.Index > 0)
597-
{
598-
RunGarbageCollection();
599-
}
600-
601594
EntryComponent entryComponent;
602595

603596
Stopwatch watch = Stopwatch.StartNew();
@@ -873,25 +866,6 @@ private void PopulateReferenceIdDictionary(IEnumerable<EntryComponent> bundleEnt
873866
}
874867
}
875868

876-
private void RunGarbageCollection()
877-
{
878-
try
879-
{
880-
_logger.LogInformation("{Origin} - MemoryWatch - Memory used before collection: {MemoryInUse:N0}", nameof(BundleHandler), GC.GetTotalMemory(forceFullCollection: false));
881-
882-
// Collecting memory up to Generation 2 using default collection mode.
883-
// No blocking, allowing a collection to be performed as soon as possible, if another collection is not in progress.
884-
// SOH compacting is set to true.
885-
GC.Collect(GC.MaxGeneration, GCCollectionMode.Default, blocking: false, compacting: true);
886-
887-
_logger.LogInformation("{Origin} - MemoryWatch - Memory used after full collection: {MemoryInUse:N0}", nameof(BundleHandler), GC.GetTotalMemory(forceFullCollection: false));
888-
}
889-
catch (Exception ex)
890-
{
891-
_logger.LogInformation(ex, "{Origin} - MemoryWatch - Error running garbage collection.", nameof(BundleHandler));
892-
}
893-
}
894-
895869
private static OperationOutcome CreateOperationOutcome(OperationOutcome.IssueSeverity issueSeverity, OperationOutcome.IssueType issueType, string diagnostics)
896870
{
897871
return new OperationOutcome

src/Microsoft.Health.Fhir.Shared.Api/Features/Resources/Bundle/BundleHandlerParallelOperations.cs

+3-11
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,6 @@ private async Task<EntryComponent> ExecuteRequestsInParallelAsync(
7272
return await Task.FromResult(throttledEntryComponent);
7373
}
7474

75-
const int GCCollectTrigger = 150;
76-
7775
using (CancellationTokenSource requestCancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken))
7876
{
7977
IAuditEventTypeMapping auditEventTypeMapping = _auditEventTypeMapping;
@@ -84,11 +82,6 @@ private async Task<EntryComponent> ExecuteRequestsInParallelAsync(
8482
// Parallel Resource Handling Function.
8583
Func<ResourceExecutionContext, CancellationToken, Task> handleRequestFunction = async (ResourceExecutionContext resourceExecutionContext, CancellationToken ct) =>
8684
{
87-
if (resourceExecutionContext.Index > 0 && resourceExecutionContext.Index % GCCollectTrigger == 0)
88-
{
89-
RunGarbageCollection();
90-
}
91-
9285
_logger.LogInformation("BundleHandler - Running '{HttpVerb}' Request #{RequestNumber} out of {TotalNumberOfRequests}.", resourceExecutionContext.HttpVerb, resourceExecutionContext.Index, bundleOperation.OriginalExpectedNumberOfResources);
9386

9487
// Creating new instances per record in the bundle, and making their access thread-safe.
@@ -147,12 +140,11 @@ private async Task<EntryComponent> ExecuteRequestsInParallelAsync(
147140

148141
try
149142
{
150-
// The following Task.WaitAll should wait for all requests to finish.
143+
// The following Task.WhenAll should wait for all requests to finish.
151144

152-
// Parallel requests are not supossed to raise exceptions, unless they are FhirTransactionFailedExceptions.
145+
// Parallel requests are not supposed to raise exceptions, unless they are FhirTransactionFailedExceptions.
153146
// FhirTransactionFailedExceptions are a special case to invalidate an entire bundle.
154-
155-
Task.WaitAll(requestsPerResource.ToArray(), cancellationToken);
147+
await Task.WhenAll(requestsPerResource);
156148
}
157149
catch (AggregateException age)
158150
{

0 commit comments

Comments
 (0)