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

Split JsonWriter into UTF-8 and UTF-16 specific types.#2292

Merged
ahsonkhan merged 5 commits into
dotnet:masterfrom
ahsonkhan:SplitUtf8Utf16JsonWriter
May 16, 2018
Merged

Split JsonWriter into UTF-8 and UTF-16 specific types.#2292
ahsonkhan merged 5 commits into
dotnet:masterfrom
ahsonkhan:SplitUtf8Utf16JsonWriter

Conversation

@ahsonkhan
Copy link
Copy Markdown
Contributor

@ahsonkhan ahsonkhan commented May 16, 2018

[WIP] Changes are on top of #2291, and hence need to be re-based first, before review.

This improves performance by 20-50% for some cases (small json payloads).

Focus only on the following commit, while reviewing: b220180

  • Split the JsonWriter into JsonWriterUtf8 and JsonWriterUtf16 types.
  • The JsonWriter no longer supports ITextBufferWriter (now supports IBufferWriter instead). Removed the SymbolTable and the "Slow" (non-invariant) encoding paths.
  • Fixed a bug in prettyPrint bytesNeeded calculation for WriteObject/ArrayStart (to account for white space), which was ported back to Optimized the JsonWriter APIs and expanded the unit test. #2291.
  • Added prettyPrint = true/false tests for both UTF-8 and UTF-16
BenchmarkDotNet=v0.10.14.534-nightly, OS=Windows 10.0.16299.431 (1709/FallCreatorsUpdate/Redstone3)
Intel Xeon CPU E5-1620 v2 3.70GHz, 1 CPU, 8 logical and 4 physical cores
Frequency=3604598 Hz, Resolution=277.4234 ns, Timer=TSC
.NET Core SDK=2.1.300-rtm-008838
  [Host]     : .NET Core 2.1.0-rtm-26514-02 (CoreCLR 4.6.26514.02, CoreFX 4.6.26514.02), 64bit RyuJIT
  DefaultJob : .NET Core 2.1.0-rtm-26514-02 (CoreCLR 4.6.26514.02, CoreFX 4.6.26514.02), 64bit RyuJIT

Method Target Formatted Mean Error StdDev Gen 0 Allocated
WriterSystemTextJsonBasic InvariantUtf16 False 14,072.96 ns 259.4878 ns 254.8517 ns - 0 B
WriterNewtonsoftBasic InvariantUtf16 False 17,213.43 ns 337.5822 ns 401.8676 ns 0.0610 416 B
WriterSystemTextJsonHelloWorld InvariantUtf16 False 97.62 ns 1.8345 ns 1.7160 ns - 0 B
WriterNewtonsoftHelloWorld InvariantUtf16 False 290.87 ns 1.5428 ns 1.3677 ns 0.0486 256 B
WriterSystemTextJsonBasic InvariantUtf16 True 17,008.83 ns 119.0800 ns 78.7641 ns - 0 B
WriterNewtonsoftBasic InvariantUtf16 True 31,596.69 ns 87.0094 ns 81.3886 ns 0.0610 584 B
WriterSystemTextJsonHelloWorld InvariantUtf16 True 103.20 ns 0.5058 ns 0.4223 ns - 0 B
WriterNewtonsoftHelloWorld InvariantUtf16 True 389.65 ns 5.6618 ns 4.7278 ns 0.0806 424 B
WriterSystemTextJsonBasic InvariantUtf8 False 14,463.19 ns 31.6241 ns 24.6900 ns - 0 B
WriterNewtonsoftBasic InvariantUtf8 False 17,268.86 ns 75.3866 ns 58.8569 ns 0.0610 416 B
WriterSystemTextJsonHelloWorld InvariantUtf8 False 161.86 ns 2.8533 ns 2.6690 ns - 0 B
WriterNewtonsoftHelloWorld InvariantUtf8 False 287.88 ns 0.9145 ns 0.6612 ns 0.0486 256 B
WriterSystemTextJsonBasic InvariantUtf8 True 15,764.73 ns 71.1455 ns 63.0686 ns - 0 B
WriterNewtonsoftBasic InvariantUtf8 True 32,678.38 ns 204.6518 ns 147.9767 ns 0.0610 584 B
WriterSystemTextJsonHelloWorld InvariantUtf8 True 166.55 ns 1.0146 ns 0.7336 ns - 0 B
WriterNewtonsoftHelloWorld InvariantUtf8 True 389.79 ns 4.3153 ns 3.8254 ns 0.0806 424 B

{
_arrayFormatter.Clear();
WriterSystemTextJsonBasic(Formatted, _arrayFormatter);
if (Target == EncoderTarget.InvariantUtf8)
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@adamsitnik, please review the changes in JsonWriterPerf.cs.

Is there a way for me to avoid adding this if check? It doesn't have much impact on the end result, though.

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.

The extra branch should not impact this particular benchmark (it's not a nano-benchmark).

To avoid this check you would have to remove EncoderTarget param and write a benchmark method per case

Copy link
Copy Markdown
Member

@adamsitnik adamsitnik 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 changes look good to me! 👍

{
_arrayFormatter.Clear();
WriterSystemTextJsonBasic(Formatted, _arrayFormatter);
if (Target == EncoderTarget.InvariantUtf8)
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.

The extra branch should not impact this particular benchmark (it's not a nano-benchmark).

To avoid this check you would have to remove EncoderTarget param and write a benchmark method per case

@Tornhoof
Copy link
Copy Markdown
Contributor

May I suggest looking into moving the pretty print part out of the writing methods?

  • If someone starts pretty printing, performance is probably not the issue anymore
  • Both SpanJson and Utf8Json have a "post-processor" pretty printer, which reads the normal output an reformat it prettily.
  • It might be possible to have the same pretty print code for all supported encodings.

@ahsonkhan
Copy link
Copy Markdown
Contributor Author

ahsonkhan commented May 16, 2018

May I suggest looking into moving the pretty print part out of the writing methods?

How would that work for writing to a stream, etc.? We can't have a post-processor, if we are sending the bytes as we write them. Given the fact that the pretty print version has relatively low cost, it might not be worth it (looking at the delta between Formatted = false vs true). Still, I will file an issue because that is an interesting optimization we can investigate. If you are interested in giving it a shot, go for it :)

We need to expand the Writer Perf tests to include more variety of json writing scenarios (similar to the JsonReader, for instance heavy nesting, where pretty print might end up costing a lot more).

#2295

@ahsonkhan ahsonkhan changed the title [WIP] Split JsonWriter into UTF-8 and UTF-16 specific types. Split JsonWriter into UTF-8 and UTF-16 specific types. May 16, 2018
@ahsonkhan ahsonkhan merged commit c50d0e7 into dotnet:master May 16, 2018
@ahsonkhan ahsonkhan deleted the SplitUtf8Utf16JsonWriter branch May 16, 2018 22:34
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.

3 participants