-
Notifications
You must be signed in to change notification settings - Fork 216
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
Remove LINQ usage from the generated code #4732
Comments
@kasperk81 I believe you've submitted pull requests across repositories and everything has been merged. |
this is tracking removal of LINQ from the generated code in this repo kiota/src/Kiota.Builder/Refiners/CSharpRefiner.cs Lines 173 to 174 in c48c7f5
|
Thanks for clarifying! |
This thread provides a lot of additional context to why we'd want to do this dotnet/runtime#102131 |
This comment was marked as outdated.
This comment was marked as outdated.
The usage of Linq is limited to a couple of ToList and ToArray calls.
I wonder whether replacing those by loops is actually going to reduce the binary size. |
removing linq has improved the binary size in other places. it's the way ilcompiler and ryujit compile the types in memory. the generic nature of linq is the very antipattern ilc and illink advise against. why keeping linq deemed necessary? it's not even maintained by the BCL team.. |
to be clear, I'm not arguing against the change. I'm trying to ensure we won't negatively impact size by making changes, whichever solution we land on. |
we have made several changes in other repos: depending on how "open" the generic T is, it will improve the codegen proportionally. if T was constrained, then we get the same codegen. either way it gives a clear message that there is no usage of linq in the generated code for accidental misuses in the future. |
Right, I had forgotten about the copy constructor. |
we can avoid two copies by iterating and short-circuiting like this: public T[] ToArrayWithoutLinq(IEnumerable<T> e)
{
if (e is ICollection<T> collection)
{
// Allocate an array with the exact size
T[] result = GC.AllocateUninitializedArray<T>(collection.Count);
collection.CopyTo(result, 0);
return result;
}
else
{
// First pass to count the elements
int count = 0;
foreach (var item in e) count++;
// Allocate array with the counted size
T[] result = GC.AllocateUninitializedArray<T>(count);
// Second pass to copy the elements
int index = 0;
foreach (var item in e) result[index++] = item;
return result;
}
} |
Thanks for the additional context. And no matter what we'll need to iterate twice so we can count the "collection" to allocate the array and avoid re-allocations. (I doubt we have any scenario where we return ICollection today). |
neither does LINQ. and it comes with additional baggage for open generics. |
Now that we have a clear roadmap, would you be open to create a pull request to make the changes we've identified? |
|
Right, but the places where we call to array are from an ienumerable. And those are generally a yield return under the covers. |
To make the generated code performant and amenable to AOT compilation and linker trimming, usage of LINQ should be removed. .NET JIT (which AOT also uses at its build-time backend) gives up while devirtualizing complex queries as it has to account for all possible types of generic from the implementation of LINQ APIs. Replacing LINQ queries with regular loops and conditions outperforms in terms of both time and space in most cases.
background microsoft/kiota-serialization-form-dotnet#142
The text was updated successfully, but these errors were encountered: