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

JsonDocument Working PR #2

Open
wants to merge 54 commits into
base: master
Choose a base branch
from
Open

JsonDocument Working PR #2

wants to merge 54 commits into from

Conversation

bartonjs
Copy link
Owner

@bartonjs bartonjs commented Dec 6, 2018

Work-In-Progress PR for unified working branch commenting

@@ -13,6 +13,49 @@ public enum JsonCommentHandling : byte
Disallow = (byte)0,
Skip = (byte)2,
}
public sealed partial class JsonDocument : System.IDisposable

Choose a reason for hiding this comment

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

Is it going to be strange for folks to need to dispose an XxDocument? Is that required for other XxDocument in the framework? Is it required for any other JSON document-like types in other JSON libraries?

Copy link
Owner Author

Choose a reason for hiding this comment

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

Usually the DOM APIs aren't IDisposable, but they have readers that are. So "no, but nearly". It seems like a natural consequence of the performance goals.

If it's "too strange for the surface area" then the next option that I see is to use generic List; the consequence of not disposing in the current model being that the document "stole" the array from the pool rather than rented it.


int tokenStart = Unsafe.ByteOffset(
ref jsonStart,
ref MemoryMarshal.GetReference(reader.ValueSpan)).ToInt32();
Copy link

@stephentoub stephentoub Dec 9, 2018

Choose a reason for hiding this comment

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

Utf8JsonReader doesn't provide this information? If not, is that a flaw in the Utf8JsonReader API, that JsonDocument needs to resort to such tactics to get data Utf8JsonReader doesn't provide?

Copy link

@ahsonkhan ahsonkhan Dec 10, 2018

Choose a reason for hiding this comment

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

The prototype JsonReader (as implemented in corefxlab) had an internal "token start" field which tracked this. This was removed when we moved to corefx since (along with "inArray") since we didn't have a JsonDocument. We could consider adding it back.

https://github.com/dotnet/corefxlab/blob/1c45ad21e3312507a085d2a91f1725e88b9c72bc/src/System.Text.JsonLab/System/Text/Json/JsonUtf8Reader.cs#L30

arrayItemsCount = row.SizeOrLength;
numberOfRowsForValues += row.NumberOfRows;
}
else if (tokenType == JsonTokenType.PropertyName)

Choose a reason for hiding this comment

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

Are these ordered from most common to least common? Since the further you get here the more checks you need to do as part of parsing, it might be interesting to gather some stats on frequency on common documents and order accordingly. Or maybe it doesn't matter.

{
if (_parent == null)
{
throw new InvalidOperationException();

Choose a reason for hiding this comment

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

Do we gain anything perf-wise if we were to move this out with the ThrowHelper pattern?

Also, I assume error messages will be added later?

Copy link
Owner Author

Choose a reason for hiding this comment

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

I moved all of these checks "am I default(JsonElement)?" to a helper CheckValidInstance, and all of the disposed checks in JsonDocument to CheckNotDisposed and all of the "am I the right type?" checks in JsonDocument to CheckExpectedType... and the performance is either unchanged or worse. (within overlapping sigmas, but the "after" had a higher mean when the JsonObject baseline got a lower mean).

But I guess those changes are fine, especially if you think we want to be more helpful on "don't call members on the default JsonElement" case by using a non-default string.

Or maybe I don't understand what the actual ThrowHelper pattern is.

Choose a reason for hiding this comment

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

Did you try a throw helper after adding a message string? @benaadams previously saw a benefit (at least in asm) here: dotnet/corefxlab#2366 (comment)

Also, from @AndyAyersMS,
dotnet#33216 (comment)

Methods that conditionally throw exceptions on some paths can still be inlined, as can methods with complex flow where every path ultimately throws.

Simple methods that unconditionally throw won't be inlined w/o AggressiveInlining.

The benefits of the throw helper pattern are that it can save code size if the same exception can be thrown from multiple places within a method or across multiple methods, and that it also may reduce some of the time and space overhead the throwing path may impose on non-throwing paths in a method (say the method prolog).

Using a throw helper for just one site in one method may not provide any benefit -- you'd have to look at the non-exceptional codegen paths with and without a helper to see.

Run the ParseJson tests for all the entrypoints.
Some caching, test perf fixes, and some test case reduction took a 23 second run down to 7.
bartonjs pushed a commit that referenced this pull request Aug 20, 2019
* Json prototype (#1)

Basic API for Json writable DOM with scenarios including collection initialization, accessing and modifying Json nodes.

* Json prototype - transformation API  (#2)

* transformation API added
* assertions to existing scenarios added

* Json prototype (#1)

Basic API for Json writable DOM with scenarios including collection initialization, accessing and modifying Json nodes.

* Json prototype - transformation API  (#2)

* transformation API added
* assertions to existing scenarios added

* JsonNumber implementation and tests (dotnet#3)

* IEquatables added
* JsonNumber implementation and unit tests added
* pragmas deleted
* review comments included, more tests added
* decimal support added to JsonNumber
* decimal support added to JsonArray and JsonObject

* all unimplemented classes and methods with accompanying tests removed

* First part of documentation added

* documentation completed

* missing exceptions added

* JsonElement changes removed

* part of the review comments included

* work on review comments

* code refactor

* more decimal tests added using MemberData

* more decimal tests added using MemberData

* more test cases added

* equals summary adjusted, equals tests added

* more Equals tests added, GetHashCode tests added, minor changes

* scientifing notation support added, rational numbers tests fixes

* rational overflow tests added

* ulong maxvalue tests added to rational types

* presision problems fixes

* exception strings fixed

* CI failing fixes (hopefully), review comments included

* missing == tests added to achieve 100% branch coverage

* review comments included

* trailing whitespaces fixes

* equals comments added

* equals object refactored to call quals json number

* merge fix
bartonjs pushed a commit that referenced this pull request Sep 18, 2019
This is attempt #2. The first attempt was commit
176da26.

Initialize HostArch to the arch-style used in RIDs directly by
converting things to lowercase.

Use the HostArch for the tool runtime instead of assuming x64.
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.

3 participants