Skip to content

perf: Remove reflection from NetworkBehaviour code to improve performance. [MTT-1968] #2522

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

Merged
merged 5 commits into from
Apr 25, 2023

Conversation

ShadauxCat
Copy link
Collaborator

@ShadauxCat ShadauxCat commented Apr 20, 2023

Changelog

  • Changed: Improved performance of NetworkBehaviour initialization by replacing reflection when initializing NetworkVariables with compile-time code generation, which should help reduce hitching during additive scene loads.

Testing and Documentation

  • No tests have been added... but updated an existing integration test to ensure it covered another ILPP edge case.
  • No documentation changes or additions were necessary.

@ShadauxCat ShadauxCat requested a review from a team as a code owner April 20, 2023 21:50
@ShadauxCat ShadauxCat changed the title perf: Remove reflection from NetworkBehaviour code to improve performance. perf: Remove reflection from NetworkBehaviour code to improve performance. [MTT-1968] Apr 20, 2023
@@ -18,6 +18,7 @@ Additional documentation and release notes are available at [Multiplayer Documen
- Fixed some errors that could occur if a connection is lost and the loss is detected when attempting to write to the socket. (#2495)

## Changed
- Improved performance of NetworkBehaviour initialization, which should help reduce hitching during additive scene loads. (#2522)
Copy link
Contributor

Choose a reason for hiding this comment

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

Improved performance of NetworkBehaviour initialization...

perhaps adding "by bla bla, which should..." might be more informative, but just nit-picking on this.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done

m_NetworkVariableBase_TypeRef = moduleDefinition.ImportReference(networkVariableBaseTypeDef);
foreach (var methodDef in networkVariableBaseTypeDef.Methods)
{
Console.WriteLine($"=>Method: {methodDef.Name}");
Copy link
Contributor

Choose a reason for hiding this comment

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

probably a debugging leftover :P

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yep, removed, thanks for the catch.

}
if (field.FieldType.IsSubclassOf(m_NetworkVariableBase_TypeRef))
{
processor.Emit(OpCodes.Ldarg_0);
Copy link
Contributor

Choose a reason for hiding this comment

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

I usually find inline pseudo-C# code helpful understanding what was tried to be achieved with IL emits.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Nice... now I can understand what the OpCodes actually mean! 😸
(TILT)

initializeVariablesBaseReference = initializeVariablesBaseReference.MakeGeneric(baseTypeInstance.GenericArguments.ToArray());
}

processor.Emit(OpCodes.Nop);
Copy link
Contributor

Choose a reason for hiding this comment

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

^ same here

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Also done.

Comment on lines -594 to -609
var sortedFields = GetFieldInfoForType(GetType());
for (int i = 0; i < sortedFields.Length; i++)
{
var fieldType = sortedFields[i].FieldType;
if (fieldType.IsSubclassOf(typeof(NetworkVariableBase)))
{
var instance = (NetworkVariableBase)sortedFields[i].GetValue(this) ?? throw new Exception($"{GetType().FullName}.{sortedFields[i].Name} cannot be null. All {nameof(NetworkVariableBase)} instances must be initialized.");
instance.Initialize(this);

var instanceNameProperty = fieldType.GetProperty(nameof(NetworkVariableBase.Name));
var sanitizedVariableName = sortedFields[i].Name.Replace("<", string.Empty).Replace(">k__BackingField", string.Empty);
instanceNameProperty?.SetValue(instance, sanitizedVariableName);

NetworkVariableFields.Add(instance);
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

what this code was doing anyway? why did we try to access variable name?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Based on the tests that failed when I forgot to bring over the "k__BackingField" part of this, it seems that the network variable's name is used for tools/metrics. This is just setting a runtime property to match the variable's name in the source, so basically it's doing Foo.Name = "Foo".

- Added an extra error handler to catch an edge case I missed before
- Added a bit more info to the changelog
- Fixed testproject-tools-integration tests
Copy link
Collaborator

@NoelStephensUnity NoelStephensUnity left a comment

Choose a reason for hiding this comment

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

Looks good to me!
@ThusSpokeNomad ?

Copy link
Contributor

@0xFA11 0xFA11 left a comment

Choose a reason for hiding this comment

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

Added a few suggestions for inline comments (typo, clarity, style).
But other than that, 🚀

Co-authored-by: Fatih Mar <mfatihmar@gmail.com>
@0xFA11 0xFA11 enabled auto-merge (squash) April 25, 2023 20:09
@0xFA11 0xFA11 merged commit 8707582 into develop Apr 25, 2023
@0xFA11 0xFA11 deleted the perf/remove_reflection_in_networkbehaviour branch April 25, 2023 20:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants