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

Non-recursive TypeName.FullName implementation #112242

Closed
wants to merge 3 commits into from

Conversation

adamsitnik
Copy link
Member

The simple recursive implementation turned into quite a complex iterative approach. I am open to any suggestions to make it better.

I've not touched the "Name" implementation yet, as I want to avoid a merge conflict with #111598 and get a confirmation about the direction I took

@adamsitnik adamsitnik added this to the 10.0.0 milestone Feb 6, 2025
@adamsitnik adamsitnik requested a review from jkotas February 6, 2025 18:25
@adamsitnik adamsitnik self-assigned this Feb 6, 2025
Copy link
Contributor

Tagging subscribers to this area: @dotnet/area-system-reflection-metadata
See info in area-owners.md if you want to be subscribed.

@jkotas
Copy link
Member

jkotas commented Feb 7, 2025

The problem we have talked about during review of this feature was non-linear amount of work and allocations performed by FullName.

I do not think that the recursive implementation is a problem. The recursion has the same approximate depth as the recursion that was performed during parsing of the type name, so the recursion here does not introduce a new problem. I agree that the non-recursive implementation makes the code complicated.

@danmoseley danmoseley requested a review from Copilot February 7, 2025 01:54
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/TypeName.cs:204

  • Ensure that the assembly name is not appended multiple times by adding a check before appending.
AppendInReverseOrder(ref builder, current.AssemblyName.FullName.AsSpan());

else if (_nestedNameLength > 0 && _fullName.Length > _nestedNameLength) // Declaring types

Span<char> characters = builder.RawChars.Slice(0, builder.Length);
characters.Reverse();
Copy link
Preview

Copilot AI Feb 7, 2025

Choose a reason for hiding this comment

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

Consider using a more efficient method to reverse the string if performance is a concern.

Copilot is powered by AI, so mistakes are possible. Review output carefully before use.

Positive Feedback
Negative Feedback

Provide additional feedback

Please help us improve GitHub Copilot by sharing more details about this comment.

Please select one or more of the options
#endif
// Stored fullName represents the full name of the nested type.
// Example: Namespace.Declaring+Nested
_fullName = _fullName.Substring(0, _nestedNameLength);
Copy link
Member

Choose a reason for hiding this comment

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

How about thread safety of this? Concurrent initialization with the same content should be safe, but this branch is modifying to different content.

Copy link
Member Author

Choose a reason for hiding this comment

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

TypeName is not thread safe. In worst case, multiple different threads are going to perform a string allocation.

Copy link
Contributor

Choose a reason for hiding this comment

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

TypeName is not thread safe.

Isn't it? It's immutable. There might be some extra allocations but it would work fine when accessed from multiple threads, wouldn't it?

Copy link
Member Author

Choose a reason for hiding this comment

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

You are right, it's fine to assume that something that is immutable is also thread-safe.

And again, in worst case, multiple threads would allocate the same string and duplicate the work, but each of them would end up computing the same text.

while (stack.Count > 0)
{
NameInfo currentInfo = stack[stack.Count - 1];
stack.RemoveAt(stack.Count - 1);
Copy link
Member

Choose a reason for hiding this comment

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

Decrease stack.Count? Otherwise it should be infinite loop.

Copy link
Member Author

Choose a reason for hiding this comment

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

RemoveAt takes care of decreasing the Count

Comment on lines +239 to +240
_fullName = characters.ToString();
builder.Dispose();
Copy link
Member

Choose a reason for hiding this comment

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

ToString already calls Dispose

Copy link
Member Author

Choose a reason for hiding this comment

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

But in this case I am not calling builder.ToString(), but builder.RawChars.ToString which does not call the Dispose

@adamsitnik
Copy link
Member Author

Closing in favor of #112350

@adamsitnik adamsitnik closed this Feb 10, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants