Skip to content

Audit MemoryExtensions.IndexOf variants - #75754

Merged
adamsitnik merged 3 commits into
dotnet:mainfrom
Rob-Hague:indexofaudit
Oct 26, 2022
Merged

Audit MemoryExtensions.IndexOf variants#75754
adamsitnik merged 3 commits into
dotnet:mainfrom
Rob-Hague:indexofaudit

Conversation

@Rob-Hague

@Rob-HagueRob-Hague commented Sep 16, 2022

Copy link
Copy Markdown
Contributor

Hi @adamsitnik, after your #73768 I am submitting a few changes which I noticed and presumed were not intentionally left out:

  1. Add the SpanHelpers.Char specialisation to LastIndexOf(Span, ROS) to match LastIndexOf(ROS, ROS). I did not forward the Span version to ROS version to be consistent with IndexOf(Span, ROS) and IndexOf(ROS, ROS), being wary of related discussion in Vectorize {Last}IndexOf{Any} and {Last}IndexOfAnyExcept without code duplication #73768 (comment)
  2. I did forward the LastIndexOfAny(Span, ROS) to LastIndexOfAny(ROS, ROS) to be consistent with IndexOfAny and considering the next changes:
  3. Add more byte cases to LastIndexOfAny and IndexOfAny to be consistent with the short path

Things I noticed but did not change, deciding they were intentional:

  1. Missing int- and long-size paths on a few variants. I saw a couple removed in that PR
  2. Varying use of IsBitwiseEquatable vs CanVectorizeAndBenefit. I saw some tweaks in the last commit of that PR
  3. SpanHelpers.IndexOfAnyValueType has up to 5-value versions but LastIndexOfAnyValueType has only up to 4-value

Sadly I am having a few troubles getting some benchmarks running. I will submit this as a draft until then, if you see anything I am doing obviously wrong I would appreciate the pointer (I am a rookie with the runtime repo).

edit: I was using the wrong corerun path. I changed
dotnet run -c Release -f net8.0 -- --coreRun C:\src\artifacts\bin\coreclr\windows.x64.Release\corerun.exe C:\src\runtime\artifacts\bin\coreclr\windows.x64.Release\corerun.exe

to

dotnet run -c Release -- --coreRun C:\src\artifacts\bin\testhost\net7.0-windows-Release-x64\shared\Microsoft.NETCore.App\8.0.0\corerun.exe C:\src\runtime\artifacts\bin\testhost\net7.0-windows-Release-x64\shared\Microsoft.NETCore.App\8.0.0\corerun.exe

@ghostghost added community-contribution Indicates that the PR has been added by a community member area-System.Memory labels Sep 16, 2022
@dnfadmin

dnfadmin commented Sep 16, 2022

Copy link
Copy Markdown

CLA assistant check
All CLA requirements met.

@ghost

Copy link
Copy Markdown

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

Issue Details

Hi @adamsitnik, after your #73768 I am submitting a few changes which I noticed and presumed were not intentionally left out:

  1. Add the SpanHelpers.Char specialisation to LastIndexOf(Span, ROS) to match LastIndexOf(ROS, ROS). I did not forward the Span version to ROS version to be consistent with IndexOf(Span, ROS) and IndexOf(ROS, ROS), being wary of related discussion in Vectorize {Last}IndexOf{Any} and {Last}IndexOfAnyExcept without code duplication #73768 (comment)
  2. I did forward the LastIndexOfAny(Span, ROS) to LastIndexOfAny(ROS, ROS) to be consistent with IndexOfAny and considering the next changes:
  3. Add more byte cases to LastIndexOfAny and IndexOfAny to be consistent with the short path

Things I noticed but did not change, deciding they were intentional:

  1. Missing int- and long-size paths on a few variants. I saw a couple removed in that PR
  2. Varying use of IsBitwiseEquatable vs CanVectorizeAndBenefit. I saw some tweaks in the last commit of that PR
  3. SpanHelpers.IndexOfAnyValueType has up to 5-value versions but LastIndexOfAnyValueType has only up to 4-value

Sadly I am having a few troubles getting some benchmarks running. I will submit this as a draft until then, if you see anything I am doing obviously wrong I would appreciate the pointer (I am a rookie with the runtime repo).

I built main branch and copied the artifacts folder out to C:\src\artifacts\ then switched to my branch and built that (to C:\src\runtime\artifacts\). I am running from within my benchmark project dotnet build then
dotnet run -c Release -f net8.0 -- --coreRun C:\src\artifacts\bin\coreclr\windows.x64.Release\corerun.exe C:\src\runtime\artifacts\bin\coreclr\windows.x64.Release\corerun.exe
but I am getting output like below.

// **************************
// Benchmark: PrValidation.LastIndexOf_char_Span: Job-NLFAIL(Toolchain=\artifacts\bin\coreclr\windows.x64.Release\corerun.exe) [SearchSpaceCount=1024, SearchSpaceValue=1, ValueSpaceCount=1]
// *** Execute ***
// Launch: 1 / 1
// Execute: C:\src\artifacts\bin\coreclr\1a9e0e35-fd39-459c-800a-15f99cad96fc\corerun.exe 50419f21-5ca4-43db-985b-56f1f7210afd.dll --benchmarkName "System.Memory.PrValidation.LastIndexOf_char_Span(SearchSpaceCount: 1024, SearchSpaceValue: 1, ValueSpaceCount: 1)" --job Toolchain=\artifacts\bin\coreclr\windows.x64.Release\corerun.exe --benchmarkId 0 in C:\src\bench\bin\Release\net8.0\win-x64\50419f21-5ca4-43db-985b-56f1f7210afd\bin\Release\net8.0\publish
ExitCode != 0 and no results reported
No Workload Results were obtained from the run.
// Benchmark Process 19124 has exited with code -532462766.
dotnet --info

.NET SDK:
Version: 8.0.100-alpha.1.22465.14
Commit: c09cc8aada
Runtime Environment:
OS Name: Windows
OS Version: 10.0.22000
OS Platform: Windows
RID: win10-x64
Base Path: C:\Program Files\dotnet\sdk\8.0.100-alpha.1.22465.14\
Host:
Version: 8.0.0-alpha.1.22462.15
Architecture: x64
Commit: c804303ace
.NET SDKs installed:
6.0.400 [C:\Program Files\dotnet\sdk]
8.0.100-alpha.1.22465.14 [C:\Program Files\dotnet\sdk]
.NET runtimes installed:
Microsoft.AspNetCore.App 6.0.8 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 8.0.0-alpha.1.22463.1 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 6.0.8 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 8.0.0-alpha.1.22462.15 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 6.0.8 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 8.0.0-alpha.1.22457.11 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Other architectures found:
x86 [C:\Program Files (x86)\dotnet]
Environment variables:
Not set
global.json file:
Not found
Learn more:
https://aka.ms/dotnet/info
Download .NET:
https://aka.ms/dotnet/download

benchmark src

<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.13.2" />
</ItemGroup>
</Project>
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
using System.Runtime.CompilerServices;
using System.Linq;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Jobs;
namespace System.Memory
{
public class PrValidation
{
//[Params(4, 64, 1024)]
[Params(1024)]
public int SearchSpaceCount;
//[Params(0, 1)]
[Params(1)]
public int SearchSpaceValue;
//[Params(0, 1, 2, 3, 4, 5)]
[Params(1)]
public int ValueSpaceCount;
private byte[] _searchSpaceBytes, _valueSpaceBytes;
private char[] _searchSpaceChars, _valueSpaceChars;
[GlobalSetup]
public void Setup()
{
_searchSpaceBytes = Enumerable.Repeat((byte)SearchSpaceValue, SearchSpaceCount).ToArray();
_searchSpaceChars = Enumerable.Repeat((char)SearchSpaceValue, SearchSpaceCount).ToArray();
_valueSpaceBytes = Enumerable.Range(1, ValueSpaceCount).Select(Convert.ToByte).ToArray();
_valueSpaceChars = Enumerable.Range(1, ValueSpaceCount).Select(Convert.ToChar).ToArray();
}
[Benchmark] public void LastIndexOf_char_Span() => new Span<char>(_searchSpaceChars).LastIndexOf(_valueSpaceChars);
// [Benchmark] public void IndexOfAny_byte_Span() => new Span<byte>(_searchSpaceBytes).IndexOfAny(_valueSpaceBytes);
// [Benchmark] public void IndexOfAny_byte_ROS() => new ReadOnlySpan<byte>(_searchSpaceBytes).IndexOfAny(_valueSpaceBytes);
// [Benchmark] public void LastIndexOfAny_byte_Span() => new Span<byte>(_searchSpaceBytes).LastIndexOfAny(_valueSpaceBytes);
// [Benchmark] public void LastIndexOfAny_byte_ROS() => new ReadOnlySpan<byte>(_searchSpaceBytes).LastIndexOfAny(_valueSpaceBytes);
}
public class Program
{
public static void Main(string[] args)
{
BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args);
}
}
}

Author:rob-hague
Assignees:-
Labels:

area-System.Memory, community-contribution

Milestone:-

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

This was calling the same function as the fallback

@Rob-Hague

Rob-Hague commented Sep 17, 2022

Copy link
Copy Markdown
ContributorAuthor

Benchmarks summary:

Regressions in IndexOfAny_byte_ROS and LastIndexOfAny_byte_ROS for 2-value
Regressions in LastIndexOfAny_byte_Span and LastIndexOfAny_char_Span for 5-value

I guess the former is related to codegen.
I guess LastIndexOfAny_byte_Span 5-value suffers from extra indirection to call the same method (there is no vectorized 5-value LastIndexOfAny).
My guess for LastIndexOfAny_char_Span 5-value is that this comes from benchmarking an unrepresentative search-space (and the probabilistic map suffers heavily from this)

I will try a more representative search space soon. In the meantime if you have any thoughts on what changes you would take (if any) please let me know. Thanks

Details
BenchmarkDotNet=v0.13.2, OS=Windows 11 (10.0.22000.978/21H2)
AMD Ryzen 7 5700U with Radeon Graphics, 1 CPU, 16 logical and 8 physical cores
.NET SDK=8.0.100-alpha.1.22465.14
[Host] : .NET 8.0.0 (8.0.22.46215), X64 RyuJIT AVX2
main : .NET 8.0.0 (42.42.42.42424), X64 RyuJIT AVX2
PR : .NET 8.0.0 (42.42.42.42424), X64 RyuJIT AVX2
MethodJobSearchSpaceCountValueSpaceCountMeanErrorStdDevMedianRatioRatioSD
IndexOfAny_byte_ROSmain819.830 ns0.2249 ns0.6156 ns10.041 ns1.000.00
IndexOfAny_byte_ROSPR814.971 ns0.1001 ns0.0937 ns4.979 ns0.550.04
IndexOfAny_byte_ROSmain826.129 ns0.1493 ns0.2576 ns5.950 ns1.000.00
IndexOfAny_byte_ROSPR828.934 ns0.2029 ns0.3957 ns8.968 ns1.460.09
IndexOfAny_byte_ROSmain839.384 ns0.2156 ns0.4154 ns9.364 ns1.000.00
IndexOfAny_byte_ROSPR839.654 ns0.2196 ns0.5387 ns9.661 ns1.030.08
IndexOfAny_byte_ROSmain8418.289 ns0.3919 ns0.7067 ns18.407 ns1.000.00
IndexOfAny_byte_ROSPR8411.070 ns0.2500 ns0.5107 ns11.093 ns0.610.04
IndexOfAny_byte_ROSmain8521.680 ns0.4553 ns0.5592 ns21.706 ns1.000.00
IndexOfAny_byte_ROSPR8510.146 ns0.2242 ns0.2399 ns10.126 ns0.470.02
IndexOfAny_byte_ROSmain64140.300 ns0.2855 ns0.2670 ns40.281 ns1.000.00
IndexOfAny_byte_ROSPR6414.416 ns0.1032 ns0.0966 ns4.435 ns0.110.00
IndexOfAny_byte_ROSmain6424.104 ns0.1106 ns0.1786 ns4.115 ns1.000.00
IndexOfAny_byte_ROSPR6425.404 ns0.1132 ns0.1059 ns5.400 ns1.320.07
IndexOfAny_byte_ROSmain6435.657 ns0.1084 ns0.1014 ns5.677 ns1.000.00
IndexOfAny_byte_ROSPR6435.975 ns0.1438 ns0.2196 ns6.006 ns1.060.04
IndexOfAny_byte_ROSmain64498.455 ns1.2650 ns1.1833 ns98.209 ns1.000.00
IndexOfAny_byte_ROSPR6447.705 ns0.1821 ns0.4364 ns7.683 ns0.080.00
IndexOfAny_byte_ROSmain645111.305 ns0.5146 ns0.4814 ns111.450 ns1.000.00
IndexOfAny_byte_ROSPR6458.245 ns0.1912 ns0.3448 ns8.240 ns0.070.00
IndexOfAny_byte_ROSmain10241550.750 ns0.4103 ns0.3427 ns550.611 ns1.000.00
IndexOfAny_byte_ROSPR1024116.185 ns0.1722 ns0.1611 ns16.210 ns0.030.00
IndexOfAny_byte_ROSmain1024218.040 ns0.3859 ns0.6657 ns17.858 ns1.000.00
IndexOfAny_byte_ROSPR1024220.046 ns0.4286 ns0.4936 ns20.117 ns1.110.05
IndexOfAny_byte_ROSmain1024322.593 ns0.3136 ns0.2934 ns22.444 ns1.000.00
IndexOfAny_byte_ROSPR1024322.648 ns0.4287 ns0.4011 ns22.742 ns1.000.03
IndexOfAny_byte_ROSmain102441,378.781 ns5.7639 ns5.3915 ns1,379.800 ns1.000.00
IndexOfAny_byte_ROSPR1024430.109 ns0.6085 ns0.5692 ns30.250 ns0.020.00
IndexOfAny_byte_ROSmain102451,648.225 ns3.7257 ns3.1112 ns1,648.891 ns1.000.00
IndexOfAny_byte_ROSPR1024530.211 ns0.4717 ns0.4412 ns30.297 ns0.020.00
LastIndexOf_char_Spanmain814.632 ns0.0077 ns0.0072 ns4.630 ns1.000.00
LastIndexOf_char_SpanPR814.694 ns0.1110 ns0.1695 ns4.716 ns1.010.05
LastIndexOf_char_Spanmain826.081 ns0.0035 ns0.0029 ns6.080 ns1.000.00
LastIndexOf_char_SpanPR826.635 ns0.0105 ns0.0088 ns6.637 ns1.090.00
LastIndexOf_char_Spanmain835.761 ns0.0049 ns0.0046 ns5.763 ns1.000.00
LastIndexOf_char_SpanPR836.268 ns0.0124 ns0.0104 ns6.266 ns1.090.00
LastIndexOf_char_Spanmain845.221 ns0.0063 ns0.0059 ns5.220 ns1.000.00
LastIndexOf_char_SpanPR846.004 ns0.0035 ns0.0032 ns6.005 ns1.150.00
LastIndexOf_char_Spanmain854.617 ns0.0015 ns0.0011 ns4.617 ns1.000.00
LastIndexOf_char_SpanPR855.771 ns0.0028 ns0.0025 ns5.770 ns1.250.00
LastIndexOf_char_Spanmain64117.617 ns0.0112 ns0.0099 ns17.616 ns1.000.00
LastIndexOf_char_SpanPR6415.610 ns0.0049 ns0.0043 ns5.611 ns0.320.00
LastIndexOf_char_Spanmain64219.020 ns0.0119 ns0.0112 ns19.022 ns1.000.00
LastIndexOf_char_SpanPR6427.238 ns0.0725 ns0.0642 ns7.253 ns0.380.00
LastIndexOf_char_Spanmain64318.526 ns0.0131 ns0.0110 ns18.524 ns1.000.00
LastIndexOf_char_SpanPR6437.215 ns0.0510 ns0.0477 ns7.188 ns0.390.00
LastIndexOf_char_Spanmain64418.194 ns0.0127 ns0.0113 ns18.192 ns1.000.00
LastIndexOf_char_SpanPR6447.288 ns0.0711 ns0.0665 ns7.296 ns0.400.00
LastIndexOf_char_Spanmain64518.095 ns0.0253 ns0.0237 ns18.097 ns1.000.00
LastIndexOf_char_SpanPR6457.137 ns0.0529 ns0.0495 ns7.142 ns0.390.00
LastIndexOf_char_Spanmain10241220.402 ns0.2264 ns0.2118 ns220.303 ns1.000.00
LastIndexOf_char_SpanPR1024129.481 ns0.0918 ns0.0858 ns29.499 ns0.130.00
LastIndexOf_char_Spanmain10242219.591 ns0.3893 ns0.3451 ns219.559 ns1.000.00
LastIndexOf_char_SpanPR1024259.159 ns0.7284 ns0.6813 ns59.171 ns0.270.00
LastIndexOf_char_Spanmain10243218.000 ns0.1500 ns0.1403 ns217.961 ns1.000.00
LastIndexOf_char_SpanPR1024359.667 ns0.3749 ns0.3323 ns59.617 ns0.270.00
LastIndexOf_char_Spanmain10244220.605 ns0.0831 ns0.0737 ns220.620 ns1.000.00
LastIndexOf_char_SpanPR1024459.760 ns0.4245 ns0.3763 ns59.789 ns0.270.00
LastIndexOf_char_Spanmain10245219.007 ns0.1947 ns0.1626 ns219.009 ns1.000.00
LastIndexOf_char_SpanPR1024559.505 ns0.5208 ns0.4871 ns59.411 ns0.270.00
LastIndexOfAny_byte_ROSmain818.740 ns0.1974 ns0.2027 ns8.756 ns1.000.00
LastIndexOfAny_byte_ROSPR815.412 ns0.1336 ns0.1641 ns5.431 ns0.620.02
LastIndexOfAny_byte_ROSmain826.840 ns0.1583 ns0.2059 ns6.875 ns1.000.00
LastIndexOfAny_byte_ROSPR828.224 ns0.1198 ns0.1062 ns8.235 ns1.210.05
LastIndexOfAny_byte_ROSmain839.525 ns0.2188 ns0.3341 ns9.553 ns1.000.00
LastIndexOfAny_byte_ROSPR839.984 ns0.2122 ns0.1985 ns9.950 ns1.050.05
LastIndexOfAny_byte_ROSmain8416.621 ns0.3242 ns0.3033 ns16.816 ns1.000.00
LastIndexOfAny_byte_ROSPR8411.422 ns0.2458 ns0.3108 ns11.439 ns0.690.02
LastIndexOfAny_byte_ROSmain8517.627 ns0.1521 ns0.1422 ns17.653 ns1.000.00
LastIndexOfAny_byte_ROSPR8518.195 ns0.1369 ns0.1281 ns18.194 ns1.030.01
LastIndexOfAny_byte_ROSmain64138.750 ns0.2145 ns0.2006 ns38.723 ns1.000.00
LastIndexOfAny_byte_ROSPR6414.607 ns0.1005 ns0.0891 ns4.613 ns0.120.00
LastIndexOfAny_byte_ROSmain6424.612 ns0.1186 ns0.1584 ns4.656 ns1.000.00
LastIndexOfAny_byte_ROSPR6425.156 ns0.0731 ns0.0684 ns5.193 ns1.120.04
LastIndexOfAny_byte_ROSmain6435.537 ns0.1178 ns0.1102 ns5.542 ns1.000.00
LastIndexOfAny_byte_ROSPR6436.040 ns0.1475 ns0.3012 ns6.163 ns1.080.07
LastIndexOfAny_byte_ROSmain64498.505 ns0.6669 ns0.6238 ns98.666 ns1.000.00
LastIndexOfAny_byte_ROSPR6447.229 ns0.1715 ns0.3424 ns7.249 ns0.070.00
LastIndexOfAny_byte_ROSmain645109.523 ns0.1604 ns0.1500 ns109.560 ns1.000.00
LastIndexOfAny_byte_ROSPR645111.629 ns0.1737 ns0.1624 ns111.664 ns1.020.00
LastIndexOfAny_byte_ROSmain10241548.149 ns0.4610 ns0.4313 ns548.020 ns1.000.00
LastIndexOfAny_byte_ROSPR1024117.031 ns0.0456 ns0.0426 ns17.028 ns0.030.00
LastIndexOfAny_byte_ROSmain1024220.863 ns0.3697 ns0.3458 ns20.693 ns1.000.00
LastIndexOfAny_byte_ROSPR1024218.833 ns0.2013 ns0.1883 ns18.859 ns0.900.02
LastIndexOfAny_byte_ROSmain1024321.567 ns0.2792 ns0.2612 ns21.573 ns1.000.00
LastIndexOfAny_byte_ROSPR1024321.688 ns0.4454 ns0.4766 ns21.688 ns1.000.03
LastIndexOfAny_byte_ROSmain102441,371.158 ns8.6512 ns8.0923 ns1,372.419 ns1.000.00
LastIndexOfAny_byte_ROSPR1024429.946 ns0.3665 ns0.3428 ns30.049 ns0.020.00
LastIndexOfAny_byte_ROSmain102451,644.423 ns2.4255 ns2.2688 ns1,644.547 ns1.000.00
LastIndexOfAny_byte_ROSPR102451,691.436 ns39.6828 ns105.9215 ns1,646.512 ns1.070.11
LastIndexOfAny_byte_Spanmain817.177 ns0.0663 ns0.0621 ns7.179 ns1.000.00
LastIndexOfAny_byte_SpanPR815.121 ns0.0870 ns0.0771 ns5.122 ns0.710.02
LastIndexOfAny_byte_Spanmain8210.563 ns0.1535 ns0.1436 ns10.639 ns1.000.00
LastIndexOfAny_byte_SpanPR829.301 ns0.2136 ns0.4012 ns9.432 ns0.880.04
LastIndexOfAny_byte_Spanmain8313.617 ns0.2393 ns0.2238 ns13.631 ns1.000.00
LastIndexOfAny_byte_SpanPR8310.058 ns0.1335 ns0.1183 ns10.039 ns0.740.01
LastIndexOfAny_byte_Spanmain8416.143 ns0.2179 ns0.2038 ns16.174 ns1.000.00
LastIndexOfAny_byte_SpanPR8412.045 ns0.1427 ns0.1265 ns12.010 ns0.750.01
LastIndexOfAny_byte_Spanmain8517.577 ns0.1953 ns0.1631 ns17.554 ns1.000.00
LastIndexOfAny_byte_SpanPR8526.138 ns0.7270 ns2.1437 ns27.469 ns1.450.12
LastIndexOfAny_byte_Spanmain64138.526 ns0.1101 ns0.1030 ns38.559 ns1.000.00
LastIndexOfAny_byte_SpanPR6414.531 ns0.0941 ns0.0880 ns4.552 ns0.120.00
LastIndexOfAny_byte_Spanmain64259.828 ns0.1546 ns0.1291 ns59.875 ns1.000.00
LastIndexOfAny_byte_SpanPR6425.825 ns0.1112 ns0.1041 ns5.802 ns0.100.00
LastIndexOfAny_byte_Spanmain64378.977 ns1.6081 ns1.7207 ns78.920 ns1.000.00
LastIndexOfAny_byte_SpanPR6436.372 ns0.1522 ns0.2665 ns6.466 ns0.080.00
LastIndexOfAny_byte_Spanmain64492.914 ns0.2358 ns0.2206 ns92.887 ns1.000.00
LastIndexOfAny_byte_SpanPR6447.106 ns0.1092 ns0.1021 ns7.093 ns0.080.00
LastIndexOfAny_byte_Spanmain645115.788 ns0.4738 ns0.4200 ns115.776 ns1.000.00
LastIndexOfAny_byte_SpanPR645178.753 ns2.8791 ns2.4042 ns178.450 ns1.540.02
LastIndexOfAny_byte_Spanmain10241546.179 ns0.7525 ns0.7039 ns546.434 ns1.000.00
LastIndexOfAny_byte_SpanPR1024115.804 ns0.2782 ns0.2603 ns15.831 ns0.030.00
LastIndexOfAny_byte_Spanmain10242826.460 ns0.4934 ns0.4374 ns826.339 ns1.000.00
LastIndexOfAny_byte_SpanPR1024222.172 ns0.4427 ns0.4546 ns22.202 ns0.030.00
LastIndexOfAny_byte_Spanmain102431,116.313 ns13.1206 ns12.2730 ns1,118.085 ns1.000.00
LastIndexOfAny_byte_SpanPR1024323.311 ns0.4563 ns0.4268 ns23.179 ns0.020.00
LastIndexOfAny_byte_Spanmain102441,377.804 ns8.4186 ns7.8747 ns1,377.064 ns1.000.00
LastIndexOfAny_byte_SpanPR1024430.467 ns0.1921 ns0.1703 ns30.499 ns0.020.00
LastIndexOfAny_byte_Spanmain102451,639.299 ns3.6586 ns3.4223 ns1,639.443 ns1.000.00
LastIndexOfAny_byte_SpanPR102451,639.896 ns2.3544 ns2.0871 ns1,639.982 ns1.000.00
LastIndexOfAny_char_ROSmain814.176 ns0.1122 ns0.2753 ns4.304 ns1.000.00
LastIndexOfAny_char_ROSPR814.118 ns0.1111 ns0.2908 ns4.198 ns0.990.09
LastIndexOfAny_char_ROSmain824.153 ns0.1100 ns0.1391 ns4.225 ns1.000.00
LastIndexOfAny_char_ROSPR824.123 ns0.1131 ns0.2336 ns4.225 ns1.000.06
LastIndexOfAny_char_ROSmain835.568 ns0.1368 ns0.1827 ns5.593 ns1.000.00
LastIndexOfAny_char_ROSPR835.579 ns0.1354 ns0.1854 ns5.606 ns1.000.05
LastIndexOfAny_char_ROSmain845.926 ns0.1444 ns0.2452 ns5.906 ns1.000.00
LastIndexOfAny_char_ROSPR846.054 ns0.1478 ns0.2345 ns6.197 ns1.020.06
LastIndexOfAny_char_ROSmain8530.105 ns0.3593 ns0.3361 ns30.278 ns1.000.00
LastIndexOfAny_char_ROSPR8528.813 ns0.1247 ns0.1166 ns28.858 ns0.960.01
LastIndexOfAny_char_ROSmain6415.117 ns0.1311 ns0.3500 ns5.114 ns1.000.00
LastIndexOfAny_char_ROSPR6415.322 ns0.1344 ns0.2093 ns5.392 ns1.040.10
LastIndexOfAny_char_ROSmain6425.861 ns0.1349 ns0.1261 ns5.918 ns1.000.00
LastIndexOfAny_char_ROSPR6425.945 ns0.1455 ns0.1361 ns5.968 ns1.010.03
LastIndexOfAny_char_ROSmain6438.693 ns0.2009 ns0.2945 ns8.722 ns1.000.00
LastIndexOfAny_char_ROSPR6438.670 ns0.1939 ns0.2233 ns8.704 ns1.000.06
LastIndexOfAny_char_ROSmain6449.198 ns0.2122 ns0.4746 ns9.419 ns1.000.00
LastIndexOfAny_char_ROSPR6449.363 ns0.2149 ns0.4763 ns9.568 ns1.020.08
LastIndexOfAny_char_ROSmain645165.454 ns0.4546 ns0.4253 ns165.417 ns1.000.00
LastIndexOfAny_char_ROSPR645163.399 ns0.1426 ns0.1334 ns163.397 ns0.990.00
LastIndexOfAny_char_ROSmain1024130.605 ns0.4445 ns0.4158 ns30.534 ns1.000.00
LastIndexOfAny_char_ROSPR1024130.494 ns0.6011 ns0.5623 ns30.541 ns1.000.02
LastIndexOfAny_char_ROSmain1024235.341 ns0.3629 ns0.3395 ns35.478 ns1.000.00
LastIndexOfAny_char_ROSPR1024235.433 ns0.2929 ns0.2740 ns35.524 ns1.000.01
LastIndexOfAny_char_ROSmain1024351.550 ns0.1107 ns0.0981 ns51.550 ns1.000.00
LastIndexOfAny_char_ROSPR1024351.553 ns0.2292 ns0.2032 ns51.633 ns1.000.00
LastIndexOfAny_char_ROSmain1024452.702 ns0.5584 ns0.5223 ns52.951 ns1.000.00
LastIndexOfAny_char_ROSPR1024452.687 ns0.6479 ns0.6061 ns52.992 ns1.000.02
LastIndexOfAny_char_ROSmain102452,402.390 ns6.0446 ns5.6541 ns2,400.650 ns1.000.00
LastIndexOfAny_char_ROSPR102452,400.704 ns3.5544 ns2.9681 ns2,399.535 ns1.000.00
LastIndexOfAny_char_Spanmain816.727 ns0.0787 ns0.0698 ns6.737 ns1.000.00
LastIndexOfAny_char_SpanPR813.637 ns0.1023 ns0.3015 ns3.727 ns0.550.05
LastIndexOfAny_char_Spanmain828.841 ns0.0080 ns0.0075 ns8.840 ns1.000.00
LastIndexOfAny_char_SpanPR824.405 ns0.1111 ns0.1628 ns4.505 ns0.490.02
LastIndexOfAny_char_Spanmain8311.014 ns0.0100 ns0.0089 ns11.012 ns1.000.00
LastIndexOfAny_char_SpanPR835.497 ns0.1366 ns0.2663 ns5.504 ns0.490.02
LastIndexOfAny_char_Spanmain8412.962 ns0.0631 ns0.0590 ns12.944 ns1.000.00
LastIndexOfAny_char_SpanPR846.496 ns0.1553 ns0.1789 ns6.500 ns0.500.01
LastIndexOfAny_char_Spanmain8515.172 ns0.0622 ns0.0581 ns15.181 ns1.000.00
LastIndexOfAny_char_SpanPR8529.214 ns0.1136 ns0.1062 ns29.259 ns1.930.01
LastIndexOfAny_char_Spanmain64137.689 ns0.0323 ns0.0302 ns37.682 ns1.000.00
LastIndexOfAny_char_SpanPR6414.564 ns0.1197 ns0.2218 ns4.643 ns0.120.01
LastIndexOfAny_char_Spanmain64258.640 ns0.1044 ns0.0925 ns58.613 ns1.000.00
LastIndexOfAny_char_SpanPR6425.953 ns0.0897 ns0.0700 ns5.974 ns0.100.00
LastIndexOfAny_char_Spanmain64376.896 ns0.4778 ns0.4469 ns76.845 ns1.000.00
LastIndexOfAny_char_SpanPR6439.166 ns0.2175 ns0.6414 ns9.171 ns0.120.01
LastIndexOfAny_char_Spanmain64491.639 ns0.3216 ns0.3009 ns91.635 ns1.000.00
LastIndexOfAny_char_SpanPR64410.127 ns0.1005 ns0.0940 ns10.151 ns0.110.00
LastIndexOfAny_char_Spanmain645109.354 ns0.2167 ns0.2027 ns109.332 ns1.000.00
LastIndexOfAny_char_SpanPR645165.458 ns1.4240 ns1.3320 ns165.469 ns1.510.01
LastIndexOfAny_char_Spanmain10241552.382 ns0.2771 ns0.2314 ns552.404 ns1.000.00
LastIndexOfAny_char_SpanPR1024129.888 ns0.1588 ns0.1486 ns29.938 ns0.050.00
LastIndexOfAny_char_Spanmain10242826.694 ns0.8303 ns0.7767 ns826.598 ns1.000.00
LastIndexOfAny_char_SpanPR1024232.428 ns0.0896 ns0.0838 ns32.427 ns0.040.00
LastIndexOfAny_char_Spanmain102431,418.347 ns86.3344 ns254.5588 ns1,636.604 ns1.000.00
LastIndexOfAny_char_SpanPR1024352.653 ns0.6295 ns0.5888 ns52.679 ns0.040.01
LastIndexOfAny_char_Spanmain102441,373.643 ns6.0041 ns5.0137 ns1,373.256 ns1.000.00
LastIndexOfAny_char_SpanPR1024452.931 ns0.3968 ns0.3712 ns52.740 ns0.040.00
LastIndexOfAny_char_Spanmain102451,659.335 ns2.3113 ns1.8045 ns1,659.399 ns1.000.00
LastIndexOfAny_char_SpanPR102452,408.283 ns8.3724 ns7.8315 ns2,405.072 ns1.450.00
publicclassPrValidation{[Params(8,64,1024)]publicintSearchSpaceCount;[Params(1,2,3,4,5)]publicintValueSpaceCount;privatebyte[]_searchSpaceBytes,_valueSpaceBytes;privatechar[]_searchSpaceChars,_valueSpaceChars;[GlobalSetup]publicvoidSetup(){_searchSpaceBytes=newbyte[SearchSpaceCount];_searchSpaceChars=newchar[SearchSpaceCount];_valueSpaceBytes=Enumerable.Range(1,ValueSpaceCount).Select(Convert.ToByte).ToArray();_valueSpaceChars=Enumerable.Range(1,ValueSpaceCount).Select(Convert.ToChar).ToArray();}[Benchmark]publicvoidLastIndexOf_char_Span()=>newSpan<char>(_searchSpaceChars).LastIndexOf(_valueSpaceChars);[Benchmark]publicvoidIndexOfAny_byte_ROS()=>newReadOnlySpan<byte>(_searchSpaceBytes).IndexOfAny(_valueSpaceBytes);[Benchmark]publicvoidLastIndexOfAny_byte_Span()=>newSpan<byte>(_searchSpaceBytes).LastIndexOfAny(_valueSpaceBytes);[Benchmark]publicvoidLastIndexOfAny_byte_ROS()=>newReadOnlySpan<byte>(_searchSpaceBytes).LastIndexOfAny(_valueSpaceBytes);[Benchmark]publicvoidLastIndexOfAny_char_Span()=>newSpan<char>(_searchSpaceChars).LastIndexOfAny(_valueSpaceChars);[Benchmark]publicvoidLastIndexOfAny_char_ROS()=>newReadOnlySpan<char>(_searchSpaceChars).LastIndexOfAny(_valueSpaceChars);}

@Rob-Hague
Rob-Hague marked this pull request as ready for review September 17, 2022 13:06
@Rob-Hague

Rob-Hague commented Sep 18, 2022

Copy link
Copy Markdown
ContributorAuthor

I ran some slightly more comprehensive benchmarks on LastIndexOfAny 5-value. Really the changes are just unifying the Span and ReadOnlySpan versions which I presume is supposed to be the case and I am only submitting them in the context of correcting a mistake rather than any optimisation opportunity. So the benchmarks are just for completeness sake (and curiosity).

Details
BenchmarkDotNet=v0.13.2, OS=Windows 11 (10.0.22000.978/21H2)
AMD Ryzen 7 5700U with Radeon Graphics, 1 CPU, 16 logical and 8 physical cores
.NET SDK=8.0.100-alpha.1.22465.14
[Host] : .NET 8.0.0 (8.0.22.46215), X64 RyuJIT AVX2
main : .NET 8.0.0 (42.42.42.42424), X64 RyuJIT AVX2
PR : .NET 8.0.0 (42.42.42.42424), X64 RyuJIT AVX2
MethodJobSearchSpaceCountvalueSpaceMeanErrorStdDevMedianRatioRatioSD
LastIndexOfAny_Spanmain10\r\n\t\\\"27.804 ns0.5796 ns1.3082 ns27.910 ns1.000.00
LastIndexOfAny_SpanPR10\r\n\t\\\"16.236 ns0.1208 ns0.1130 ns16.286 ns0.600.03
LastIndexOfAny_ROSmain10\r\n\t\\\"15.309 ns0.1546 ns0.1447 ns15.357 ns1.000.00
LastIndexOfAny_ROSPR10\r\n\t\\\"15.421 ns0.1328 ns0.1242 ns15.466 ns1.010.01
LastIndexOfAny_Spanmain10LWXYZ27.230 ns0.8606 ns2.5374 ns26.416 ns1.000.00
LastIndexOfAny_SpanPR10LWXYZ17.270 ns0.1064 ns0.0996 ns17.313 ns0.660.05
LastIndexOfAny_ROSmain10LWXYZ16.384 ns0.0820 ns0.0767 ns16.433 ns1.000.00
LastIndexOfAny_ROSPR10LWXYZ16.341 ns0.1697 ns0.1587 ns16.401 ns1.000.01
LastIndexOfAny_Spanmain10abcde14.497 ns0.1948 ns0.1727 ns14.422 ns1.000.00
LastIndexOfAny_SpanPR10abcde16.428 ns0.1138 ns0.1065 ns16.439 ns1.130.02
LastIndexOfAny_ROSmain10abcde15.460 ns0.1171 ns0.1095 ns15.515 ns1.000.00
LastIndexOfAny_ROSPR10abcde15.429 ns0.1387 ns0.1298 ns15.469 ns1.000.01
LastIndexOfAny_Spanmain10zzzzu3.325 ns0.0305 ns0.0270 ns3.323 ns1.000.00
LastIndexOfAny_SpanPR10zzzzu12.517 ns0.1053 ns0.0985 ns12.548 ns3.770.05
LastIndexOfAny_ROSmain10zzzzu11.752 ns0.1259 ns0.1051 ns11.768 ns1.000.00
LastIndexOfAny_ROSPR10zzzzu11.853 ns0.2234 ns0.2090 ns11.757 ns1.010.02
LastIndexOfAny_Spanmain100\r\n\t&quot;250.333 ns5.0276 ns11.8508 ns249.235 ns1.000.00
LastIndexOfAny_SpanPR100\r\n\t&quot;82.828 ns0.1629 ns0.1360 ns82.841 ns0.330.02
LastIndexOfAny_ROSmain100\r\n\t&quot;75.268 ns0.1356 ns0.1268 ns75.216 ns1.000.00
LastIndexOfAny_ROSPR100\r\n\t&quot;74.259 ns0.1841 ns0.1722 ns74.271 ns0.990.00
LastIndexOfAny_Spanmain100LWXYZ295.952 ns13.6564 ns40.2662 ns292.568 ns1.000.00
LastIndexOfAny_SpanPR100LWXYZ87.481 ns1.2991 ns1.2152 ns87.459 ns0.350.04
LastIndexOfAny_ROSmain100LWXYZ79.039 ns0.2940 ns0.2750 ns79.073 ns1.000.00
LastIndexOfAny_ROSPR100LWXYZ79.330 ns0.4195 ns0.3924 ns79.323 ns1.000.00
LastIndexOfAny_Spanmain100abcde8.767 ns0.1342 ns0.1120 ns8.772 ns1.000.00
LastIndexOfAny_SpanPR100abcde13.302 ns0.1049 ns0.0981 ns13.350 ns1.520.03
LastIndexOfAny_ROSmain100abcde12.582 ns0.1828 ns0.1710 ns12.606 ns1.000.00
LastIndexOfAny_ROSPR100abcde12.525 ns0.1695 ns0.1586 ns12.584 ns1.000.02
LastIndexOfAny_Spanmain100zzzzu8.908 ns0.2076 ns0.5014 ns9.091 ns1.000.00
LastIndexOfAny_SpanPR100zzzzu13.690 ns0.1475 ns0.1380 ns13.731 ns1.540.10
LastIndexOfAny_ROSmain100zzzzu12.846 ns0.2601 ns0.2433 ns12.949 ns1.000.00
LastIndexOfAny_ROSPR100zzzzu12.885 ns0.1873 ns0.1752 ns12.920 ns1.000.02
LastIndexOfAny_Spanmain1000\r\n\t&quot;526.045 ns4.8075 ns4.2617 ns527.380 ns1.000.00
LastIndexOfAny_SpanPR1000\r\n\t&quot;207.644 ns0.0942 ns0.0787 ns207.641 ns0.390.00
LastIndexOfAny_ROSmain1000\r\n\t&quot;183.971 ns0.3338 ns0.2959 ns184.048 ns1.000.00
LastIndexOfAny_ROSPR1000\r\n\t&quot;184.128 ns0.2943 ns0.2609 ns184.171 ns1.000.00
LastIndexOfAny_Spanmain1000LWXYZ2,190.996 ns145.3601 ns428.5975 ns2,315.091 ns1.000.00
LastIndexOfAny_SpanPR1000LWXYZ640.646 ns0.2470 ns0.2311 ns640.625 ns0.280.02
LastIndexOfAny_ROSmain1000LWXYZ561.617 ns0.5231 ns0.4637 ns561.710 ns1.000.00
LastIndexOfAny_ROSPR1000LWXYZ561.928 ns0.3935 ns0.3681 ns561.968 ns1.000.00
LastIndexOfAny_Spanmain1000abcde10.516 ns0.2370 ns0.2910 ns10.596 ns1.000.00
LastIndexOfAny_SpanPR1000abcde14.389 ns0.1549 ns0.1449 ns14.413 ns1.370.04
LastIndexOfAny_ROSmain1000abcde13.649 ns0.1730 ns0.1618 ns13.717 ns1.000.00
LastIndexOfAny_ROSPR1000abcde13.523 ns0.2902 ns0.2715 ns13.618 ns0.990.02
LastIndexOfAny_Spanmain1000zzzzu11.171 ns0.1732 ns0.1621 ns11.212 ns1.000.00
LastIndexOfAny_SpanPR1000zzzzu15.124 ns0.1184 ns0.1108 ns15.155 ns1.350.02
LastIndexOfAny_ROSmain1000zzzzu14.606 ns0.1404 ns0.1313 ns14.625 ns1.000.00
LastIndexOfAny_ROSPR1000zzzzu14.626 ns0.1390 ns0.1300 ns14.686 ns1.000.01
publicclassLoremIpsum{[Params(10,100,1000)]publicintSearchSpaceCount;privatechar[]_searchSpace;[GlobalSetup]publicvoidSetup(){_searchSpace=_loremIpsum.AsSpan(0,SearchSpaceCount).ToArray();}[Benchmark][ArgumentsSource(nameof(ValueSpaces))]publicintLastIndexOfAny_Span(stringvalueSpace)=>newSpan<char>(_searchSpace).LastIndexOfAny(valueSpace);[Benchmark][ArgumentsSource(nameof(ValueSpaces))]publicintLastIndexOfAny_ROS(stringvalueSpace)=>newReadOnlySpan<char>(_searchSpace).LastIndexOfAny(valueSpace);publicIEnumerable<object>ValueSpaces(){yieldreturn"\r\n\t\\\"";// (-1, -1, 724) in _searchSpace.AsSpan(0, SearchSpaceCount)yieldreturn"abcde";// (3, 96, 996)yieldreturn"zzzzu";// (-1, 57, 899)yieldreturn"LWXYZ";// (0, 0, 101)}privatereadonlystring_loremIpsum=@"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam sodales orci at urna efficitur finibus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean ultrices facilisis volutpat. Curabitur vel sollicitudin risus. Nunc tortor libero, pretium ut mi eu, finibus rutrum enim. Vivamus malesuada vel nunc eu faucibus. Aliquam volutpat ultrices risus non pellentesque. Vivamus dignissim augue non dignissim pellentesque. Duis a fermentum dui. Nullam quis vestibulum neque. Quisque euismod ligula in ex blandit, sed aliquam orci lacinia. Curabitur facilisis, ante cursus venenatis dictum, elit ante rutrum nibh, vitae maximus libero odio ac est. Aliquam dignissim eros quis congue convallis. Aenean et erat libero.Donec sapien nisl, efficitur nec arcu non, convallis fringilla nunc. Aenean rhoncus, tortor quis imperdiet placerat, dui nibh accumsan felis, sed mattis odio lectus sed est. Nulla cursus dictum sodales. Maecenas eget ornare augue, sed aliquam mauris. Fusce vel nisl congue, porta elit et, semper lectus.";}

@Rob-Hague

Copy link
Copy Markdown
ContributorAuthor

ping @adamsitnik not sure if you saw this one (which was unfortunately timed amongst the other IndexOf fixes), or if you otherwise had any thoughts. Thanks

@adamsitnikadamsitnik self-assigned this Oct 26, 2022

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thank you for a very thoughtful audit of all MemoryExtensions overloads! And apologies for the delay in review.

The PR looks great to me, failures are unrelated. Merging!

@adamsitnik
adamsitnik merged commit 3e40074 into dotnet:mainOct 26, 2022
@adamsitnikadamsitnik added the tenet-performance Performance related issue label Oct 26, 2022
@adamsitnikadamsitnik added this to the 8.0.0 milestone Oct 26, 2022
/// </summary>
/// <param name="span">The span to search.</param>
/// <param name="values">The set of values to search for.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]

@MihaZupanMihaZupanOct 26, 2022

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@Rob-Hague@adamsitnik
Was this intentional?

For better or worse, the LastIndexOfAny(ROS) overload is marked with AggressiveInlining, so this Span overload will now be more expensive for const values.

At the very least, it's now even more inconsistent with other places (e.g. IndexOfAny).

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

It was intentional in that it became consistent with many of the other Span to ROS forwards though I agree it is (now) inconsistent with IndexOfAny(Span, ROS). I probably overlooked that.

I also believed that the annotation was superfluous in such cases - I apologise for the assumption as I did not instrument that.

@AndyAyersMS

AndyAyersMS commented Nov 3, 2022

Copy link
Copy Markdown
Member

@ghostghost locked as resolved and limited conversation to collaborators Dec 3, 2022
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Memorycommunity-contributionIndicates that the PR has been added by a community membertenet-performancePerformance related issue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@Rob-Hague@dnfadmin@AndyAyersMS@adamsitnik@MihaZupan@jozkee