Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

StringBuilder.Replace with ReadOnlySpan<char>#93938

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Conversation

@TheMaximum
Copy link
Contributor

Converted theStringBuilder.Replace(string, string, int, int) method and underlaying methods to takeReadOnlySpan<char> as arguments instead. TheReplace methods with string arguments are cast to spans (calling.AsSpan()) to use the same new method.

String-based tests still pass, as do the added ones for theReadOnlySpan<char> variants. Was looking to see if I can somehow benchmark the implementations, but I can't figure out how to run these against the self-built runtime.

Fix#77837

Converted the StringBuilder.Replace(string, string, int, int) methodand underlaying methods to take ReadOnlySpan<char> as argumentsinstead. The Replace methods with string arguments create spans to usethe same new method.Fixdotnet#77837
@ghost
Copy link

Note regarding thenew-api-needs-documentation label:

This serves as a reminder for when your PR is modifying a ref *.cs file and adding/modifying public APIs, please make sure the API implementation in the src *.cs file is documented with triple slash comments, so the PR reviewers can sign off that change.

@ghostghost added the community-contributionIndicates that the PR has been added by a community member labelOct 24, 2023
@ghost
Copy link

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

Issue Details

Converted theStringBuilder.Replace(string, string, int, int) method and underlaying methods to takeReadOnlySpan<char> as arguments instead. TheReplace methods with string arguments are cast to spans (calling.AsSpan()) to use the same new method.

String-based tests still pass, as do the added ones for theReadOnlySpan<char> variants. Was looking to see if I can somehow benchmark the implementations, but I can't figure out how to run these against the self-built runtime.

Fix#77837

Author:TheMaximum
Assignees:-
Labels:

area-System.Runtime,new-api-needs-documentation

Milestone:-

Moved null checks to the string-specific overloads, as spans won't benull. (PR feedback)
@danmoseley
Copy link
Member

Re benchmarking, there are docs in dotnet/performance repo that may help.

Fixed code-style failure and implemented further feedback.
@TheMaximum
Copy link
ContributorAuthor

TheMaximum commentedOct 25, 2023
edited
Loading

Re benchmarking, there are docs in dotnet/performance repo that may help.

I had found that documentation,@danmoseley, however when trying to run any benchmarks it kept complaining about SDK mismatches, which I wasn't able to solve for several days.Must admit that I now face a similar issue even building the solution as I synced the branch which now builds for the RTM version which is not publicly available (but this is a more recent issue)...

@danmoseley
Copy link
Member

OK, I don't work in this repo day to day any more, so@stephentoub may be more useful as he does this kind of benchmarking all the time.

Copy link
Member

@adamsitnikadamsitnik left a comment

Choose a reason for hiding this comment

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

The code LGTM, but it needs a little of polishing before it's approved. PTAL at my comments.

however when trying to run any benchmarks it kept complaining about SDK mismatches, which I wasn't able to solve for several days

You can use the python 3 script provided by the dotnet/performance repository. It's going to download the SDK for you and run the benchmarks:

git clone https://github.com/dotnet/performance.gitcd performancepython3 .\scripts\benchmarks_ci.py -f net8.0 --filter '*yourFilter*' --corerun $pathToCoreRunWithoutChanges $pathToCoreRunWithChanges

But one thing to keep in mind is that benchmarking new APIs is PITA. To make your life easier, you can simply benchmark the existing string-based overload:

publicStringBuilderReplace(stringoldValue,string?newValue,intstartIndex,intcount)

To do that you will need to add new benchmarks tohttps://github.com/dotnet/performance/blob/main/src/benchmarks/micro/libraries/System.Text/Perf.StringBuilder.cs as we currently don't have benchmarks for this particular overload.

If you can't run the benchmarks or simply don't have the time to do it, please let me know.

@TheMaximum thank you for your contribution!

@ghostghost added the needs-author-actionAn issue or pull request that requires more info or actions from the author. labelNov 3, 2023
@adamsitnikadamsitnik self-assigned thisNov 3, 2023
@ghostghost removed the needs-author-actionAn issue or pull request that requires more info or actions from the author. labelNov 3, 2023
Copy link
Member

@adamsitnikadamsitnik left a comment

Choose a reason for hiding this comment

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

It's almost ready 👍 Thank you@TheMaximum !

Copy link
Member

@adamsitnikadamsitnik left a comment

Choose a reason for hiding this comment

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

LGTM, thank you@TheMaximum !

TheMaximum reacted with thumbs up emoji
@TheMaximum
Copy link
ContributorAuthor

@adamsitnik, I've been able to run the benchmarks using the following command:

python3 .\scripts\benchmarks_ci.py -f net8.0 --filter '*StringBuilder*Replace*' --corerun "D:\dotnet\runtime-upstream\artifacts\bin\testhost\net9.0-windows-Release-x64\shared\Microsoft.NETCore.App\9.0.0\corerun.exe" "D:\dotnet\runtime\artifacts\bin\testhost\net9.0-windows-Release-x64\shared\Microsoft.NETCore.App\9.0.0\corerun.exe"

Created a benchmark as follows:

[Benchmark]publicStringBuilderReplace_Strings(){StringBuilderbuilder=newStringBuilder("initialvalue");builder.Replace("initial","new");builder.Replace("value","text");returnbuilder;}

The results are as follows below (runtime = with change /runtime-upstream = latest fromdotnet/runtime:main). Seems like the new implementation is slightly slower than the existing one - might this be caused by calling.AsSpan() or maybe it has something to do with the changed implementation of the main replace methods? The issue was mainly centered about improving memory/GC usage when usingReadOnlySpan<char> (avoiding the need to cast tostring).

I'm not 100% sure I'm reading this right, and also not sure if the benchmark is representative. Don't know if these results are satisfactory, or maybe you want to give some pointers (or run some yourself)? Not sure if these benchmarks are necessary either way (but wanted to attempt it anyway)...

MethodJobToolchainMeanErrorStdDevMedianMinMaxRatioRatioSDGen0AllocatedAlloc Ratio
Replace_StringsJob-IBBWUN\runtime-upstream\artifacts\bin\testhost\net9.0-windows-Release-x64\shared\Microsoft.NETCore.App\9.0.0\corerun.exe80.38 ns1.591 ns1.832 ns80.35 ns75.12 ns83.28 ns1.000.000.0082104 B1.00
Replace_StringsJob-GSLAPY\runtime\artifacts\bin\testhost\net9.0-windows-Release-x64\shared\Microsoft.NETCore.App\9.0.0\corerun.exe86.53 ns1.958 ns2.255 ns85.82 ns83.87 ns90.47 ns1.080.040.0080104 B1.00

A second run seems to produce similar results:

MethodJobToolchainMeanErrorStdDevMedianMinMaxRatioRatioSDGen0AllocatedAlloc Ratio
Replace_StringsJob-DXQHQN\runtime-upstream\artifacts\bin\testhost\net9.0-windows-Release-x64\shared\Microsoft.NETCore.App\9.0.0\corerun.exe83.43 ns2.414 ns2.780 ns83.89 ns78.26 ns88.03 ns1.000.000.0081104 B1.00
Replace_StringsJob-NOAKZW\runtime\artifacts\bin\testhost\net9.0-windows-Release-x64\shared\Microsoft.NETCore.App\9.0.0\corerun.exe89.14 ns2.242 ns2.582 ns89.48 ns83.64 ns92.88 ns1.070.050.0080104 B1.00

/// </remarks>
publicStringBuilderReplace(stringoldValue,string?newValue,intstartIndex,intcount)
{
ArgumentException.ThrowIfNullOrEmpty(oldValue);
Copy link
Member

Choose a reason for hiding this comment

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

This can just be ThrowIfNull. The called method has the check for empty.

Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

It would change the exception message (I think) in case it's an empty string (SR.Arg_EmptySpan instead ofSR.Argument_EmptyString), I don't know if that would be an issue? It might be confusing to the user who's using strings to get an exception message indicating an empty span?

Copy link
Member

@adamsitnikadamsitnik left a comment

Choose a reason for hiding this comment

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

not sure if the benchmark is representative

The benchmark you have provided creates a relatively smallStringBuilder that is internally backed by a single segment and performs two simple replace operations that do find the strings and replace them with shorter values.
It's OK, but we need more scenarios to be covered.

Ideally we would need:

Once we have that you can tell the python script to run the benchmarks more than once by adding--bdn-arguments "--launchCount 6 --memoryRandomization true". It will run every benchmark six times and try to apply some memory randomization (so the alignment of internal string builder buffer is different every time)

@TheMaximum
Copy link
ContributorAuthor

TheMaximum commentedNov 6, 2023
edited
Loading

@adamsitnik, I've attempted to create the (micro)benchmarks for the cases you've described:

[Benchmark][Arguments(100)][Arguments(LOHAllocatedStringSize)]publicStringBuilderReplace_Strings_Simple(intlength){StringBuilderbuilder=newStringBuilder(newstring('a',length));builder.Replace("a","b");returnbuilder;}[Benchmark][Arguments(100)][Arguments(LOHAllocatedStringSize)]publicStringBuilderReplace_Strings_NoReplace(intlength){StringBuilderbuilder=newStringBuilder(newstring('a',length));builder.Replace("b","test");returnbuilder;}[Benchmark][Arguments(100)][Arguments(LOHAllocatedStringSize)]publicStringBuilderReplace_Strings_ReplaceShorter(intlength){StringBuilderbuilder=newStringBuilder();builder.Insert(0,"ab",(length/2));builder.Replace("ab","a");returnbuilder;}[Benchmark][Arguments(100)][Arguments(LOHAllocatedStringSize)]publicStringBuilderReplace_Strings_ReplaceLonger(intlength){StringBuilderbuilder=newStringBuilder();builder.Insert(0,"ab",(length/2));builder.Replace("ab","zab");returnbuilder;}

I got the following results with executing them 6 times and applying memory randomization. To be honest, I'd like to leave the conclusions to you - as I'm not so sure I can make any myself (and I'm not 100% sure the benchmarks are correct)...

MethodJobToolchainlengthMeanErrorStdDevMedianMinMaxRatioRatioSDGen0Gen1Gen2AllocatedAlloc Ratio
Replace_Strings_SimpleJob-NLGUEL\runtime-upstream\artifacts\bin\testhost\net9.0-windows-Release-x64\shared\Microsoft.NETCore.App\9.0.0\corerun.exe1001,520.31 ns12.381 ns37.838 ns1,529.53 ns1,435.22 ns1,589.31 ns1.000.000.0368--496 B1.00
Replace_Strings_SimpleJob-HNVNGD\runtime\artifacts\bin\testhost\net9.0-windows-Release-x64\shared\Microsoft.NETCore.App\9.0.0\corerun.exe1001,526.04 ns11.463 ns35.377 ns1,533.88 ns1,443.38 ns1,611.74 ns1.000.030.0367--496 B1.00
Replace_Strings_NoReplaceJob-NLGUEL\runtime-upstream\artifacts\bin\testhost\net9.0-windows-Release-x64\shared\Microsoft.NETCore.App\9.0.0\corerun.exe10042.07 ns1.135 ns3.685 ns41.31 ns37.00 ns66.99 ns1.000.000.0395--496 B1.00
Replace_Strings_NoReplaceJob-HNVNGD\runtime\artifacts\bin\testhost\net9.0-windows-Release-x64\shared\Microsoft.NETCore.App\9.0.0\corerun.exe10041.06 ns0.412 ns1.226 ns40.91 ns38.17 ns47.19 ns0.980.080.0394--496 B1.00
Replace_Strings_ReplaceShorterJob-NLGUEL\runtime-upstream\artifacts\bin\testhost\net9.0-windows-Release-x64\shared\Microsoft.NETCore.App\9.0.0\corerun.exe100861.60 ns7.113 ns21.521 ns861.16 ns810.39 ns930.71 ns1.000.000.0296--376 B1.00
Replace_Strings_ReplaceShorterJob-HNVNGD\runtime\artifacts\bin\testhost\net9.0-windows-Release-x64\shared\Microsoft.NETCore.App\9.0.0\corerun.exe100860.98 ns13.823 ns43.479 ns858.90 ns785.76 ns1,129.19 ns1.000.060.0290--376 B1.00
Replace_Strings_ReplaceLongerJob-NLGUEL\runtime-upstream\artifacts\bin\testhost\net9.0-windows-Release-x64\shared\Microsoft.NETCore.App\9.0.0\corerun.exe100899.33 ns8.389 ns26.014 ns899.36 ns818.48 ns968.44 ns1.000.000.0438--552 B1.00
Replace_Strings_ReplaceLongerJob-HNVNGD\runtime\artifacts\bin\testhost\net9.0-windows-Release-x64\shared\Microsoft.NETCore.App\9.0.0\corerun.exe100887.16 ns7.845 ns23.131 ns894.88 ns816.92 ns928.70 ns0.990.040.0431--552 B1.00
Replace_Strings_SimpleJob-NLGUEL\runtime-upstream\artifacts\bin\testhost\net9.0-windows-Release-x64\shared\Microsoft.NETCore.App\9.0.0\corerun.exe1000001,561,129.26 ns9,994.000 ns28,513.445 ns1,562,408.75 ns1,497,733.24 ns1,633,194.32 ns1.000.00107.9545107.9545107.9545400168 B1.00
Replace_Strings_SimpleJob-HNVNGD\runtime\artifacts\bin\testhost\net9.0-windows-Release-x64\shared\Microsoft.NETCore.App\9.0.0\corerun.exe1000001,568,158.41 ns10,759.941 ns30,348.606 ns1,571,989.01 ns1,500,515.62 ns1,658,951.88 ns1.000.03107.9545107.9545107.9545400168 B1.00
Replace_Strings_NoReplaceJob-NLGUEL\runtime-upstream\artifacts\bin\testhost\net9.0-windows-Release-x64\shared\Microsoft.NETCore.App\9.0.0\corerun.exe100000128,536.19 ns435.035 ns1,212.703 ns128,243.42 ns126,064.13 ns132,801.07 ns1.000.00124.4919124.4919124.4919400138 B1.00
Replace_Strings_NoReplaceJob-HNVNGD\runtime\artifacts\bin\testhost\net9.0-windows-Release-x64\shared\Microsoft.NETCore.App\9.0.0\corerun.exe100000131,851.64 ns1,884.796 ns6,119.111 ns129,304.45 ns126,879.17 ns156,769.66 ns1.020.05124.4792124.4792124.4792400138 B1.00
Replace_Strings_ReplaceShorterJob-NLGUEL\runtime-upstream\artifacts\bin\testhost\net9.0-windows-Release-x64\shared\Microsoft.NETCore.App\9.0.0\corerun.exe100000892,371.89 ns7,697.059 ns23,983.806 ns888,522.04 ns833,729.93 ns968,752.34 ns1.000.0058.823558.823558.8235200218 B1.00
Replace_Strings_ReplaceShorterJob-HNVNGD\runtime\artifacts\bin\testhost\net9.0-windows-Release-x64\shared\Microsoft.NETCore.App\9.0.0\corerun.exe100000884,278.04 ns7,294.555 ns21,046.460 ns883,833.31 ns830,986.33 ns949,464.84 ns0.990.0459.027859.027859.0278200218 B1.00
Replace_Strings_ReplaceLongerJob-NLGUEL\runtime-upstream\artifacts\bin\testhost\net9.0-windows-Release-x64\shared\Microsoft.NETCore.App\9.0.0\corerun.exe100000851,331.92 ns8,929.931 ns27,692.793 ns852,993.96 ns790,693.26 ns973,410.76 ns1.000.0088.815888.815888.8158300310 B1.00
Replace_Strings_ReplaceLongerJob-HNVNGD\runtime\artifacts\bin\testhost\net9.0-windows-Release-x64\shared\Microsoft.NETCore.App\9.0.0\corerun.exe100000851,073.43 ns6,466.335 ns19,267.521 ns853,501.10 ns792,163.49 ns893,834.56 ns1.000.0488.235388.235388.2353300310 B1.00
Outliers  Perf_StringBuilder.Replace_Strings_NoReplace: PowerPlanMode=00000000-0000-0000-0000-000000000000, Arguments=/p:EnableUnsafeBinaryFormatterSerialization=true, Toolchain=\runtime-upstream\artifacts\bin\testhost\net9.0-windows-Release-x64\shared\Microsoft.NETCore.App\9.0.0\corerun.exe, IterationTime=250.0000 ms, LaunchCount=6, MaxIterationCount=20, MemoryRandomization=True, MinIterationCount=15, WarmupCount=1      -> 8 outliers were detected (50.65 ns..69.67 ns)  Perf_StringBuilder.Replace_Strings_NoReplace: PowerPlanMode=00000000-0000-0000-0000-000000000000, Arguments=/p:EnableUnsafeBinaryFormatterSerialization=true, Toolchain=\runtime\artifacts\bin\testhost\net9.0-windows-Release-x64\shared\Microsoft.NETCore.App\9.0.0\corerun.exe, IterationTime=250.0000 ms, LaunchCount=6, MaxIterationCount=20, MemoryRandomization=True, MinIterationCount=15, WarmupCount=1               -> 10 outliers were detected (40.61 ns..41.37 ns, 45.82 ns..49.91 ns)  Perf_StringBuilder.Replace_Strings_ReplaceShorter: PowerPlanMode=00000000-0000-0000-0000-000000000000, Arguments=/p:EnableUnsafeBinaryFormatterSerialization=true, Toolchain=\runtime-upstream\artifacts\bin\testhost\net9.0-windows-Release-x64\shared\Microsoft.NETCore.App\9.0.0\corerun.exe, IterationTime=250.0000 ms, LaunchCount=6, MaxIterationCount=20, MemoryRandomization=True, MinIterationCount=15, WarmupCount=1 -> 1 outlier  was  detected (933.40 ns)  Perf_StringBuilder.Replace_Strings_ReplaceShorter: PowerPlanMode=00000000-0000-0000-0000-000000000000, Arguments=/p:EnableUnsafeBinaryFormatterSerialization=true, Toolchain=\runtime\artifacts\bin\testhost\net9.0-windows-Release-x64\shared\Microsoft.NETCore.App\9.0.0\corerun.exe, IterationTime=250.0000 ms, LaunchCount=6, MaxIterationCount=20, MemoryRandomization=True, MinIterationCount=15, WarmupCount=1          -> 7 outliers were detected (788.58 ns..791.53 ns, 969.41 ns..1.13 us)  Perf_StringBuilder.Replace_Strings_ReplaceLonger: PowerPlanMode=00000000-0000-0000-0000-000000000000, Arguments=/p:EnableUnsafeBinaryFormatterSerialization=true, Toolchain=\runtime-upstream\artifacts\bin\testhost\net9.0-windows-Release-x64\shared\Microsoft.NETCore.App\9.0.0\corerun.exe, IterationTime=250.0000 ms, LaunchCount=6, MaxIterationCount=20, MemoryRandomization=True, MinIterationCount=15, WarmupCount=1  -> 3 outliers were detected (821.10 ns, 831.56 ns, 971.04 ns)  Perf_StringBuilder.Replace_Strings_ReplaceLonger: PowerPlanMode=00000000-0000-0000-0000-000000000000, Arguments=/p:EnableUnsafeBinaryFormatterSerialization=true, Toolchain=\runtime\artifacts\bin\testhost\net9.0-windows-Release-x64\shared\Microsoft.NETCore.App\9.0.0\corerun.exe, IterationTime=250.0000 ms, LaunchCount=6, MaxIterationCount=20, MemoryRandomization=True, MinIterationCount=15, WarmupCount=1           -> 4 outliers were detected (819.55 ns..831.17 ns)  Perf_StringBuilder.Replace_Strings_Simple: PowerPlanMode=00000000-0000-0000-0000-000000000000, Arguments=/p:EnableUnsafeBinaryFormatterSerialization=true, Toolchain=\runtime\artifacts\bin\testhost\net9.0-windows-Release-x64\shared\Microsoft.NETCore.App\9.0.0\corerun.exe, IterationTime=250.0000 ms, LaunchCount=6, MaxIterationCount=20, MemoryRandomization=True, MinIterationCount=15, WarmupCount=1                  -> 1 outlier  was  detected (1.66 ms)  Perf_StringBuilder.Replace_Strings_NoReplace: PowerPlanMode=00000000-0000-0000-0000-000000000000, Arguments=/p:EnableUnsafeBinaryFormatterSerialization=true, Toolchain=\runtime-upstream\artifacts\bin\testhost\net9.0-windows-Release-x64\shared\Microsoft.NETCore.App\9.0.0\corerun.exe, IterationTime=250.0000 ms, LaunchCount=6, MaxIterationCount=20, MemoryRandomization=True, MinIterationCount=15, WarmupCount=1      -> 8 outliers were detected (126.07 us, 130.91 us..132.80 us)  Perf_StringBuilder.Replace_Strings_NoReplace: PowerPlanMode=00000000-0000-0000-0000-000000000000, Arguments=/p:EnableUnsafeBinaryFormatterSerialization=true, Toolchain=\runtime\artifacts\bin\testhost\net9.0-windows-Release-x64\shared\Microsoft.NETCore.App\9.0.0\corerun.exe, IterationTime=250.0000 ms, LaunchCount=6, MaxIterationCount=20, MemoryRandomization=True, MinIterationCount=15, WarmupCount=1               -> 17 outliers were detected (138.14 us..156.77 us)  Perf_StringBuilder.Replace_Strings_ReplaceShorter: PowerPlanMode=00000000-0000-0000-0000-000000000000, Arguments=/p:EnableUnsafeBinaryFormatterSerialization=true, Toolchain=\runtime-upstream\artifacts\bin\testhost\net9.0-windows-Release-x64\shared\Microsoft.NETCore.App\9.0.0\corerun.exe, IterationTime=250.0000 ms, LaunchCount=6, MaxIterationCount=20, MemoryRandomization=True, MinIterationCount=15, WarmupCount=1 -> 2 outliers were detected (968.20 us, 968.76 us)  Perf_StringBuilder.Replace_Strings_ReplaceShorter: PowerPlanMode=00000000-0000-0000-0000-000000000000, Arguments=/p:EnableUnsafeBinaryFormatterSerialization=true, Toolchain=\runtime\artifacts\bin\testhost\net9.0-windows-Release-x64\shared\Microsoft.NETCore.App\9.0.0\corerun.exe, IterationTime=250.0000 ms, LaunchCount=6, MaxIterationCount=20, MemoryRandomization=True, MinIterationCount=15, WarmupCount=1          -> 15 outliers were detected (830.99 us..849.87 us, 916.17 us..949.47 us)  Perf_StringBuilder.Replace_Strings_ReplaceLonger: PowerPlanMode=00000000-0000-0000-0000-000000000000, Arguments=/p:EnableUnsafeBinaryFormatterSerialization=true, Toolchain=\runtime-upstream\artifacts\bin\testhost\net9.0-windows-Release-x64\shared\Microsoft.NETCore.App\9.0.0\corerun.exe, IterationTime=250.0000 ms, LaunchCount=6, MaxIterationCount=20, MemoryRandomization=True, MinIterationCount=15, WarmupCount=1  -> 19 outliers were detected (790.70 us..808.92 us, 895.26 us..973.41 us)  Perf_StringBuilder.Replace_Strings_ReplaceLonger: PowerPlanMode=00000000-0000-0000-0000-000000000000, Arguments=/p:EnableUnsafeBinaryFormatterSerialization=true, Toolchain=\runtime\artifacts\bin\testhost\net9.0-windows-Release-x64\shared\Microsoft.NETCore.App\9.0.0\corerun.exe, IterationTime=250.0000 ms, LaunchCount=6, MaxIterationCount=20, MemoryRandomization=True, MinIterationCount=15, WarmupCount=1           -> 8 outliers were detected (792.17 us..810.34 us, 893.84 us)

Copy link
Member

@adamsitnikadamsitnik left a comment

Choose a reason for hiding this comment

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

The benchmark numbers LGTM, thank you for sharing the results@TheMaximum !

I've found two places where we could improve the comments. I'll apply my suggestions and merge the PR. Thanks!

TheMaximum reacted with thumbs up emoji
…-replace-readonlyspan# Conflicts:#src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Text/StringBuilderReplaceTests.cs
Sign up for freeto subscribe to this conversation on GitHub. Already have an account?Sign in.

Reviewers

@stephentoubstephentoubstephentoub left review comments

@adamsitnikadamsitnikadamsitnik approved these changes

+1 more reviewer

@teo-tsirpanisteo-tsirpanisteo-tsirpanis left review comments

Reviewers whose approvals may not affect merge requirements

Assignees

@adamsitnikadamsitnik

Labels

area-System.Runtimecommunity-contributionIndicates that the PR has been added by a community membernew-api-needs-documentation

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

[API Proposal]: Stringbuilder.Replace(ROS oldValue, ROS newValue, int index, int count)

5 participants

@TheMaximum@danmoseley@stephentoub@adamsitnik@teo-tsirpanis

[8]ページ先頭

©2009-2025 Movatter.jp