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

Simplify non-generic ArrayEnumerator #51351

Merged
merged 4 commits into from
Apr 21, 2021
Merged

Simplify non-generic ArrayEnumerator #51351

merged 4 commits into from
Apr 21, 2021

Conversation

jkotas
Copy link
Member

@jkotas jkotas commented Apr 15, 2021

No description provided.

@jkotas jkotas requested a review from marek-safar as a code owner April 15, 2021 23:31
@dotnet-issue-labeler
Copy link

I couldn't figure out the best area label to add to this PR. If you have write-permissions please help me learn by adding exactly one area label.

@@ -124,6 +124,77 @@ public static void Copy(Array sourceArray, long sourceIndex, Array destinationAr
Copy(sourceArray, isourceIndex, destinationArray, idestinationIndex, ilength);
}

#if !MONO
// The various Get values...
public object? GetValue(params int[] indices)
Copy link
Member Author

Choose a reason for hiding this comment

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

@CoffeeFlux I think this can be shared with Mono, but I am not sure about the best way to implement the GetFlattenedIndex method for Mono.

Copy link
Member Author

Choose a reason for hiding this comment

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

I gave it a shot. Let me know what you think

Copy link
Contributor

Choose a reason for hiding this comment

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

@lambdageek please have a look as well

Copy link
Member Author

Choose a reason for hiding this comment

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

@lambdageek Do you plan to take a look?

Copy link
Member

Choose a reason for hiding this comment

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

@jkotas sorry about that, LGTM

return new SZArrayEnumerator(this);
else
return new ArrayEnumerator(this, lowerBound, Length);
return new ArrayEnumerator(this);
Copy link
Member Author

Choose a reason for hiding this comment

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

This is the main point of the change - use the same implementation for both single and multi-dimensional arrays.

Copy link
Member

Choose a reason for hiding this comment

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

Nice

Copy link
Contributor

@CoffeeFlux CoffeeFlux left a comment

Choose a reason for hiding this comment

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

Mostly LGTM, thanks! This is a nice little cleanup.

@danmoseley
Copy link
Member

Does it need any perf validation?

@jkotas
Copy link
Member Author

jkotas commented Apr 17, 2021

The performance of these non-generic enumerators and accessors does not matter a whole lot. They are slow by construction.

Anyway, this change makes them faster. For example, foreach (var o in a) { } is 4x faster for Array a = new object[3,3] with this change.

This change moves more of the implementation from C/C++ into C#, so the perf results may vary for modalities where the managed code executes slower than native code, such as wasm interpretter. I assume that we do not care.

@marek-safar
Copy link
Contributor

managed code executes slower than native code, such as wasm interpretter. I assume that we do not care.

correct

@ghost
Copy link

ghost commented Apr 17, 2021

Tagging subscribers to this area: @tannergooding
See info in area-owners.md if you want to be subscribed.

Issue Details
Author: jkotas
Assignees: -
Labels:

area-System.Runtime

Milestone: -

@jkotas
Copy link
Member Author

jkotas commented Apr 20, 2021

@GrabYourPitchforks Could you please review the CoreCLR part of the change?

if (RuntimeHelpers.GetMethodTable(this)->IsMultiDimensionalArray)
{
ref int bounds = ref RuntimeHelpers.GetMultiDimensionalArrayBounds(this);
nint flattenedIndex = 0;
Copy link
Member

Choose a reason for hiding this comment

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

Nit: I think nuint makes a bit more sense than nint since we're talking about absolute offsets, and absolute offsets can never be negative. But if the convention is to use nint, so be 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.

Yeah, I need signed int for the iterator. So this really becomes a question of where you choose to place the casts.

I prefer signed int in situations like this, both in C/C++ and C#. There has been a lot of written about signed vs. unsigned. For example, https://google.github.io/styleguide/cppguide.html#Integer_Types that is aligned with my thinking on this.

src/coreclr/classlibnative/bcltype/arraynative.cpp Outdated Show resolved Hide resolved
@@ -139,11 +38,12 @@ public bool MoveNext()
{
get
{
if (_index < 0)
nint index = _index;
if (index < 0)
Copy link
Member

Choose a reason for hiding this comment

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

Does it make sense to reorder these with success first (predicted taken) and failures later?

if ((nuint)index < (nuint)_array.LongLength)) { return _array.InternalGetValue(index); }
else if (not_yet_started) { /* ... */ }
else { /* ... */ }

Copy link
Member Author

Choose a reason for hiding this comment

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

I have rearranged it so that the flow looks like the flow of the generic enumerator in this file.

I have not done the manual predicten taken part. That's a problem for the JIT to deal with.

Copy link
Member

@GrabYourPitchforks GrabYourPitchforks left a comment

Choose a reason for hiding this comment

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

coreclr side LGTM! My approval doesn't cover the mono side.

Copy link
Member

@lambdageek lambdageek left a comment

Choose a reason for hiding this comment

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

Mono LGTM, too

@jkotas jkotas merged commit 8c3180d into dotnet:main Apr 21, 2021
@jkotas jkotas deleted the array branch April 21, 2021 03:57
@karelz karelz added this to the 6.0.0 milestone May 20, 2021
@ghost ghost locked as resolved and limited conversation to collaborators Jun 19, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants