Skip to content

Commit

Permalink
perf: process experiments in parallel (#522)
Browse files Browse the repository at this point in the history
  • Loading branch information
melotic authored Apr 24, 2023
1 parent e7ecddd commit 96020de
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -98,16 +98,14 @@ public async Task FinishAsync()

var diff = new ExperimentDiff(controlComponents, experimentComponents);

foreach (var processor in this.experimentProcessors)
try
{
try
{
await processor.ProcessExperimentAsync(config, diff);
}
catch (Exception e)
{
this.logger.LogWarning(e, "Error processing experiment {Experiment}", config.Name);
}
var tasks = this.experimentProcessors.Select(x => x.ProcessExperimentAsync(config, diff));
await Task.WhenAll(tasks);
}
catch (Exception e)
{
this.logger.LogError(e, "Error processing experiment {Experiment}", config.Name);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
namespace Microsoft.ComponentDetection.Orchestrator.Experiments.Models;

using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;

/// <summary>
Expand All @@ -20,12 +21,12 @@ public ExperimentDiff(
var oldComponentDictionary = controlGroupComponents.ToDictionary(x => x.Id);
var newComponentDictionary = experimentGroupComponents.ToDictionary(x => x.Id);

this.AddedIds = newComponentDictionary.Keys.Except(oldComponentDictionary.Keys).ToList();
this.RemovedIds = oldComponentDictionary.Keys.Except(newComponentDictionary.Keys).ToList();
this.AddedIds = newComponentDictionary.Keys.Except(oldComponentDictionary.Keys).ToImmutableList();
this.RemovedIds = oldComponentDictionary.Keys.Except(newComponentDictionary.Keys).ToImmutableList();

this.DevelopmentDependencyChanges = new List<DevelopmentDependencyChange>();
this.AddedRootIds = new Dictionary<string, HashSet<string>>();
this.RemovedRootIds = new Dictionary<string, HashSet<string>>();
var developmentDependencyChanges = new List<DevelopmentDependencyChange>();
var addedRootIds = new Dictionary<string, IReadOnlySet<string>>();
var removedRootIds = new Dictionary<string, IReadOnlySet<string>>();

// Need performance benchmark to see if this is worth parallelization
foreach (var id in newComponentDictionary.Keys.Intersect(oldComponentDictionary.Keys))
Expand All @@ -35,53 +36,57 @@ public ExperimentDiff(

if (oldComponent.DevelopmentDependency != newComponent.DevelopmentDependency)
{
this.DevelopmentDependencyChanges.Add(new DevelopmentDependencyChange(
developmentDependencyChanges.Add(new DevelopmentDependencyChange(
id,
oldComponent.DevelopmentDependency,
newComponent.DevelopmentDependency));
}

var addedRootIds = newComponent.RootIds.Except(oldComponent.RootIds).ToHashSet();
var removedRootIds = oldComponent.RootIds.Except(newComponent.RootIds).ToHashSet();
var newRoots = newComponent.RootIds.Except(oldComponent.RootIds).ToImmutableHashSet();
var removedRoots = oldComponent.RootIds.Except(newComponent.RootIds).ToImmutableHashSet();

if (addedRootIds.Count > 0)
if (newRoots.Count > 0)
{
this.AddedRootIds[id] = addedRootIds;
addedRootIds[id] = newRoots;
}

if (removedRootIds.Count > 0)
if (removedRoots.Count > 0)
{
this.RemovedRootIds[id] = removedRootIds;
removedRootIds[id] = removedRoots;
}
}

this.DevelopmentDependencyChanges = developmentDependencyChanges.AsReadOnly();
this.AddedRootIds = addedRootIds.ToImmutableDictionary();
this.RemovedRootIds = removedRootIds.ToImmutableDictionary();
}

/// <summary>
/// Gets a list of component IDs that were present in the experimental group but not the control group.
/// </summary>
public List<string> AddedIds { get; }
public IReadOnlyCollection<string> AddedIds { get; }

/// <summary>
/// Gets a list of component IDs that were present in the control group but not the experimental group.
/// </summary>
public List<string> RemovedIds { get; }
public IReadOnlyCollection<string> RemovedIds { get; }

/// <summary>
/// Gets a list of changes to the development dependency status of components.
/// </summary>
public List<DevelopmentDependencyChange> DevelopmentDependencyChanges { get; }
public IReadOnlyCollection<DevelopmentDependencyChange> DevelopmentDependencyChanges { get; }

/// <summary>
/// Gets a dictionary of component IDs to the set of root IDs that were added to the component. The component ID
/// is the key.
/// </summary>
public Dictionary<string, HashSet<string>> AddedRootIds { get; }
public IReadOnlyDictionary<string, IReadOnlySet<string>> AddedRootIds { get; }

/// <summary>
/// Gets a dictionary of component IDs to the set of root IDs that were removed from the component. The component
/// ID is the key.
/// </summary>
public Dictionary<string, HashSet<string>> RemovedRootIds { get; }
public IReadOnlyDictionary<string, IReadOnlySet<string>> RemovedRootIds { get; }

/// <summary>
/// Stores information about a change to the development dependency status of a component.
Expand Down

0 comments on commit 96020de

Please sign in to comment.