Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Improve pref of Array.IndexOf() for certain T. #24293

Merged
merged 1 commit into from
Apr 30, 2019

Conversation

dschinde
Copy link

Applies changes to Array.IndexOf() and Array.LastIndexOf() similar
to the changes made in #20855, so that types other than byte and
char can use use the fast vectorized path.

Also allows 32-bit and 64-bit types for which
RuntimeHelpers.IsBitwiseEquatable<T>() returns true to use the
faster implementation of IndexOf and LastIndexOf from
MemoryExtensions.

Applies changes to `Array.IndexOf()` and `Array.LastIndexOf()` similar
to the changes made in dotnet#20855, so that types other than `byte` and
`char` can use use the fast vectorized path.

Also allows 32-bit and 64-bit types for which
`RuntimeHelpers.IsBitwiseEquatable<T>()` returns `true` to use the
faster implementation of `IndexOf` and `LastIndexOf` from
`MemoryExtensions`.
Unsafe.As<T, long>(ref value),
count);
return (result >= 0 ? startIndex : 0) + result;
}
Copy link
Member

Choose a reason for hiding this comment

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

I wonder - is it possible to replace it all with return new Span<T>(array, startIndex, count).IndexOf(value); to re-use that MemoryExtensions code with IsBitwiseEquatable

Copy link
Author

Choose a reason for hiding this comment

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

MemoryExtensions.IndexOf<T>(Span<T>, T) requires that T implement IEquatable<T>, and while we know that all types for which IsBitwiseEquatable<T>() currently returns true satisfy that requirement, there is no way to tell that to the compiler.

@jkotas
Copy link
Member

jkotas commented Apr 29, 2019

Do you have any numbers that show how much this change improved the performance?

Copy link
Member

@jkotas jkotas left a comment

Choose a reason for hiding this comment

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

Thank you! The change looks good me once it is supported by numbers.

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.

Echoing Jan's comments: LGTM, but would like to see numbers.

@dschinde
Copy link
Author

I tested using the same logic as the Contains tests in dotnet/performance.

For example:

[Benchmark]
public int ArrayIndexOf()
{
    int result = 0;
    var values = _values;
    var found = _found;
    for (int i = 0; i < found.Length; i++)
        result ^= Array.IndexOf(values, found[i]);
    return result;
}
BenchmarkDotNet=v0.11.5, OS=Windows 10.0.17134.706 (1803/April2018Update/Redstone4)
Intel Core i7-8700K CPU 3.70GHz (Coffee Lake), 1 CPU, 12 logical and 6 physical cores
Frequency=3609369 Hz, Resolution=277.0567 ns, Timer=TSC
.NET Core SDK=3.0.100-preview5-011281
  [Host]     : .NET Core 3.0.0-preview5-27613-06 (CoreCLR 4.6.27613.71, CoreFX 4.700.19.21214), 64bit RyuJIT
  Job-JLWIJH : .NET Core ? (CoreCLR 4.6.27620.0, CoreFX 4.700.19.21911), 64bit RyuJIT
  Job-OBNZOS : .NET Core ? (CoreCLR 4.6.27620.0, CoreFX 4.700.19.21911), 64bit RyuJIT

IterationTime=250.0000 ms  MaxIterationCount=20  MinIterationCount=15  
WarmupCount=1  
Type Method Toolchain N Mean Error StdDev Median Min Max Ratio
IndexOfBenchmark<Int16> ArrayIndexOf Master 512 93.070 us 0.6910 us 0.6464 us 92.916 us 91.678 us 94.335 us 1.00
IndexOfBenchmark<Int16> ArrayIndexOf array-perf 512 9.775 us 0.0553 us 0.0490 us 9.782 us 9.697 us 9.883 us 0.10
IndexOfBenchmark<Int32> ArrayIndexOf Master 512 61.155 us 0.4038 us 0.3777 us 60.950 us 60.797 us 61.887 us 1.00
IndexOfBenchmark<Int32> ArrayIndexOf array-perf 512 26.765 us 0.1157 us 0.1082 us 26.820 us 26.617 us 26.933 us 0.44
IndexOfBenchmark<Int64> ArrayIndexOf Master 512 61.721 us 0.3472 us 0.3248 us 61.565 us 61.405 us 62.339 us 1.00
IndexOfBenchmark<Int64> ArrayIndexOf array-perf 512 26.847 us 0.1516 us 0.1344 us 26.796 us 26.703 us 27.054 us 0.43
LastIndexOfBenchmark<Int16> ArrayLastIndexOf Master 512 60.658 us 0.3088 us 0.2737 us 60.578 us 60.370 us 61.300 us 1.00
LastIndexOfBenchmark<Int16> ArrayLastIndexOf array-perf 512 11.132 us 0.0482 us 0.0428 us 11.121 us 11.077 us 11.212 us 0.18
LastIndexOfBenchmark<Int32> ArrayLastIndexOf Master 512 61.085 us 0.9160 us 0.7649 us 61.037 us 60.499 us 63.252 us 1.00
LastIndexOfBenchmark<Int32> ArrayLastIndexOf array-perf 512 34.243 us 0.2046 us 0.1914 us 34.272 us 33.949 us 34.550 us 0.56
LastIndexOfBenchmark<Int64> ArrayLastIndexOf Master 512 62.331 us 1.0727 us 1.0034 us 62.737 us 61.106 us 64.081 us 1.00
LastIndexOfBenchmark<Int64> ArrayLastIndexOf array-perf 512 33.069 us 0.2088 us 0.1953 us 33.100 us 32.788 us 33.386 us 0.53

@GrabYourPitchforks
Copy link
Member

The CI failures are unrelated. I wouldn't block this merge waiting for CI to go green.

@jkotas jkotas merged commit 2551753 into dotnet:master Apr 30, 2019
Dotnet-GitSync-Bot pushed a commit to Dotnet-GitSync-Bot/corefx that referenced this pull request Apr 30, 2019
)

Applies changes to `Array.IndexOf()` and `Array.LastIndexOf()` similar
to the changes made in #20855, so that types other than `byte` and
`char` can use use the fast vectorized path.

Also allows 32-bit and 64-bit types for which
`RuntimeHelpers.IsBitwiseEquatable<T>()` returns `true` to use the
faster implementation of `IndexOf` and `LastIndexOf` from
`MemoryExtensions`.

Signed-off-by: dotnet-bot <[email protected]>
stephentoub pushed a commit to dotnet/corefx that referenced this pull request Apr 30, 2019
)

Applies changes to `Array.IndexOf()` and `Array.LastIndexOf()` similar
to the changes made in #20855, so that types other than `byte` and
`char` can use use the fast vectorized path.

Also allows 32-bit and 64-bit types for which
`RuntimeHelpers.IsBitwiseEquatable<T>()` returns `true` to use the
faster implementation of `IndexOf` and `LastIndexOf` from
`MemoryExtensions`.

Signed-off-by: dotnet-bot <[email protected]>
@GrabYourPitchforks
Copy link
Member

Thanks @dschinde for your contribution! :)

Dotnet-GitSync-Bot pushed a commit to Dotnet-GitSync-Bot/corert that referenced this pull request Apr 30, 2019
)

Applies changes to `Array.IndexOf()` and `Array.LastIndexOf()` similar
to the changes made in #20855, so that types other than `byte` and
`char` can use use the fast vectorized path.

Also allows 32-bit and 64-bit types for which
`RuntimeHelpers.IsBitwiseEquatable<T>()` returns `true` to use the
faster implementation of `IndexOf` and `LastIndexOf` from
`MemoryExtensions`.

Signed-off-by: dotnet-bot <[email protected]>
Dotnet-GitSync-Bot pushed a commit to Dotnet-GitSync-Bot/mono that referenced this pull request Apr 30, 2019
)

Applies changes to `Array.IndexOf()` and `Array.LastIndexOf()` similar
to the changes made in mono#20855, so that types other than `byte` and
`char` can use use the fast vectorized path.

Also allows 32-bit and 64-bit types for which
`RuntimeHelpers.IsBitwiseEquatable<T>()` returns `true` to use the
faster implementation of `IndexOf` and `LastIndexOf` from
`MemoryExtensions`.

Signed-off-by: dotnet-bot <[email protected]>
jkotas pushed a commit to dotnet/corert that referenced this pull request Apr 30, 2019
)

Applies changes to `Array.IndexOf()` and `Array.LastIndexOf()` similar
to the changes made in #20855, so that types other than `byte` and
`char` can use use the fast vectorized path.

Also allows 32-bit and 64-bit types for which
`RuntimeHelpers.IsBitwiseEquatable<T>()` returns `true` to use the
faster implementation of `IndexOf` and `LastIndexOf` from
`MemoryExtensions`.

Signed-off-by: dotnet-bot <[email protected]>
marek-safar pushed a commit to mono/mono that referenced this pull request Apr 30, 2019
)

Applies changes to `Array.IndexOf()` and `Array.LastIndexOf()` similar
to the changes made in #20855, so that types other than `byte` and
`char` can use use the fast vectorized path.

Also allows 32-bit and 64-bit types for which
`RuntimeHelpers.IsBitwiseEquatable<T>()` returns `true` to use the
faster implementation of `IndexOf` and `LastIndexOf` from
`MemoryExtensions`.

Signed-off-by: dotnet-bot <[email protected]>
picenka21 pushed a commit to picenka21/runtime that referenced this pull request Feb 18, 2022
)

Applies changes to `Array.IndexOf()` and `Array.LastIndexOf()` similar
to the changes made in dotnet/coreclr#20855, so that types other than `byte` and
`char` can use use the fast vectorized path.

Also allows 32-bit and 64-bit types for which
`RuntimeHelpers.IsBitwiseEquatable<T>()` returns `true` to use the
faster implementation of `IndexOf` and `LastIndexOf` from
`MemoryExtensions`.

Commit migrated from dotnet/coreclr@2551753
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants