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

Replace ArrayList in InputLanguageSource with fixed-size array, reduce allocations #9221

Merged

Conversation

h3xds1nz
Copy link
Contributor

@h3xds1nz h3xds1nz commented Jun 6, 2024

Description

Replaces ArrayList with a CultureInfo[] of 1 item downcasted to IEnumerable to improve performance of retrieval and decrease allocations caused by allocating an ArrayList and adding an item into it.

Method Mean [ns] Error [ns] StdDev [ns] Code Size [B] Gen0 Allocated
ArrayList 13.167 ns 0.2586 ns 0.3362 ns 488 B 0.0053 88 B
GenericList 8.222 ns 0.1907 ns 0.1690 ns 1,261 B 0.0038 64 B
PR__EDIT 4.229 ns 0.1225 ns 0.2864 ns 54 B 0.0019 32 B

Customer Impact

Improved performance, less allocations.

Regression

No.

Testing

Local build, CI.

Risk

As outlined in the discussion with @miloush, this is a change to a public type under the hood. If someone was relying on an implementation detail, that this was an ArrayList, it would break. Do note that is nowhere documented this is an ArrayList.

Documentation clearly states for InputLanguageList property (nobody should assume otherwise):
When implemented by a class, this property should return an object that implements the IEnumerable interface, and that supports enumerating a collection of CultureInfo objects, each representing a supported input language.

Microsoft Reviewers: Open in CodeFlow

@h3xds1nz h3xds1nz requested a review from a team as a code owner June 6, 2024 17:05
@dotnet-policy-service dotnet-policy-service bot added PR metadata: Label to tag PRs, to facilitate with triage Community Contribution A label for all community Contributions labels Jun 6, 2024
@h3xds1nz h3xds1nz changed the title [InputLanguageSource.cs] Replace ArrayList with pre-allocated generic List<CultureInfo> Replace ArrayList with pre-allocated generic List<CultureInfo> in InputLanguageSource Sep 1, 2024
@h3xds1nz h3xds1nz changed the title Replace ArrayList with pre-allocated generic List<CultureInfo> in InputLanguageSource Replace ArrayList in InputLanguageSource with pre-allocated generic List<CultureInfo> Sep 1, 2024
siagupta0202
siagupta0202 previously approved these changes Sep 11, 2024
@miloush
Copy link
Contributor

miloush commented Sep 11, 2024

I will just point out that this value is returned by public API via InputLanguageManager.AvailableInputLanguages. After this change, the type of the returned value will be changed, but only for the case where single input language installed. The list is also generated anew on every call and so "belongs" to the caller, who can be manipulating it. If you are playing nice and you want to clone the list first, well, the generic list, unlike ArrayList, does not implement ICloneable.

On the positive side, the ownership is not documented, the public contract is IEnumerable only and there does not seem to be a single project on GitHub using this API. So it's likely fine.

@h3xds1nz
Copy link
Contributor Author

h3xds1nz commented Sep 11, 2024

You're returning an interface for a reason, to interface with it. That is the contract that was given.

Relying on an implementation detail such as this is the same as using reflection on private types in a foreign assembly.

Note aside: Don't worry about the ArrayList in InputProcessorProfiles, its demise is coming.

@miloush
Copy link
Contributor

miloush commented Sep 11, 2024

Why List rather than an array then?

this is the same as using reflection on private types in a foreign assembly

Not quite as all the involved types are public and you were able to do this even in partial trust. In the sense of "relying on implementation detail", sure. But so is relying on the fact that the enumerable contains CultureInfos, yet I am pretty sure that would be slightly more concerning thing to change.

As I said I am happy with this one going ahead, I just wouldn't necessarily call it "None" risk.

Don't worry about the ArrayList in InputProcessorProfiles, its demise is coming.

Never had doubts about that. :)

@h3xds1nz
Copy link
Contributor Author

Why List rather than an array then?

Now that is a very good question that I do not have an answer to. @siagupta0202 Would it be too late to change it?

Not quite as all the involved types are public and you were able to do this even in partial trust. In the sense of "relying on implementation detail", sure. But so is relying on the fact that the enumerable contains CultureInfos, yet I am pretty sure that would be slightly more concerning thing to change.

When implemented by a class, this property should return an object that implements the IEnumerable interface, and that supports enumerating a collection of CultureInfo objects, each representing a supported input language.

We can refer to the wording, relying on CultureInfo is documented and so that the returned object that shall implement only IEnumerable.

As I said I am happy with this one going ahead, I just wouldn't necessarily call it "None" risk.

Fair point. Could have been outlined better from my side :)

Never had doubts about that. :)

Wouldn't believe you if you said you did, haha.

@miloush
Copy link
Contributor

miloush commented Sep 11, 2024

Ah good idea checking the interface documentation, I missed that. The one for AvailableInputLanguages could certainly use some tightening (since the relevance/existence of the interface is not clear).

@h3xds1nz
Copy link
Contributor Author

Yeah, agreed.

@siagupta0202
Copy link
Contributor

Now that is a very good question that I do not have an answer to. @siagupta0202 Would it be too late to change it?

@h3xds1nz it's not too late, you can still make the changes.

@h3xds1nz
Copy link
Contributor Author

@siagupta0202 Thanks, will push it shortly.

@h3xds1nz h3xds1nz force-pushed the replace-arraylist-with-generic-list branch from a9530ef to c80e4de Compare September 12, 2024 12:32
@h3xds1nz h3xds1nz requested a review from a team as a code owner September 12, 2024 12:32
@h3xds1nz h3xds1nz changed the title Replace ArrayList in InputLanguageSource with pre-allocated generic List<CultureInfo> Replace ArrayList in InputLanguageSource with fixed-size array, reduce allocations Sep 12, 2024
@harshit7962 harshit7962 merged commit 8b20afb into dotnet:main Oct 1, 2024
8 checks passed
@harshit7962
Copy link
Member

@h3xds1nz Thank you for your contribution.

@h3xds1nz
Copy link
Contributor Author

h3xds1nz commented Oct 1, 2024

@harshit7962 Thanks for including it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Community Contribution A label for all community Contributions PR metadata: Label to tag PRs, to facilitate with triage
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants