Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Three-way diffing Synchronizer #1707

Merged
merged 18 commits into from
Jul 2, 2024
Merged

Three-way diffing Synchronizer #1707

merged 18 commits into from
Jul 2, 2024

Conversation

halgari
Copy link
Collaborator

@halgari halgari commented Jul 1, 2024

This switches our synchronizer over to a much simpler, 3-way merge approach. For a in-depth overview of the changes here, see the included ADR 0014.

Due to the change in how this code operates, I had to delete most of the associated benchmarks. It won't be hard to add them back in when I do a performance pass on this code, but it's plenty fast for now. The various tests we have in place for managing and un-managing games all seem to work.

Added a test in SDV that exercises the code that moves files into the matching mods when ingesting.

@halgari halgari changed the title Sync redux Three-way diffing Synchronizer Jul 2, 2024
@halgari halgari requested a review from a team July 2, 2024 04:03
…d an error with the sync code exposed by the test
Comment on lines +6 to +37
/// <summary>
/// A grouping of actions that can be performed on a file. The SyncTree has a `Actions`
/// field and that field is used to put the items in the tree into these specific groups.
/// </summary>
public class SyncActionGroupings
{
private ConcurrentDictionary<Actions, ConcurrentBag<SyncTreeNode>> _groupings = new();

/// <summary>
/// Gets the group of nodes that have the specified action.
/// </summary>
/// <param name="action"></param>
public IReadOnlyCollection<SyncTreeNode> this[Actions action] => _groupings.GetOrAdd(action, static _ => []);

/// <summary>
/// Adds a node to the groupings based on the actions it has.
/// </summary>
/// <param name="node"></param>
public void Add(SyncTreeNode node)
{
foreach (var flag in Enum.GetValues<Actions>())
{
if (node.Actions.HasFlag(flag))
AddOne(flag, node);
}
}

private void AddOne(Actions flag, SyncTreeNode node)
{
_groupings.GetOrAdd(flag, static _ => []).Add(node);
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there's a ton of performance potential in this class. Without getting into the weeds, the biggest performance wins for the least amount of effort would be the following:

  1. Using normal Dictionary and List. I might be mistaken, but it doesn't look like we're using instances of this class in a multithreaded context.
  2. Using a static array instead of calling Enum.GetValues<Actions>. All the Enum methods actually use reflection, so this is extra slow.
  3. Prepopulating the groupings' dictionary. Following number 2, we can create a dictionary will all keys. This would also mean we're never writing to the dictionary, and can replace ConcurrentDictionary with a normal Dictionary.
  4. Similar to number 2, HasFlag can be replaced with HasFlagFast.

There's more to be done here, but those 4 points together have the best performance/effort ratio.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, I haven't yet added any parallel code around this but it's fairly trivial to do so. My goal was to try and get this code done so it would un-block people while I'm out on holiday. I plan on using the next few days to do performance improvements and other small feature additions separate PRs

@halgari halgari requested a review from erri120 July 2, 2024 12:13
@halgari halgari merged commit a4703d0 into main Jul 2, 2024
13 checks passed
@halgari halgari deleted the sync-redux branch July 2, 2024 12:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

2 participants