Skip to content

Improve String.Substring performance #62577

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

Closed
wants to merge 8 commits into from
Closed

Conversation

nietras
Copy link
Contributor

@nietras nietras commented Dec 9, 2021

WIP just to get the ball rolling regarding discussion of changing exception messages or similar. cc @adamsitnik @GrabYourPitchforks @stephentoub as discussed in #60463

Change to Substring(int startIndex) improvements (note highly volatile). This comes with all the caveats of potential increases code size etc.

BenchmarkDotNet=v0.13.1.1620-nightly, OS=Windows 10.0.19044.1348 (21H2)
AMD Ryzen 9 5950X, 1 CPU, 32 logical and 16 physical cores
.NET SDK=7.0.100-alpha.1.21568.2
  [Host]     : .NET 6.0.0 (6.0.21.48005), X64 RyuJIT
  Job-FWUOEW : .NET 7.0.0 (42.42.42.42424), X64 RyuJIT
  Job-HPGSVV : .NET 7.0.0 (42.42.42.42424), X64 RyuJIT

PowerPlanMode=00000000-0000-0000-0000-000000000000  Arguments=/p:DebugType=portable,-bl:benchmarkdotnet.binlog  IterationTime=250.0000 ms  
MaxIterationCount=20  MinIterationCount=15  WarmupCount=1  
Method Job Toolchain s i Mean Error StdDev Median Min Max Ratio RatioSD Gen 0 Allocated
Substring_Int Job-FWUOEW m dzsdzsDDZSDZSDZSddsz 0 1.1022 ns 0.0068 ns 0.0064 ns 1.1049 ns 1.0853 ns 1.1092 ns 1.00 0.00 - -
Substring_Int Job-HPGSVV pr dzsdzsDDZSDZSDZSddsz 0 0.4543 ns 0.0069 ns 0.0065 ns 0.4541 ns 0.4382 ns 0.4658 ns 0.41 0.01 - -
Substring_Int Job-FWUOEW m dzsdzsDDZSDZSDZSddsz 7 8.6245 ns 2.2287 ns 2.5666 ns 9.5946 ns 5.4283 ns 12.5358 ns 1.00 0.00 0.0029 48 B
Substring_Int Job-HPGSVV pr dzsdzsDDZSDZSDZSddsz 7 7.1005 ns 1.1957 ns 1.3770 ns 6.5014 ns 5.6306 ns 9.5741 ns 0.88 0.22 0.0029 48 B
Substring_Int Job-FWUOEW m dzsdzsDDZSDZSDZSddsz 10 10.3062 ns 0.6670 ns 0.7681 ns 10.5393 ns 8.8757 ns 11.3953 ns 1.00 0.00 0.0029 48 B
Substring_Int Job-HPGSVV pr dzsdzsDDZSDZSDZSddsz 10 7.5328 ns 0.6341 ns 0.7302 ns 7.4150 ns 6.3654 ns 9.1740 ns 0.73 0.07 0.0028 48 B
Substring_Int Job-FWUOEW m dzsdzsDDZSDZSDZSddsz 19 12.9457 ns 1.6428 ns 1.8919 ns 13.3785 ns 5.5022 ns 14.3101 ns 1.00 0.00 0.0014 24 B
Substring_Int Job-HPGSVV pr dzsdzsDDZSDZSDZSddsz 19 6.8188 ns 0.9429 ns 1.0858 ns 6.6514 ns 5.0843 ns 9.0324 ns 0.55 0.18 0.0014 24 B

@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.

@ghost ghost added the community-contribution Indicates that the PR has been added by a community member label Dec 9, 2021
@nietras
Copy link
Contributor Author

nietras commented Dec 9, 2021

Using Span.Slice guard clauses for perf. Regressions I believe are due to benchmark issues. In any case, is changing guard clauses to this an acceptable change? Should exception messages be preserved?

// * Warnings *
MultimodalDistribution
  Perf_String.Substring_IntInt: PowerPlanMode=00000000-0000-0000-0000-000000000000, Arguments=/p:DebugType=portable,-bl:benchmarkdotnet.binlog, Toolchain=\runtime-pr\artifacts\bin\testhost\net7.0-windows-Release-x64\shared\Microsoft.NETCore.App\7.0.0\CoreRun.exe, IterationTime=250.0000 ms, MaxIterationCount=20, MinIterationCount=15, WarmupCount=1 -> It seems that the distribution is bimodal (mValue = 3.56)
  Perf_String.Substring_IntInt: PowerPlanMode=00000000-0000-0000-0000-000000000000, Arguments=/p:DebugType=portable,-bl:benchmarkdotnet.binlog, Toolchain=\runtime-m\artifacts\bin\testhost\net7.0-windows-Release-x64\shared\Microsoft.NETCore.App\7.0.0\CoreRun.exe, IterationTime=250.0000 ms, MaxIterationCount=20, MinIterationCount=15, WarmupCount=1  -> It seems that the distribution can have several modes (mValue = 2.89)
  Perf_String.Substring_IntInt: PowerPlanMode=00000000-0000-0000-0000-000000000000, Arguments=/p:DebugType=portable,-bl:benchmarkdotnet.binlog, Toolchain=\runtime-m\artifacts\bin\testhost\net7.0-windows-Release-x64\shared\Microsoft.NETCore.App\7.0.0\CoreRun.exe, IterationTime=250.0000 ms, MaxIterationCount=20, MinIterationCount=15, WarmupCount=1  -> It seems that the distribution is bimodal (mValue = 3.75)
  Perf_String.Substring_Int: PowerPlanMode=00000000-0000-0000-0000-000000000000, Arguments=/p:DebugType=portable,-bl:benchmarkdotnet.binlog, Toolchain=\runtime-m\artifacts\bin\testhost\net7.0-windows-Release-x64\shared\Microsoft.NETCore.App\7.0.0\CoreRun.exe, IterationTime=250.0000 ms, MaxIterationCount=20, MinIterationCount=15, WarmupCount=1     -> It seems that the distribution can have several modes (mValue = 3)
  Perf_String.Substring_Int: PowerPlanMode=00000000-0000-0000-0000-000000000000, Arguments=/p:DebugType=portable,-bl:benchmarkdotnet.binlog, Toolchain=\runtime-pr\artifacts\bin\testhost\net7.0-windows-Release-x64\shared\Microsoft.NETCore.App\7.0.0\CoreRun.exe, IterationTime=250.0000 ms, MaxIterationCount=20, MinIterationCount=15, WarmupCount=1    -> It seems that the distribution is bimodal (mValue = 3.78)
  Perf_String.Substring_Int: PowerPlanMode=00000000-0000-0000-0000-000000000000, Arguments=/p:DebugType=portable,-bl:benchmarkdotnet.binlog, Toolchain=\runtime-pr\artifacts\bin\testhost\net7.0-windows-Release-x64\shared\Microsoft.NETCore.App\7.0.0\CoreRun.exe, IterationTime=250.0000 ms, MaxIterationCount=20, MinIterationCount=15, WarmupCount=1    -> It seems that the distribution can have several modes (mValue = 2.83)
BenchmarkDotNet=v0.13.1.1620-nightly, OS=Windows 10.0.19044.1348 (21H2)
AMD Ryzen 9 5950X, 1 CPU, 32 logical and 16 physical cores
.NET SDK=7.0.100-alpha.1.21568.2
  [Host]     : .NET 6.0.0 (6.0.21.48005), X64 RyuJIT
  Job-ICQHYC : .NET 7.0.0 (42.42.42.42424), X64 RyuJIT
  Job-KPKVVD : .NET 7.0.0 (42.42.42.42424), X64 RyuJIT

PowerPlanMode=00000000-0000-0000-0000-000000000000  Arguments=/p:DebugType=portable,-bl:benchmarkdotnet.binlog  IterationTime=250.0000 ms  
MaxIterationCount=20  MinIterationCount=15  WarmupCount=1  
Method Job Toolchain s i l Mean Error StdDev Median Min Max Ratio RatioSD Gen 0 Allocated
Substring_IntInt Job-ICQHYC m dzsdzsDDZSDZSDZSddsz 0 8 15.3259 ns 0.9471 ns 1.0906 ns 15.6270 ns 11.1665 ns 16.1263 ns 1.00 0.00 0.0024 40 B
Substring_IntInt Job-KPKVVD pr dzsdzsDDZSDZSDZSddsz 0 8 7.1677 ns 0.3913 ns 0.4506 ns 7.2510 ns 6.2912 ns 7.9841 ns 0.47 0.05 0.0024 40 B
Substring_Int Job-ICQHYC m dzsdzsDDZSDZSDZSddsz 0 ? 1.0918 ns 0.0057 ns 0.0051 ns 1.0905 ns 1.0861 ns 1.1031 ns 1.00 0.00 - -
Substring_Int Job-KPKVVD pr dzsdzsDDZSDZSDZSddsz 0 ? 0.4470 ns 0.0059 ns 0.0055 ns 0.4444 ns 0.4404 ns 0.4585 ns 0.41 0.01 - -
Substring_IntInt Job-ICQHYC m dzsdzsDDZSDZSDZSddsz 7 4 7.6604 ns 0.3992 ns 0.4597 ns 7.7002 ns 6.7318 ns 8.2808 ns 1.00 0.00 0.0019 32 B
Substring_IntInt Job-KPKVVD pr dzsdzsDDZSDZSDZSddsz 7 4 13.2061 ns 0.9380 ns 1.0802 ns 13.5553 ns 11.1386 ns 14.6399 ns 1.73 0.21 0.0019 32 B
Substring_Int Job-ICQHYC m dzsdzsDDZSDZSDZSddsz 7 ? 9.0171 ns 1.6091 ns 1.8531 ns 9.2496 ns 5.2419 ns 12.1909 ns 1.00 0.00 0.0029 48 B
Substring_Int Job-KPKVVD pr dzsdzsDDZSDZSDZSddsz 7 ? 14.7738 ns 0.7346 ns 0.8165 ns 14.9451 ns 11.5924 ns 15.5339 ns 1.73 0.44 0.0029 48 B
Substring_IntInt Job-ICQHYC m dzsdzsDDZSDZSDZSddsz 10 1 12.1967 ns 1.0340 ns 1.1908 ns 12.3111 ns 10.2499 ns 14.3337 ns 1.00 0.00 0.0014 24 B
Substring_IntInt Job-KPKVVD pr dzsdzsDDZSDZSDZSddsz 10 1 4.3119 ns 0.0334 ns 0.0279 ns 4.3081 ns 4.2731 ns 4.3719 ns 0.35 0.04 0.0014 24 B
Substring_Int Job-ICQHYC m dzsdzsDDZSDZSDZSddsz 10 ? 10.0238 ns 0.5880 ns 0.6772 ns 10.1232 ns 8.0144 ns 10.7685 ns 1.00 0.00 0.0029 48 B
Substring_Int Job-KPKVVD pr dzsdzsDDZSDZSDZSddsz 10 ? 10.8206 ns 0.7301 ns 0.8407 ns 10.7733 ns 8.8957 ns 11.9972 ns 1.09 0.14 0.0029 48 B
Substring_Int Job-ICQHYC m dzsdzsDDZSDZSDZSddsz 19 ? 10.1852 ns 0.8323 ns 0.9585 ns 10.1999 ns 8.4898 ns 11.9423 ns 1.00 0.00 0.0014 24 B
Substring_Int Job-KPKVVD pr dzsdzsDDZSDZSDZSddsz 19 ? 6.4746 ns 0.4515 ns 0.5200 ns 6.2816 ns 5.9014 ns 7.5252 ns 0.64 0.08 0.0014 24 B

@ghost
Copy link

ghost commented Dec 9, 2021

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

Issue Details

WIP just to get the ball rolling regarding discussion of changing exception messages or similar. cc @adamsitnik @GrabYourPitchforks @stephentoub as discussed in #60463

Change to Substring(int startIndex) improvements (note highly volatile). This comes with all the caveats of potential increases code size etc.

BenchmarkDotNet=v0.13.1.1620-nightly, OS=Windows 10.0.19044.1348 (21H2)
AMD Ryzen 9 5950X, 1 CPU, 32 logical and 16 physical cores
.NET SDK=7.0.100-alpha.1.21568.2
  [Host]     : .NET 6.0.0 (6.0.21.48005), X64 RyuJIT
  Job-FWUOEW : .NET 7.0.0 (42.42.42.42424), X64 RyuJIT
  Job-HPGSVV : .NET 7.0.0 (42.42.42.42424), X64 RyuJIT

PowerPlanMode=00000000-0000-0000-0000-000000000000  Arguments=/p:DebugType=portable,-bl:benchmarkdotnet.binlog  IterationTime=250.0000 ms  
MaxIterationCount=20  MinIterationCount=15  WarmupCount=1  
Method Job Toolchain s i Mean Error StdDev Median Min Max Ratio RatioSD Gen 0 Allocated
Substring_Int Job-FWUOEW m dzsdzsDDZSDZSDZSddsz 0 1.1022 ns 0.0068 ns 0.0064 ns 1.1049 ns 1.0853 ns 1.1092 ns 1.00 0.00 - -
Substring_Int Job-HPGSVV pr dzsdzsDDZSDZSDZSddsz 0 0.4543 ns 0.0069 ns 0.0065 ns 0.4541 ns 0.4382 ns 0.4658 ns 0.41 0.01 - -
Substring_Int Job-FWUOEW m dzsdzsDDZSDZSDZSddsz 7 8.6245 ns 2.2287 ns 2.5666 ns 9.5946 ns 5.4283 ns 12.5358 ns 1.00 0.00 0.0029 48 B
Substring_Int Job-HPGSVV pr dzsdzsDDZSDZSDZSddsz 7 7.1005 ns 1.1957 ns 1.3770 ns 6.5014 ns 5.6306 ns 9.5741 ns 0.88 0.22 0.0029 48 B
Substring_Int Job-FWUOEW m dzsdzsDDZSDZSDZSddsz 10 10.3062 ns 0.6670 ns 0.7681 ns 10.5393 ns 8.8757 ns 11.3953 ns 1.00 0.00 0.0029 48 B
Substring_Int Job-HPGSVV pr dzsdzsDDZSDZSDZSddsz 10 7.5328 ns 0.6341 ns 0.7302 ns 7.4150 ns 6.3654 ns 9.1740 ns 0.73 0.07 0.0028 48 B
Substring_Int Job-FWUOEW m dzsdzsDDZSDZSDZSddsz 19 12.9457 ns 1.6428 ns 1.8919 ns 13.3785 ns 5.5022 ns 14.3101 ns 1.00 0.00 0.0014 24 B
Substring_Int Job-HPGSVV pr dzsdzsDDZSDZSDZSddsz 19 6.8188 ns 0.9429 ns 1.0858 ns 6.6514 ns 5.0843 ns 9.0324 ns 0.55 0.18 0.0014 24 B
Author: nietras
Assignees: -
Labels:

area-System.Runtime, community-contribution

Milestone: -

@adamsitnik adamsitnik added the tenet-performance Performance related issue label Dec 10, 2021
@nietras
Copy link
Contributor Author

nietras commented Dec 10, 2021

@GrabYourPitchforks tried to address feedback. Still don't know what to do about getting reliable benchmark tests. These do not show expected results currently but are also volatile. Substring(0) still faster of course.

Tried running StringReaderReadLineTests.ReadLine tests but no significant change there except [0, 0] case, so this PR does not appear to currently improve on that.

Let me know, what next steps you guys think should be.

@nietras
Copy link
Contributor Author

nietras commented Dec 14, 2021

Cleaned up. Benchmarks below, only significant improvements for when returning same string or empty. Regressions are often due to variance in benchmarks. Main point probably is throw code is separated out reducing code size of the method. I have included the cost of new'ing a similar string for comparison here.

Substring(int)

Method Job Toolchain Start Mean Error StdDev Median Min Max Ratio RatioSD Gen 0 Gen 1 Gen 2 Allocated Code Size
Substring Job-WNUADI m 0 1.933 ns 0.0043 ns 0.0038 ns 1.934 ns 1.926 ns 1.939 ns 1.00 0.00 - - - - 867 B
Substring Job-WPCFEP pr 0 1.283 ns 0.0061 ns 0.0057 ns 1.282 ns 1.275 ns 1.294 ns 0.66 0.00 - - - - 471 B
Substring Job-WNUADI m 8 5.323 ns 0.0295 ns 0.0276 ns 5.324 ns 5.286 ns 5.382 ns 1.00 0.00 0.0024 - - 40 B 867 B
Substring Job-WPCFEP pr 8 5.906 ns 0.0271 ns 0.0240 ns 5.895 ns 5.875 ns 5.947 ns 1.11 0.01 0.0024 - - 40 B 471 B
NewString Job-WNUADI m 8 3.755 ns 0.0320 ns 0.0299 ns 3.760 ns 3.706 ns 3.805 ns 1.00 0.00 0.0024 - - 40 B 40 B
NewString Job-WPCFEP pr 8 3.758 ns 0.0170 ns 0.0151 ns 3.760 ns 3.730 ns 3.782 ns 1.00 0.01 0.0024 - - 40 B 40 B
Substring Job-WNUADI m 16 1.570 ns 0.0473 ns 0.0419 ns 1.552 ns 1.538 ns 1.655 ns 1.00 0.00 - - - - 867 B
Substring Job-WPCFEP pr 16 1.578 ns 0.0353 ns 0.0330 ns 1.594 ns 1.511 ns 1.614 ns 1.00 0.03 - - - - 471 B
NewString Job-WNUADI m 16 1.371 ns 0.0218 ns 0.0193 ns 1.372 ns 1.343 ns 1.413 ns 1.00 0.00 - - - - 40 B
NewString Job-WPCFEP pr 16 1.296 ns 0.0040 ns 0.0036 ns 1.296 ns 1.290 ns 1.302 ns 0.95 0.01 - - - - 40 B

Substring(int,int)

Method Job Toolchain Slice Mean Error StdDev Median Min Max Ratio RatioSD Gen 0 Gen 1 Gen 2 Allocated Code Size
Substring Job-WNUADI m I: 0 L: 0 1.713 ns 0.0042 ns 0.0039 ns 1.712 ns 1.707 ns 1.721 ns 1.00 0.00 - - - - 864 B
Substring Job-WPCFEP pr I: 0 L: 0 1.292 ns 0.0063 ns 0.0059 ns 1.290 ns 1.283 ns 1.303 ns 0.75 0.00 - - - - 483 B
NewString Job-WNUADI m I: 0 L: 0 1.702 ns 0.0046 ns 0.0043 ns 1.701 ns 1.693 ns 1.710 ns 1.00 0.00 - - - - 27 B
NewString Job-WPCFEP pr I: 0 L: 0 1.501 ns 0.0034 ns 0.0029 ns 1.501 ns 1.495 ns 1.505 ns 0.88 0.00 - - - - 27 B
Substring Job-WNUADI m I: 0 L:16 1.923 ns 0.0025 ns 0.0022 ns 1.924 ns 1.918 ns 1.926 ns 1.00 0.00 - - - - 864 B
Substring Job-WPCFEP pr I: 0 L:16 1.504 ns 0.0027 ns 0.0026 ns 1.505 ns 1.499 ns 1.509 ns 0.78 0.00 - - - - 483 B
NewString Job-WNUADI m I: 0 L:16 4.252 ns 0.0147 ns 0.0130 ns 4.255 ns 4.218 ns 4.268 ns 1.00 0.00 0.0033 - - 56 B 27 B
NewString Job-WPCFEP pr I: 0 L:16 4.214 ns 0.0461 ns 0.0409 ns 4.207 ns 4.163 ns 4.280 ns 0.99 0.01 0.0033 - - 56 B 27 B
Substring Job-WNUADI m I: 1 L: 1 5.146 ns 0.0528 ns 0.0494 ns 5.154 ns 4.973 ns 5.177 ns 1.00 0.00 0.0014 - - 24 B 864 B
Substring Job-WPCFEP pr I: 1 L: 1 5.194 ns 0.0180 ns 0.0159 ns 5.194 ns 5.161 ns 5.221 ns 1.01 0.01 0.0014 - - 24 B 483 B
NewString Job-WNUADI m I: 1 L: 1 3.656 ns 0.0179 ns 0.0167 ns 3.658 ns 3.623 ns 3.678 ns 1.00 0.00 0.0014 - - 24 B 27 B
NewString Job-WPCFEP pr I: 1 L: 1 3.685 ns 0.0186 ns 0.0174 ns 3.684 ns 3.656 ns 3.716 ns 1.01 0.01 0.0014 - - 24 B 27 B
Substring Job-WNUADI m I: 2 L: 2 5.554 ns 0.0214 ns 0.0189 ns 5.556 ns 5.522 ns 5.589 ns 1.00 0.00 0.0019 - - 32 B 864 B
Substring Job-WPCFEP pr I: 2 L: 2 5.375 ns 0.0403 ns 0.0377 ns 5.368 ns 5.322 ns 5.445 ns 0.97 0.01 0.0019 - - 32 B 483 B
NewString Job-WNUADI m I: 2 L: 2 3.842 ns 0.0142 ns 0.0133 ns 3.842 ns 3.815 ns 3.868 ns 1.00 0.00 0.0019 - - 32 B 27 B
NewString Job-WPCFEP pr I: 2 L: 2 3.871 ns 0.0179 ns 0.0168 ns 3.866 ns 3.848 ns 3.905 ns 1.01 0.01 0.0019 - - 32 B 27 B
Substring Job-WNUADI m I: 3 L: 3 5.708 ns 0.1507 ns 0.1736 ns 5.616 ns 5.568 ns 6.077 ns 1.00 0.00 0.0019 - - 32 B 864 B
Substring Job-WPCFEP pr I: 3 L: 3 5.395 ns 0.0215 ns 0.0179 ns 5.399 ns 5.346 ns 5.413 ns 0.94 0.03 0.0019 - - 32 B 483 B
NewString Job-WNUADI m I: 3 L: 3 3.859 ns 0.0231 ns 0.0205 ns 3.856 ns 3.835 ns 3.907 ns 1.00 0.00 0.0019 - - 32 B 27 B
NewString Job-WPCFEP pr I: 3 L: 3 3.820 ns 0.0243 ns 0.0227 ns 3.827 ns 3.787 ns 3.857 ns 0.99 0.01 0.0019 - - 32 B 27 B
Substring Job-WNUADI m I: 4 L: 4 5.352 ns 0.0226 ns 0.0176 ns 5.354 ns 5.314 ns 5.380 ns 1.00 0.00 0.0019 - - 32 B 864 B
Substring Job-WPCFEP pr I: 4 L: 4 13.276 ns 0.2797 ns 0.2872 ns 13.330 ns 12.226 ns 13.534 ns 2.47 0.06 0.0019 - - 32 B 483 B
NewString Job-WNUADI m I: 4 L: 4 3.825 ns 0.0109 ns 0.0102 ns 3.827 ns 3.807 ns 3.839 ns 1.00 0.00 0.0019 - - 32 B 27 B
NewString Job-WPCFEP pr I: 4 L: 4 3.815 ns 0.0236 ns 0.0221 ns 3.812 ns 3.791 ns 3.864 ns 1.00 0.01 0.0019 - - 32 B 27 B
Substring Job-WNUADI m I: 5 L: 5 5.334 ns 0.0321 ns 0.0300 ns 5.327 ns 5.295 ns 5.385 ns 1.00 0.00 0.0019 - - 32 B 864 B
Substring Job-WPCFEP pr I: 5 L: 5 5.618 ns 0.0410 ns 0.0343 ns 5.614 ns 5.566 ns 5.694 ns 1.05 0.01 0.0019 - - 32 B 483 B
NewString Job-WNUADI m I: 5 L: 5 3.813 ns 0.0179 ns 0.0168 ns 3.816 ns 3.786 ns 3.839 ns 1.00 0.00 0.0019 - - 32 B 27 B
NewString Job-WPCFEP pr I: 5 L: 5 3.801 ns 0.0241 ns 0.0213 ns 3.802 ns 3.771 ns 3.836 ns 1.00 0.01 0.0019 - - 32 B 27 B
Substring Job-WNUADI m I: 6 L: 6 5.492 ns 0.0333 ns 0.0311 ns 5.489 ns 5.447 ns 5.544 ns 1.00 0.00 0.0024 - - 40 B 864 B
Substring Job-WPCFEP pr I: 6 L: 6 5.679 ns 0.0306 ns 0.0286 ns 5.675 ns 5.640 ns 5.724 ns 1.03 0.01 0.0024 - - 40 B 483 B
NewString Job-WNUADI m I: 6 L: 6 3.986 ns 0.0096 ns 0.0090 ns 3.985 ns 3.970 ns 4.005 ns 1.00 0.00 0.0024 - - 40 B 27 B
NewString Job-WPCFEP pr I: 6 L: 6 3.958 ns 0.0164 ns 0.0146 ns 3.957 ns 3.939 ns 3.984 ns 0.99 0.00 0.0024 - - 40 B 27 B
Substring Job-WNUADI m I: 7 L: 7 5.511 ns 0.0220 ns 0.0205 ns 5.513 ns 5.476 ns 5.545 ns 1.00 0.00 0.0024 - - 40 B 864 B
Substring Job-WPCFEP pr I: 7 L: 7 5.702 ns 0.0298 ns 0.0279 ns 5.700 ns 5.645 ns 5.745 ns 1.03 0.01 0.0024 - - 40 B 483 B
NewString Job-WNUADI m I: 7 L: 7 3.853 ns 0.0175 ns 0.0164 ns 3.854 ns 3.825 ns 3.880 ns 1.00 0.00 0.0024 - - 40 B 27 B
NewString Job-WPCFEP pr I: 7 L: 7 3.988 ns 0.0207 ns 0.0184 ns 3.987 ns 3.962 ns 4.020 ns 1.04 0.01 0.0024 - - 40 B 27 B
Substring Job-WNUADI m I: 8 L: 8 5.491 ns 0.0296 ns 0.0277 ns 5.499 ns 5.449 ns 5.538 ns 1.00 0.00 0.0024 - - 40 B 864 B
Substring Job-WPCFEP pr I: 8 L: 8 5.680 ns 0.0358 ns 0.0335 ns 5.685 ns 5.623 ns 5.742 ns 1.03 0.01 0.0024 - - 40 B 483 B
NewString Job-WNUADI m I: 8 L: 8 4.015 ns 0.0120 ns 0.0112 ns 4.015 ns 3.986 ns 4.030 ns 1.00 0.00 0.0024 - - 40 B 27 B
NewString Job-WPCFEP pr I: 8 L: 8 3.971 ns 0.0296 ns 0.0277 ns 3.972 ns 3.929 ns 4.018 ns 0.99 0.01 0.0024 - - 40 B 27 B

ASM

M

; System.Tests.Perf_String_Substring_IntInt.Substring()
       sub       rsp,28
       mov       r8,[rcx+8]
       mov       rcx,1B31ACA8048
       mov       rcx,[rcx]
       mov       edx,[r8+8]
       mov       r8d,[r8+0C]
       call      System.String.Substring(Int32, Int32)
       nop
       add       rsp,28
       ret
; Total bytes of code 40
; System.String.Substring(Int32, Int32)
       push      rdi
       push      rsi
       push      rbx
       sub       rsp,20
       mov       rdi,rcx
       mov       esi,edx
       test      esi,esi
       jl        near ptr M01_L03
       mov       ebx,[rdi+8]
       cmp       ebx,esi
       jl        near ptr M01_L04
       test      r8d,r8d
       jl        near ptr M01_L05
       mov       ecx,ebx
       sub       ecx,r8d
       cmp       ecx,esi
       jl        near ptr M01_L06
       test      r8d,r8d
       je        short M01_L02
       test      esi,esi
       je        short M01_L01
M01_L00:
       mov       ecx,r8d
       call      System.String.FastAllocateString(Int32)
       mov       rbx,rax
       mov       r8d,[rbx+8]
       lea       rcx,[rbx+0C]
       add       rdi,0C
       mov       edx,esi
       lea       rdx,[rdi+rdx*2]
       add       r8,r8
       call      System.Buffer.Memmove(Byte ByRef, Byte ByRef, UIntPtr)
       mov       rax,rbx
       add       rsp,20
       pop       rbx
       pop       rsi
       pop       rdi
       ret
M01_L01:
       cmp       ebx,r8d
       jne       short M01_L00
       mov       rax,rdi
       add       rsp,20
       pop       rbx
       pop       rsi
       pop       rdi
       ret
M01_L02:
       mov       rax,1B31ACA3020
       mov       rax,[rax]
       add       rsp,20
       pop       rbx
       pop       rsi
       pop       rdi
       ret
M01_L03:
       mov       rcx,offset MT_System.ArgumentOutOfRangeException
       call      CORINFO_HELP_NEWSFAST
       mov       rsi,rax
       mov       ecx,19A4
       mov       rdx,7FF7DA114000
       call      CORINFO_HELP_STRCNS
       mov       rdi,rax
       mov       ecx,0A855
       mov       rdx,7FF7DA114000
       call      CORINFO_HELP_STRCNS
       mov       rcx,rax
       call      System.SR.GetResourceString(System.String)
       mov       r8,rax
       mov       rdx,rdi
       mov       rcx,rsi
       call      System.ArgumentOutOfRangeException..ctor(System.String, System.String)
       mov       rcx,rsi
       call      CORINFO_HELP_THROW
M01_L04:
       mov       rcx,offset MT_System.ArgumentOutOfRangeException
       call      CORINFO_HELP_NEWSFAST
       mov       rsi,rax
       mov       ecx,19A4
       mov       rdx,7FF7DA114000
       call      CORINFO_HELP_STRCNS
       mov       rdi,rax
       mov       ecx,0A891
       mov       rdx,7FF7DA114000
       call      CORINFO_HELP_STRCNS
       mov       rcx,rax
       call      System.SR.GetResourceString(System.String)
       mov       r8,rax
       mov       rdx,rdi
       mov       rcx,rsi
       call      System.ArgumentOutOfRangeException..ctor(System.String, System.String)
       mov       rcx,rsi
       call      CORINFO_HELP_THROW
M01_L05:
       mov       rcx,offset MT_System.ArgumentOutOfRangeException
       call      CORINFO_HELP_NEWSFAST
       mov       rsi,rax
       mov       ecx,57
       mov       rdx,7FF7DA114000
       call      CORINFO_HELP_STRCNS
       mov       rdi,rax
       mov       ecx,0A519
       mov       rdx,7FF7DA114000
       call      CORINFO_HELP_STRCNS
       mov       rcx,rax
       call      System.SR.GetResourceString(System.String)
       mov       r8,rax
       mov       rdx,rdi
       mov       rcx,rsi
       call      System.ArgumentOutOfRangeException..ctor(System.String, System.String)
       mov       rcx,rsi
       call      CORINFO_HELP_THROW
M01_L06:
       mov       rcx,offset MT_System.ArgumentOutOfRangeException
       call      CORINFO_HELP_NEWSFAST
       mov       rsi,rax
       mov       ecx,57
       mov       rdx,7FF7DA114000
       call      CORINFO_HELP_STRCNS
       mov       rdi,rax
       mov       ecx,9EBD
       mov       rdx,7FF7DA114000
       call      CORINFO_HELP_STRCNS
       mov       rcx,rax
       call      System.SR.GetResourceString(System.String)
       mov       r8,rax
       mov       rdx,rdi
       mov       rcx,rsi
       call      System.ArgumentOutOfRangeException..ctor(System.String, System.String)
       mov       rcx,rsi
       call      CORINFO_HELP_THROW
       int       3
; Total bytes of code 512

PR

; System.Tests.Perf_String_Substring_IntInt.Substring()
       sub       rsp,28
       mov       r8,[rcx+8]
       mov       rcx,1FA62268048
       mov       rcx,[rcx]
       mov       edx,[r8+8]
       mov       r8d,[r8+0C]
       call      System.String.Substring(Int32, Int32)
       nop
       add       rsp,28
       ret
; Total bytes of code 40
; System.String.Substring(Int32, Int32)
       push      rdi
       push      rsi
       push      rbx
       sub       rsp,20
       mov       rsi,rcx
       mov       edi,edx
       mov       ecx,[rsi+8]
       mov       eax,edi
       mov       edx,r8d
       add       rax,rdx
       mov       edx,ecx
       cmp       rax,rdx
       ja        short M01_L02
       test      r8d,r8d
       jne       short M01_L00
       mov       rax,1FA62263020
       mov       rax,[rax]
       add       rsp,20
       pop       rbx
       pop       rsi
       pop       rdi
       ret
M01_L00:
       cmp       r8d,ecx
       jne       short M01_L01
       mov       rax,rsi
       add       rsp,20
       pop       rbx
       pop       rsi
       pop       rdi
       ret
M01_L01:
       mov       ecx,r8d
       call      System.String.FastAllocateString(Int32)
       mov       rbx,rax
       mov       r8d,[rbx+8]
       lea       rcx,[rbx+0C]
       add       rsi,0C
       mov       edx,edi
       lea       rdx,[rsi+rdx*2]
       add       r8,r8
       call      System.Buffer.Memmove(Byte ByRef, Byte ByRef, UIntPtr)
       mov       rax,rbx
       add       rsp,20
       pop       rbx
       pop       rsi
       pop       rdi
       ret
M01_L02:
       mov       rcx,rsi
       mov       edx,edi
       call      System.String.ThrowSubstringArgumentOutRangeException(Int32, Int32)
       int       3
; Total bytes of code 131

@nietras
Copy link
Contributor Author

nietras commented Jan 25, 2022

@GrabYourPitchforks should I close this or?

@danmoseley
Copy link
Member

I'm going to close this as the improvements are as you say marginal. Thank you for the attempt!

@danmoseley danmoseley closed this May 2, 2022
@ghost ghost locked as resolved and limited conversation to collaborators Jun 1, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-System.Runtime community-contribution Indicates that the PR has been added by a community member tenet-performance Performance related issue
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants