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

Return ValueTask instead of Task for read/write APIs. #2953

Closed
wants to merge 8 commits into from

Conversation

habbes
Copy link
Contributor

@habbes habbes commented Apr 30, 2024

Issues

This pull request fixes #2816 .

Description

Refactor read/write APIs to return ValueTask instead of Task to improve performance and reduce allocations. This PR targets read and write APIs because those are buffered and may complete synchronously most of the time. This PR also only target the core library and not the client. This PR does not change all async APIs from Task to ValueTask, some APIs are intentional left as-is, for example in the following scenarios:

  • FlushAsync() methods still return Task. We don't expect FlushAsync() to complete synchronously because the method is intended to force the I/O operation.
  • Read/Write methods that override standard API methods that return Task (e.g. when inheriting from TextWriter).

Here are classes where I have made changes from Task to ValueTask. Let me know if I missed any:

  • IJsonWriter
  • IJsonReader
  • JsonWriter
  • ODataUtf8JsonWriter and its nested classes
  • ODataOutputContext
  • ODataMessageWriter
  • ODataInputContext
  • ...

TODO: refactor or remove the custom FollowOnSuccessWith and FollowAlwaysMethod and other TaskUtils helpers.

Removed ValidateBufferArguments from TranscodingWriteStream method because it's now inherited from Stream. We should also remove our the custom TranscodingWriteStream and replace it with the built-in one.

Benchmarks before

Method WriterName Mean Error StdDev Median Gen 0 Gen 1 Allocated
WriteToFileAsync JsonSerializer 26.83 ms 0.534 ms 0.799 ms 26.80 ms - - 3,289 B
WriteToFileAsync ODataMessageWriter 105.21 ms 2.639 ms 7.443 ms 103.41 ms 15800.0000 200.0000 68,851,538 B
WriteToFileAsync ODataMessageWriter-Async 176.06 ms 4.141 ms 11.679 ms 173.24 ms 20000.0000 1000.0000 86,382,176 B
WriteToFileAsync ODataMessageWriter-NoValidation 97.20 ms 2.647 ms 7.552 ms 95.41 ms 15000.0000 - 68,852,552 B
WriteToFileAsync ODataMessageWriter-NoValidation-Async 157.68 ms 3.124 ms 8.339 ms 155.84 ms 20000.0000 1000.0000 86,378,832 B
WriteToFileAsync ODataMessageWriter-Utf8JsonWriter 89.85 ms 1.151 ms 2.299 ms 89.27 ms 15000.0000 - 66,144,584 B
WriteToFileAsync ODataMessageWriter-Utf8JsonWriter-Async 139.12 ms 2.770 ms 7.345 ms 138.23 ms 15000.0000 - 66,516,616 B
WriteToFileAsync ODataMessageWriter-Utf8JsonWriter-NoValidation 82.96 ms 2.212 ms 6.417 ms 80.30 ms 15000.0000 - 66,141,240 B
WriteToFileAsync ODataMessageWriter-Utf8JsonWriter-NoValidation-Async 120.10 ms 2.370 ms 5.398 ms 118.73 ms 15000.0000 - 66,513,272 B
WriteToFileWithLargeValuesAsync JsonSerializer 305.32 ms 5.825 ms 7.574 ms 306.77 ms - - -
WriteToFileWithLargeValuesAsync ODataMessageWriter 400.29 ms 16.450 ms 47.984 ms 382.67 ms - - 239,168 B
WriteToFileWithLargeValuesAsync ODataMessageWriter-Async 1,250.57 ms 29.237 ms 84.356 ms 1,229.95 ms 490000.0000 - 2,113,979,832 B
WriteToFileWithLargeValuesAsync ODataMessageWriter-NoValidation 342.92 ms 7.624 ms 21.504 ms 337.85 ms - - 237,160 B
WriteToFileWithLargeValuesAsync ODataMessageWriter-NoValidation-Async 1,115.87 ms 17.410 ms 14.538 ms 1,113.62 ms 490000.0000 - 2,113,978,240 B
WriteToFileWithLargeValuesAsync ODataMessageWriter-Utf8JsonWriter 197.86 ms 4.726 ms 13.636 ms 196.58 ms - - 226,456 B
WriteToFileWithLargeValuesAsync ODataMessageWriter-Utf8JsonWriter-Async 264.63 ms 7.449 ms 21.372 ms 258.54 ms - - 2,096,688 B
WriteToFileWithLargeValuesAsync ODataMessageWriter-Utf8JsonWriter-NoValidation 206.98 ms 4.500 ms 13.126 ms 205.95 ms - - 224,784 B
WriteToFileWithLargeValuesAsync ODataMessageWriter-Utf8JsonWriter-NoValidation-Async 263.91 ms 6.069 ms 17.512 ms 264.12 ms - - 2,095,936 B
Method propertyType Mean Error StdDev Median Gen 0 Gen 1 Gen 2 Allocated
WriteFeed Entit(...)etSet [23] 87.97 ms 2.777 ms 8.011 ms 85.86 ms 4000.0000 - - 20.55 MB
WriteFeed EntityDecimalSet 91.31 ms 1.821 ms 5.016 ms 89.29 ms 4000.0000 - - 19.02 MB
WriteFeed EntityGuidSet 66.00 ms 1.285 ms 2.596 ms 65.04 ms 5000.0000 - - 22.07 MB
WriteFeed EntityInt32Set 59.73 ms 1.192 ms 2.435 ms 59.23 ms 3000.0000 - - 12.92 MB
WriteFeed EntityInt64Set 62.82 ms 1.251 ms 2.974 ms 61.54 ms 3000.0000 - - 15.97 MB
WriteFeed EntityMixedSet 49.27 ms 0.982 ms 0.767 ms 49.22 ms 2000.0000 - - 10.93 MB
WriteFeed EntityStringSet 62.84 ms 0.964 ms 0.805 ms 62.80 ms - - - 3.76 MB

Checklist (Uncheck if it is not completed)

  • Test cases added
  • Build and test with one-click build and test script passed

Additional work necessary

If documentation update is needed, please add "Docs Needed" label to the issue and provide details about the required document change in the issue.

@habbes habbes marked this pull request as draft April 30, 2024 14:54
@habbes
Copy link
Contributor Author

habbes commented May 22, 2024

Closing because I've picked up the work in a different PR: #2975

@habbes habbes closed this May 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant