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

Single line pretty-printing options #20

Merged
merged 7 commits into from
Apr 11, 2024

Conversation

veqryn
Copy link
Contributor

@veqryn veqryn commented Nov 2, 2023

Discussion:
In the same vein as the WithIndent and WithIndentPrefix formatting options, I would really like the option to make json pretty but on a single line.
I end up reading, or at least skimming, through a lot of new-line delimited json, and this would make my life better 100%.

Consider reading the following:

{"foo": "bar", "baz": 123, "qux": {"quux": "corge"}, "grault": {"garply": ["waldo", "fred"]}, "thud": "plugh"}
{"foo":"bar", "baz":123, "qux":{"quux":"corge"}, "grault":{"garply":["waldo", "fred"]}, "thud":"plugh"}
{"foo":"bar","baz":123,"qux":{"quux":"corge"},"grault":{"garply":["waldo","fred"]},"thud":"plugh"}

The first two are much easier to see the key-value pairs and the elements than the third one, which is the only option right now.

golang/go#63397 (comment)

PR Details:
This PR adds two new boolean flag options: SpaceAfterColon and SpaceAfterComma
I do like those to be separate options, as I prefer to have the space after comma but not after colon, while lots of other people like space after both.
I'm not married to the naming or the implementation, and am open to any suggestions.
Please let me know if I need to add any additional tests beyond the two I added.

@@ -274,6 +274,7 @@ func (e *encoderState) UnwriteEmptyObjectMember(prevName *string) bool {
b = b[:len(b)-n]
b = jsonwire.TrimSuffixWhitespace(b)
b = jsonwire.TrimSuffixByte(b, ':')
b = jsonwire.TrimSuffixWhitespace(b)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

i think this is needed, but am not really sure about this section of code or why it worked previously without it even on multiline/expanded json.

@dsnet
Copy link
Collaborator

dsnet commented Nov 2, 2023

Thanks for the PR.

I apologize for being a stickler for legal rules. Since the goal of this is intended to merge into the Go toolchain, we'll need every contribution to have also signed the Go CLA. Is there a merged commit in any of the Go repositories that you can point to that proves you've signed the CLA? Thanks!

High-level thought: Modifying MayAppendDelim likely makes it such that it is no longer inlineable. We don't want to slow down the case where whitespace is completely elided. I'd like to see benchmarks of the performance delta of compacted output.

@veqryn
Copy link
Contributor Author

veqryn commented Nov 3, 2023

Of course. I have signed the Go CLA. Here is my most recent contribution, though small:
golang/go@65c53a1
https://go-review.googlesource.com/c/go/+/524618

@veqryn
Copy link
Contributor Author

veqryn commented Nov 3, 2023

I am also curious on how it may affect performance. Do you want me to run benchmarks, and do those benchmarks already exist? Or is this something you'd like to do to keep consistency with previous runs?

@veqryn
Copy link
Contributor Author

veqryn commented Nov 8, 2023

Ran some benchmarks, comparing against master.
These runs are on a M1 macbook.

$ go env
GO111MODULE=''
GOARCH='arm64'
GOBIN=''
GOCACHE='/Users/x/Library/Caches/go-build'
GOENV='/Users/x/Library/Application Support/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='arm64'
GOHOSTOS='darwin'
GOINSECURE=''
GOMODCACHE='/Users/x/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='darwin'
GOPATH='/Users/cduncan/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/opt/homebrew/opt/go/libexec'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/opt/homebrew/opt/go/libexec/pkg/tool/darwin_arm64'
GOVCS=''
GOVERSION='go1.21.4'
GCCGO='gccgo'
AR='ar'
CC='cc'
CXX='c++'
CGO_ENABLED='1'
GOMOD='/dev/null'
GOWORK=''
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS='-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -ffile-prefix-map=/var/folders/jx/04vrv3h53d72ylmj73g8r8lc0000gn/T/go-build682745689=/tmp/go-build -gno-record-gcc-switches -fno-common'

Master:

BenchmarkMarshal
BenchmarkMarshal/Bool
BenchmarkMarshal/Bool-10         	17499763	        68.53 ns/op	  58.37 MB/s	       8 B/op	       1 allocs/op
BenchmarkMarshal/String
BenchmarkMarshal/String-10       	16208367	        73.79 ns/op	 203.27 MB/s	      16 B/op	       1 allocs/op
BenchmarkMarshal/Int
BenchmarkMarshal/Int-10          	17451297	        68.37 ns/op	  73.14 MB/s	       8 B/op	       1 allocs/op
BenchmarkMarshal/Uint
BenchmarkMarshal/Uint-10         	17472674	        68.26 ns/op	  58.60 MB/s	       8 B/op	       1 allocs/op
BenchmarkMarshal/Float
BenchmarkMarshal/Float-10        	11057541	       107.5 ns/op	  46.53 MB/s	       8 B/op	       1 allocs/op
BenchmarkMarshal/Map/ManyEmpty
BenchmarkMarshal/Map/ManyEmpty-10         	  769255	      1566 ns/op	 192.16 MB/s	     320 B/op	       1 allocs/op
BenchmarkMarshal/Map/OneLarge
BenchmarkMarshal/Map/OneLarge-10          	  635246	      1877 ns/op	 111.37 MB/s	     384 B/op	       4 allocs/op
BenchmarkMarshal/Map/ManySmall
BenchmarkMarshal/Map/ManySmall-10         	  177566	      6728 ns/op	  54.25 MB/s	    4697 B/op	      82 allocs/op
BenchmarkMarshal/Struct/ManyEmpty
BenchmarkMarshal/Struct/ManyEmpty-10      	  475663	      2532 ns/op	 118.86 MB/s	     320 B/op	       1 allocs/op
BenchmarkMarshal/Struct/OneLarge
BenchmarkMarshal/Struct/OneLarge-10       	 1435818	       835.9 ns/op	 250.04 MB/s	     224 B/op	       1 allocs/op
BenchmarkMarshal/Struct/ManySmall
BenchmarkMarshal/Struct/ManySmall-10      	  635452	      1892 ns/op	 192.90 MB/s	     384 B/op	       1 allocs/op
BenchmarkMarshal/Slice/ManyEmpty
BenchmarkMarshal/Slice/ManyEmpty-10       	 1485180	       796.3 ns/op	 378.01 MB/s	     320 B/op	       1 allocs/op
BenchmarkMarshal/Slice/OneLarge
BenchmarkMarshal/Slice/OneLarge-10        	 2681997	       446.9 ns/op	 234.94 MB/s	     112 B/op	       1 allocs/op
BenchmarkMarshal/Slice/ManySmall
BenchmarkMarshal/Slice/ManySmall-10       	 1233034	       962.5 ns/op	 163.11 MB/s	     160 B/op	       1 allocs/op
BenchmarkMarshal/Array/OneLarge
BenchmarkMarshal/Array/OneLarge-10        	 2692856	       449.6 ns/op	 233.55 MB/s	     112 B/op	       1 allocs/op
BenchmarkMarshal/Array/ManySmall
BenchmarkMarshal/Array/ManySmall-10       	 1332310	       899.0 ns/op	 174.64 MB/s	     160 B/op	       1 allocs/op
BenchmarkMarshal/Bytes/Slice
BenchmarkMarshal/Bytes/Slice-10           	 8157802	       147.0 ns/op	 312.87 MB/s	     112 B/op	       2 allocs/op
BenchmarkMarshal/Bytes/Array
BenchmarkMarshal/Bytes/Array-10           	 8151314	       149.2 ns/op	 308.39 MB/s	     112 B/op	       2 allocs/op
BenchmarkMarshal/Pointer
BenchmarkMarshal/Pointer-10               	 7415541	       161.8 ns/op	  24.73 MB/s	       8 B/op	       1 allocs/op
BenchmarkMarshal/TextArshal
BenchmarkMarshal/TextArshal-10            	13136809	        90.71 ns/op	  88.20 MB/s	      16 B/op	       2 allocs/op
BenchmarkMarshal/JSONArshalV1
BenchmarkMarshal/JSONArshalV1-10          	13365788	        89.04 ns/op	  89.84 MB/s	      16 B/op	       2 allocs/op
BenchmarkMarshal/JSONArshalV2
BenchmarkMarshal/JSONArshalV2-10          	13210863	        90.46 ns/op	  88.44 MB/s	       8 B/op	       1 allocs/op
BenchmarkMarshal/Duration
BenchmarkMarshal/Duration-10              	12109178	        98.77 ns/op	  80.99 MB/s	      16 B/op	       2 allocs/op
BenchmarkMarshal/Time
BenchmarkMarshal/Time-10                  	11445398	       104.4 ns/op	 210.63 MB/s	      24 B/op	       1 allocs/op

BenchmarkTextValue
BenchmarkTextValue/IsValid
BenchmarkTextValue/IsValid-10         	     902	   1216821 ns/op	1419.44 MB/s	   23065 B/op	     213 allocs/op
BenchmarkTextValue/Compact
BenchmarkTextValue/Compact-10         	    1080	   1106798 ns/op	1560.54 MB/s	       1 B/op	       0 allocs/op
BenchmarkTextValue/Compact/Noop
BenchmarkTextValue/Compact/Noop-10    	    1815	    655949 ns/op	2633.14 MB/s	    1399 B/op	       0 allocs/op
BenchmarkTextValue/Indent
BenchmarkTextValue/Indent-10          	     648	   1839437 ns/op	 938.98 MB/s	       1 B/op	       0 allocs/op
BenchmarkTextValue/Indent/Noop
BenchmarkTextValue/Indent/Noop-10     	     642	   1849534 ns/op	 933.86 MB/s	       2 B/op	       0 allocs/op
BenchmarkTextValue/Indent#01
BenchmarkTextValue/Indent#01-10       	     394	   3027398 ns/op	 570.52 MB/s	   29646 B/op	     212 allocs/op
BenchmarkTextValue/Indent/Noop#01
BenchmarkTextValue/Indent/Noop#01-10  	     460	   2598857 ns/op	 664.60 MB/s	   28752 B/op	     212 allocs/op
BenchmarkTextValue/Canonicalize
BenchmarkTextValue/Canonicalize-10    	     393	   3034790 ns/op	 569.13 MB/s	   29717 B/op	     212 allocs/op
BenchmarkTextValue/Canonicalize/Noop
BenchmarkTextValue/Canonicalize/Noop-10         	     460	   2594072 ns/op	 665.83 MB/s	   28764 B/op	     212 allocs/op

Single line pretty printing PR:

BenchmarkMarshal
BenchmarkMarshal/Bool
BenchmarkMarshal/Bool-10         	15141565	        69.03 ns/op	  57.95 MB/s	       8 B/op	       1 allocs/op
BenchmarkMarshal/String
BenchmarkMarshal/String-10       	15740070	        75.42 ns/op	 198.90 MB/s	      16 B/op	       1 allocs/op
BenchmarkMarshal/Int
BenchmarkMarshal/Int-10          	17256627	        68.17 ns/op	  73.34 MB/s	       8 B/op	       1 allocs/op
BenchmarkMarshal/Uint
BenchmarkMarshal/Uint-10         	17343348	        68.25 ns/op	  58.61 MB/s	       8 B/op	       1 allocs/op
BenchmarkMarshal/Float
BenchmarkMarshal/Float-10        	11074166	       107.2 ns/op	  46.64 MB/s	       8 B/op	       1 allocs/op
BenchmarkMarshal/Map/ManyEmpty
BenchmarkMarshal/Map/ManyEmpty-10         	  669688	      1753 ns/op	 171.72 MB/s	     320 B/op	       1 allocs/op
BenchmarkMarshal/Map/OneLarge
BenchmarkMarshal/Map/OneLarge-10          	  606732	      1950 ns/op	 107.19 MB/s	     384 B/op	       4 allocs/op
BenchmarkMarshal/Map/ManySmall
BenchmarkMarshal/Map/ManySmall-10         	  174262	      6799 ns/op	  53.68 MB/s	    4697 B/op	      82 allocs/op
BenchmarkMarshal/Struct/ManyEmpty
BenchmarkMarshal/Struct/ManyEmpty-10      	  458298	      2619 ns/op	 114.91 MB/s	     320 B/op	       1 allocs/op
BenchmarkMarshal/Struct/OneLarge
BenchmarkMarshal/Struct/OneLarge-10       	 1331934	       899.9 ns/op	 232.25 MB/s	     224 B/op	       1 allocs/op
BenchmarkMarshal/Struct/ManySmall
BenchmarkMarshal/Struct/ManySmall-10      	  608961	      1962 ns/op	 186.06 MB/s	     384 B/op	       1 allocs/op
BenchmarkMarshal/Slice/ManyEmpty
BenchmarkMarshal/Slice/ManyEmpty-10       	 1433493	       826.3 ns/op	 364.27 MB/s	     320 B/op	       1 allocs/op
BenchmarkMarshal/Slice/OneLarge
BenchmarkMarshal/Slice/OneLarge-10        	 2447815	       489.7 ns/op	 214.43 MB/s	     112 B/op	       1 allocs/op
BenchmarkMarshal/Slice/ManySmall
BenchmarkMarshal/Slice/ManySmall-10       	 1000000	      1040 ns/op	 150.99 MB/s	     160 B/op	       1 allocs/op
BenchmarkMarshal/Array/OneLarge
BenchmarkMarshal/Array/OneLarge-10        	 2460807	       487.5 ns/op	 215.37 MB/s	     112 B/op	       1 allocs/op
BenchmarkMarshal/Array/ManySmall
BenchmarkMarshal/Array/ManySmall-10       	 1251490	       959.1 ns/op	 163.69 MB/s	     160 B/op	       1 allocs/op
BenchmarkMarshal/Bytes/Slice
BenchmarkMarshal/Bytes/Slice-10           	 8173449	       147.6 ns/op	 311.74 MB/s	     112 B/op	       2 allocs/op
BenchmarkMarshal/Bytes/Array
BenchmarkMarshal/Bytes/Array-10           	 8078925	       149.3 ns/op	 308.14 MB/s	     112 B/op	       2 allocs/op
BenchmarkMarshal/Pointer
BenchmarkMarshal/Pointer-10               	 7258795	       163.2 ns/op	  24.50 MB/s	       8 B/op	       1 allocs/op
BenchmarkMarshal/TextArshal
BenchmarkMarshal/TextArshal-10            	12987001	        91.84 ns/op	  87.10 MB/s	      16 B/op	       2 allocs/op
BenchmarkMarshal/JSONArshalV1
BenchmarkMarshal/JSONArshalV1-10          	13303111	        89.76 ns/op	  89.13 MB/s	      16 B/op	       2 allocs/op
BenchmarkMarshal/JSONArshalV2
BenchmarkMarshal/JSONArshalV2-10          	13645311	        87.32 ns/op	  91.61 MB/s	       8 B/op	       1 allocs/op
BenchmarkMarshal/Duration
BenchmarkMarshal/Duration-10              	12055948	        98.91 ns/op	  80.88 MB/s	      16 B/op	       2 allocs/op
BenchmarkMarshal/Time
BenchmarkMarshal/Time-10                  	11438097	       104.7 ns/op	 210.15 MB/s	      24 B/op	       1 allocs/op

BenchmarkTextValue
BenchmarkTextValue/IsValid
BenchmarkTextValue/IsValid-10         	     918	   1216074 ns/op	1420.31 MB/s	   23072 B/op	     213 allocs/op
BenchmarkTextValue/Compact
BenchmarkTextValue/Compact-10         	    1072	   1114277 ns/op	1550.07 MB/s	    2369 B/op	       0 allocs/op
BenchmarkTextValue/Compact/Noop
BenchmarkTextValue/Compact/Noop-10    	    1754	    671224 ns/op	2573.22 MB/s	    1448 B/op	       0 allocs/op
BenchmarkTextValue/Indent
BenchmarkTextValue/Indent-10          	     648	   1873448 ns/op	 921.94 MB/s	   16348 B/op	       0 allocs/op
BenchmarkTextValue/Indent/Noop
BenchmarkTextValue/Indent/Noop-10     	     642	   1874352 ns/op	 921.49 MB/s	       2 B/op	       0 allocs/op
BenchmarkTextValue/Indent#01
BenchmarkTextValue/Indent#01-10       	     393	   3045207 ns/op	 567.19 MB/s	   23165 B/op	     212 allocs/op
BenchmarkTextValue/Indent/Noop#01
BenchmarkTextValue/Indent/Noop#01-10  	     460	   2593190 ns/op	 666.05 MB/s	   28766 B/op	     212 allocs/op
BenchmarkTextValue/Canonicalize
BenchmarkTextValue/Canonicalize-10    	     393	   3037923 ns/op	 568.55 MB/s	   29628 B/op	     212 allocs/op
BenchmarkTextValue/Canonicalize/Noop
BenchmarkTextValue/Canonicalize/Noop-10         	     460	   2591278 ns/op	 666.55 MB/s	   23077 B/op	     212 allocs/op

Comparison between master and this pr:

0.7% slower		BenchmarkMarshal/Bool
2.2% slower		BenchmarkMarshal/String
0.3% faster		BenchmarkMarshal/Int
0.0% faster		BenchmarkMarshal/Uint
0.3% faster		BenchmarkMarshal/Float
10.0% slower		BenchmarkMarshal/Map/ManyEmpty
3.7% slower		BenchmarkMarshal/Map/OneLarge
1.0% slower		BenchmarkMarshal/Map/ManySmall
3.3% slower		BenchmarkMarshal/Struct/ManyEmpty
7.1% slower		BenchmarkMarshal/Struct/OneLarge
3.6% slower		BenchmarkMarshal/Struct/ManySmall
3.6% slower		BenchmarkMarshal/Slice/ManyEmpty
8.7% slower		BenchmarkMarshal/Slice/OneLarge
7.5% slower		BenchmarkMarshal/Slice/ManySmall
7.8% slower		BenchmarkMarshal/Array/OneLarge
6.3% slower		BenchmarkMarshal/Array/ManySmall
0.4% slower		BenchmarkMarshal/Bytes/Slice
0.0% faster		BenchmarkMarshal/Bytes/Array
0.9% slower		BenchmarkMarshal/Pointer
1.2% slower		BenchmarkMarshal/TextArshal
0.8% slower		BenchmarkMarshal/JSONArshalV1
3.6% faster		BenchmarkMarshal/JSONArshalV2
0.1% slower		BenchmarkMarshal/Duration
0.2% slower		BenchmarkMarshal/Time

0.0% faster		BenchmarkTextValue/IsValid
0.6% slower		BenchmarkTextValue/Compact
2.3% slower		BenchmarkTextValue/Compact/Noop
1.8% slower		BenchmarkTextValue/Indent
1.3% slower		BenchmarkTextValue/Indent/Noop
0.6% slower		BenchmarkTextValue/Indent#01
0.2% faster		BenchmarkTextValue/Indent/Noop#01
0.1% slower		BenchmarkTextValue/Canonicalize
0.1% faster		BenchmarkTextValue/Canonicalize/Noop

@dsnet What do you think?

@dsnet
Copy link
Collaborator

dsnet commented Nov 8, 2023

Thanks for running the benchmarks, but up to 10% slowdown is a fairly non-trivial performance detriment. Especially since the benchmarks are intended to exercise the performance Go reflection, not the syntactic processor.

@dsnet
Copy link
Collaborator

dsnet commented Nov 9, 2023

If you're okay with it, I can take a stab at implementing this.

@veqryn
Copy link
Contributor Author

veqryn commented Nov 9, 2023

Ok. So here is what I plan to change, please let me know what you think:

  • Move the extra space out of MayAppendDelim
  • Move the extra space into WriteToken
  • In all the "optimized" paths like this:
			if optimizeCommon && !xe.Flags.Get(jsonflags.Expand) && !xe.Tokens.Last.NeedObjectName() {
				xe.Buf = append(xe.Tokens.MayAppendDelim(xe.Buf, '{', xe.Flags.Get(jsonflags.SpaceAfterColon), xe.Flags.Get(jsonflags.SpaceAfterComma)), "{}"...)

I will either add && !xe.Flags.Get(jsonflags.SpaceAfterColon) && !xe.Flags.Get(jsonflags.SpaceAfterComma)
or I will have both those flags and jsonflags.Expand flag all set some fourth flag for avoiding optimization, so that we only have to check 1 flag for these paths.

@veqryn
Copy link
Contributor Author

veqryn commented Nov 9, 2023

I'm ok if you want to take a stab. I'd probably prefer to collaborate so I can learn from you (including if we want to throw all of this out and start over, with different flags, etc), but am ok with anything.

@dsnet
Copy link
Collaborator

dsnet commented Nov 9, 2023

Feel free to keep working on it. Your idea is similar to what I had in mind. Essentially, we want to change nothing about the old code path if Expand&SpaceAfterColon&SpaceAfterComma are all false.

You can probably do something like:

package jsonflags

// AnyWhitespace reports whether the encoded output might have any whitespace.
const AnyWhitespace = SpaceAfterColon | SpaceAfterComma | Expand
package json

if optimizeCommon && !xe.Flags.Get(jsonflags.AnyWhitespace) && !xe.Tokens.Last.NeedObjectName() {
    ...
}

I believe this should work since jsonflags.Flags.Get is semantically equivalent to reporting whether any of the bits are set, which allows us to check all three flags in a single operation.

We might want to rename Expand to Multiline, since Expand is an ambiguous option now with the introduction of expansion within a single line.

@dsnet
Copy link
Collaborator

dsnet commented Nov 9, 2023

We also probably want to have the semantic that use of Multiline or Indent or IndentPrefix implies SpaceAfterColon if not already set.

@dsnet
Copy link
Collaborator

dsnet commented Nov 9, 2023

Also for benchmarks, you probably want to run these instead:

go test -run=- -bench="Testdata//(Marshal|Encode)/"

@veqryn
Copy link
Contributor Author

veqryn commented Nov 9, 2023

Master:

BenchmarkMarshal/Bool-10 	17468782	        68.35 ns/op	  58.52 MB/s	       8 B/op	       1 allocs/op
BenchmarkMarshal/String-10         	16201582	        73.64 ns/op	 203.70 MB/s	      16 B/op	       1 allocs/op
BenchmarkMarshal/Int-10            	17379528	        68.38 ns/op	  73.12 MB/s	       8 B/op	       1 allocs/op
BenchmarkMarshal/Uint-10           	17042438	        68.85 ns/op	  58.10 MB/s	       8 B/op	       1 allocs/op
BenchmarkMarshal/Float-10          	11098650	       107.5 ns/op	  46.50 MB/s	       8 B/op	       1 allocs/op
BenchmarkMarshal/Map/ManyEmpty-10  	  767757	      1564 ns/op	 192.41 MB/s	     320 B/op	       1 allocs/op
BenchmarkMarshal/Map/OneLarge-10   	  626533	      1895 ns/op	 110.29 MB/s	     384 B/op	       4 allocs/op
BenchmarkMarshal/Map/ManySmall-10  	  174926	      6757 ns/op	  54.02 MB/s	    4697 B/op	      82 allocs/op
BenchmarkMarshal/Struct/ManyEmpty-10         	  476367	      2557 ns/op	 117.73 MB/s	     320 B/op	       1 allocs/op
BenchmarkMarshal/Struct/OneLarge-10          	 1440249	       832.4 ns/op	 251.09 MB/s	     224 B/op	       1 allocs/op
BenchmarkMarshal/Struct/ManySmall-10         	  634903	      1877 ns/op	 194.43 MB/s	     384 B/op	       1 allocs/op
BenchmarkMarshal/Slice/ManyEmpty-10          	 1481580	       796.4 ns/op	 377.97 MB/s	     320 B/op	       1 allocs/op
BenchmarkMarshal/Slice/OneLarge-10           	 2679693	       447.2 ns/op	 234.77 MB/s	     112 B/op	       1 allocs/op
BenchmarkMarshal/Slice/ManySmall-10          	 1246032	       961.9 ns/op	 163.22 MB/s	     160 B/op	       1 allocs/op
BenchmarkMarshal/Array/OneLarge-10           	 2691718	       445.1 ns/op	 235.90 MB/s	     112 B/op	       1 allocs/op
BenchmarkMarshal/Array/ManySmall-10          	 1313089	       904.8 ns/op	 173.52 MB/s	     160 B/op	       1 allocs/op
BenchmarkMarshal/Bytes/Slice-10              	 8135280	       148.0 ns/op	 310.91 MB/s	     112 B/op	       2 allocs/op
BenchmarkMarshal/Bytes/Array-10              	 8096805	       149.4 ns/op	 307.93 MB/s	     112 B/op	       2 allocs/op
BenchmarkMarshal/Pointer-10                  	 7230853	       164.8 ns/op	  24.27 MB/s	       8 B/op	       1 allocs/op
BenchmarkMarshal/TextArshal-10               	13068982	        91.06 ns/op	  87.86 MB/s	      16 B/op	       2 allocs/op
BenchmarkMarshal/JSONArshalV1-10             	13155099	        90.63 ns/op	  88.27 MB/s	      16 B/op	       2 allocs/op
BenchmarkMarshal/JSONArshalV2-10             	13515478	        87.46 ns/op	  91.47 MB/s	       8 B/op	       1 allocs/op
BenchmarkMarshal/Duration-10                 	12179206	        97.91 ns/op	  81.71 MB/s	      16 B/op	       2 allocs/op
BenchmarkMarshal/Time-10                     	11404070	       104.9 ns/op	 209.81 MB/s	      24 B/op	       1 allocs/op
BenchmarkTextValue/IsValid-10                	     981	   1217373 ns/op	1418.80 MB/s	   23071 B/op	     213 allocs/op
BenchmarkTextValue/Compact-10                	    1083	   1106176 ns/op	1561.42 MB/s	    2345 B/op	       0 allocs/op
BenchmarkTextValue/Compact/Noop-10           	    1814	    653127 ns/op	2644.52 MB/s	       0 B/op	       0 allocs/op
BenchmarkTextValue/Indent-10                 	     648	   1834621 ns/op	 941.45 MB/s	       1 B/op	       0 allocs/op
BenchmarkTextValue/Indent/Noop-10            	     645	   1848691 ns/op	 934.28 MB/s	       1 B/op	       0 allocs/op
BenchmarkTextValue/Canonicalize-10           	     393	   3037866 ns/op	 568.56 MB/s	   29613 B/op	     212 allocs/op
BenchmarkTextValue/Canonicalize/Noop-10      	     462	   2592450 ns/op	 666.24 MB/s	   23071 B/op	     212 allocs/op
BenchmarkTestdata/CanadaGeometry/Marshal/Concrete-10         	     981	   1171681 ns/op	 230.78 MB/s	  278646 B/op	       1 allocs/op
BenchmarkTestdata/CanadaGeometry/Marshal/Interface-10        	     946	   1258706 ns/op	 214.83 MB/s	  278682 B/op	       2 allocs/op
BenchmarkTestdata/CanadaGeometry/Encode/Token/Streaming-10   	    1036	   1150617 ns/op	 235.01 MB/s	    9416 B/op	      38 allocs/op
BenchmarkTestdata/CanadaGeometry/Encode/Token/Buffered-10    	    1042	   1145659 ns/op	 236.02 MB/s	    1192 B/op	      26 allocs/op
BenchmarkTestdata/CanadaGeometry/Encode/Value/Streaming-10   	    2500	    465955 ns/op	 580.32 MB/s	 1187561 B/op	      46 allocs/op
BenchmarkTestdata/CanadaGeometry/Encode/Value/Buffered-10    	    3492	    342796 ns/op	 788.82 MB/s	    1024 B/op	      20 allocs/op
BenchmarkTestdata/CitmCatalog/Marshal/Concrete-10            	    1138	   1045570 ns/op	1651.93 MB/s	  511155 B/op	     133 allocs/op
BenchmarkTestdata/CitmCatalog/Marshal/Interface-10           	     645	   1839433 ns/op	 938.99 MB/s	  508006 B/op	       2 allocs/op
BenchmarkTestdata/CitmCatalog/Encode/Token/Streaming-10      	     686	   1740098 ns/op	 992.59 MB/s	   36116 B/op	     271 allocs/op
BenchmarkTestdata/CitmCatalog/Encode/Token/Buffered-10       	     694	   1721999 ns/op	1003.02 MB/s	   27823 B/op	     258 allocs/op
BenchmarkTestdata/CitmCatalog/Encode/Value/Streaming-10      	     724	   1638241 ns/op	1054.30 MB/s	 2564896 B/op	     271 allocs/op
BenchmarkTestdata/CitmCatalog/Encode/Value/Buffered-10       	     824	   1448067 ns/op	1192.76 MB/s	   26660 B/op	     241 allocs/op
BenchmarkTestdata/GolangSource/Marshal/Concrete-10           	     307	   3904894 ns/op	 496.93 MB/s	 1941727 B/op	       1 allocs/op
BenchmarkTestdata/GolangSource/Marshal/Interface-10          	     193	   6155516 ns/op	 315.24 MB/s	 1941700 B/op	       2 allocs/op
BenchmarkTestdata/GolangSource/Encode/Token/Streaming-10     	     183	   6505386 ns/op	 298.29 MB/s	   17776 B/op	     168 allocs/op
BenchmarkTestdata/GolangSource/Encode/Token/Buffered-10      	     186	   6448351 ns/op	 300.93 MB/s	    9344 B/op	     153 allocs/op
BenchmarkTestdata/GolangSource/Encode/Value/Streaming-10     	     282	   4234603 ns/op	 458.24 MB/s	10599377 B/op	     189 allocs/op
BenchmarkTestdata/GolangSource/Encode/Value/Buffered-10      	     337	   3550961 ns/op	 546.46 MB/s	    8408 B/op	     153 allocs/op
BenchmarkTestdata/StringEscaped/Marshal/Concrete-10          	   50049	     24098 ns/op	1745.42 MB/s	   18438 B/op	       1 allocs/op
BenchmarkTestdata/StringEscaped/Marshal/Interface-10         	   40562	     29717 ns/op	1415.43 MB/s	   18449 B/op	       2 allocs/op
BenchmarkTestdata/StringEscaped/Encode/Token/Streaming-10    	   37190	     32134 ns/op	1308.97 MB/s	   12624 B/op	      29 allocs/op
BenchmarkTestdata/StringEscaped/Encode/Token/Buffered-10     	   38908	     30716 ns/op	1369.38 MB/s	    4080 B/op	      19 allocs/op
BenchmarkTestdata/StringEscaped/Encode/Value/Streaming-10    	    4125	    286689 ns/op	 146.72 MB/s	  151016 B/op	     216 allocs/op
BenchmarkTestdata/StringEscaped/Encode/Value/Buffered-10     	    4305	    278973 ns/op	 150.77 MB/s	   67632 B/op	     201 allocs/op
BenchmarkTestdata/StringUnicode/Marshal/Concrete-10          	   49994	     24071 ns/op	 752.92 MB/s	   18438 B/op	       1 allocs/op
BenchmarkTestdata/StringUnicode/Marshal/Interface-10         	   40437	     29758 ns/op	 609.05 MB/s	   18447 B/op	       2 allocs/op
BenchmarkTestdata/StringUnicode/Encode/Token/Streaming-10    	   37274	     32188 ns/op	 563.07 MB/s	   12624 B/op	      29 allocs/op
BenchmarkTestdata/StringUnicode/Encode/Token/Buffered-10     	   38970	     30717 ns/op	 590.04 MB/s	    4080 B/op	      19 allocs/op
BenchmarkTestdata/StringUnicode/Encode/Value/Streaming-10    	   33397	     35745 ns/op	 507.04 MB/s	   87456 B/op	      33 allocs/op
BenchmarkTestdata/StringUnicode/Encode/Value/Buffered-10     	   42044	     28522 ns/op	 635.43 MB/s	    4072 B/op	      18 allocs/op
BenchmarkTestdata/SyntheaFhir/Marshal/Concrete-10            	     178	   6686264 ns/op	 300.39 MB/s	 3141766 B/op	    2569 allocs/op
BenchmarkTestdata/SyntheaFhir/Marshal/Interface-10           	     405	   2936731 ns/op	 683.92 MB/s	 1146993 B/op	       2 allocs/op
BenchmarkTestdata/SyntheaFhir/Encode/Token/Streaming-10      	     470	   2538261 ns/op	 791.29 MB/s	   11832 B/op	      77 allocs/op
BenchmarkTestdata/SyntheaFhir/Encode/Token/Buffered-10       	     480	   2495617 ns/op	 804.81 MB/s	    3528 B/op	      63 allocs/op
BenchmarkTestdata/SyntheaFhir/Encode/Value/Streaming-10      	     434	   2736869 ns/op	 733.87 MB/s	 6646266 B/op	      95 allocs/op
BenchmarkTestdata/SyntheaFhir/Encode/Value/Buffered-10       	     543	   2219020 ns/op	 905.13 MB/s	    3840 B/op	      61 allocs/op
BenchmarkTestdata/TwitterStatus/Marshal/Concrete-10          	    1587	    743084 ns/op	 849.86 MB/s	  501913 B/op	      59 allocs/op
BenchmarkTestdata/TwitterStatus/Marshal/Interface-10         	    1170	   1016499 ns/op	 621.26 MB/s	  467015 B/op	       2 allocs/op
BenchmarkTestdata/TwitterStatus/Encode/Token/Streaming-10    	    1075	   1111981 ns/op	 567.92 MB/s	   17464 B/op	      94 allocs/op
BenchmarkTestdata/TwitterStatus/Encode/Token/Buffered-10     	    1096	   1090856 ns/op	 578.92 MB/s	    9808 B/op	      81 allocs/op
BenchmarkTestdata/TwitterStatus/Encode/Value/Streaming-10    	    1023	   1156195 ns/op	 546.20 MB/s	 2551920 B/op	     119 allocs/op
BenchmarkTestdata/TwitterStatus/Encode/Value/Buffered-10     	    1233	    968893 ns/op	 651.79 MB/s	   13112 B/op	      89 allocs/op

This PR:

BenchmarkMarshal/Bool-10 	15258075	        67.49 ns/op	  59.26 MB/s	       8 B/op	       1 allocs/op
BenchmarkMarshal/String-10         	16305501	        73.41 ns/op	 204.34 MB/s	      16 B/op	       1 allocs/op
BenchmarkMarshal/Int-10            	17270784	        70.04 ns/op	  71.39 MB/s	       8 B/op	       1 allocs/op
BenchmarkMarshal/Uint-10           	17452978	        68.22 ns/op	  58.64 MB/s	       8 B/op	       1 allocs/op
BenchmarkMarshal/Float-10          	10972519	       108.5 ns/op	  46.10 MB/s	       8 B/op	       1 allocs/op
BenchmarkMarshal/Map/ManyEmpty-10  	  738729	      1627 ns/op	 185.03 MB/s	     320 B/op	       1 allocs/op
BenchmarkMarshal/Map/OneLarge-10   	  635596	      1867 ns/op	 111.97 MB/s	     384 B/op	       4 allocs/op
BenchmarkMarshal/Map/ManySmall-10  	  176860	      6677 ns/op	  54.67 MB/s	    4697 B/op	      82 allocs/op
BenchmarkMarshal/Struct/ManyEmpty-10         	  447837	      2711 ns/op	 111.04 MB/s	     320 B/op	       1 allocs/op
BenchmarkMarshal/Struct/OneLarge-10          	 1396676	       862.1 ns/op	 242.44 MB/s	     224 B/op	       1 allocs/op
BenchmarkMarshal/Struct/ManySmall-10         	  625180	      1918 ns/op	 190.26 MB/s	     384 B/op	       1 allocs/op
BenchmarkMarshal/Slice/ManyEmpty-10          	 1448064	       833.4 ns/op	 361.15 MB/s	     320 B/op	       1 allocs/op
BenchmarkMarshal/Slice/OneLarge-10           	 2511039	       479.5 ns/op	 218.99 MB/s	     112 B/op	       1 allocs/op
BenchmarkMarshal/Slice/ManySmall-10          	 1000000	      1019 ns/op	 154.01 MB/s	     160 B/op	       1 allocs/op
BenchmarkMarshal/Array/OneLarge-10           	 2686700	       445.5 ns/op	 235.71 MB/s	     112 B/op	       1 allocs/op
BenchmarkMarshal/Array/ManySmall-10          	 1327821	       903.9 ns/op	 173.69 MB/s	     160 B/op	       1 allocs/op
BenchmarkMarshal/Bytes/Slice-10              	 8212627	       146.3 ns/op	 314.47 MB/s	     112 B/op	       2 allocs/op
BenchmarkMarshal/Bytes/Array-10              	 8089743	       147.9 ns/op	 311.04 MB/s	     112 B/op	       2 allocs/op
BenchmarkMarshal/Pointer-10                  	 7419316	       160.4 ns/op	  24.94 MB/s	       8 B/op	       1 allocs/op
BenchmarkMarshal/TextArshal-10               	13062153	        91.14 ns/op	  87.78 MB/s	      16 B/op	       2 allocs/op
BenchmarkMarshal/JSONArshalV1-10             	13446426	        88.40 ns/op	  90.50 MB/s	      16 B/op	       2 allocs/op
BenchmarkMarshal/JSONArshalV2-10             	13279116	        90.40 ns/op	  88.49 MB/s	       8 B/op	       1 allocs/op
BenchmarkMarshal/Duration-10                 	12004356	        99.55 ns/op	  80.37 MB/s	      16 B/op	       2 allocs/op
BenchmarkMarshal/Time-10                     	11433212	       104.3 ns/op	 210.88 MB/s	      24 B/op	       1 allocs/op
BenchmarkTextValue/IsValid-10                	     979	   1216533 ns/op	1419.78 MB/s	   23075 B/op	     213 allocs/op
BenchmarkTextValue/Compact-10                	    1071	   1096822 ns/op	1574.73 MB/s	       1 B/op	       0 allocs/op
BenchmarkTextValue/Compact/Noop-10           	    1801	    660279 ns/op	2615.87 MB/s	       0 B/op	       0 allocs/op
BenchmarkTextValue/Indent-10                 	     645	   1848907 ns/op	 934.18 MB/s	       1 B/op	       0 allocs/op
BenchmarkTextValue/Indent/Noop-10            	     636	   1874258 ns/op	 921.54 MB/s	       2 B/op	       0 allocs/op
BenchmarkTextValue/Canonicalize-10           	     394	   3024818 ns/op	 571.01 MB/s	   29674 B/op	     212 allocs/op
BenchmarkTextValue/Canonicalize/Noop-10      	     460	   2592809 ns/op	 666.15 MB/s	   23054 B/op	     212 allocs/op
BenchmarkTestdata/CanadaGeometry/Marshal/Concrete-10         	     942	   1173041 ns/op	 230.51 MB/s	  279907 B/op	       1 allocs/op
BenchmarkTestdata/CanadaGeometry/Marshal/Interface-10        	     940	   1268764 ns/op	 213.12 MB/s	  278682 B/op	       2 allocs/op
BenchmarkTestdata/CanadaGeometry/Encode/Token/Streaming-10   	    1034	   1153147 ns/op	 234.49 MB/s	    9416 B/op	      38 allocs/op
BenchmarkTestdata/CanadaGeometry/Encode/Token/Buffered-10    	    1040	   1150103 ns/op	 235.11 MB/s	    1192 B/op	      26 allocs/op
BenchmarkTestdata/CanadaGeometry/Encode/Value/Streaming-10   	    2407	    471761 ns/op	 573.18 MB/s	 1187561 B/op	      46 allocs/op
BenchmarkTestdata/CanadaGeometry/Encode/Value/Buffered-10    	    3458	    346602 ns/op	 780.15 MB/s	    1024 B/op	      20 allocs/op
BenchmarkTestdata/CitmCatalog/Marshal/Concrete-10            	    1104	   1082243 ns/op	1595.95 MB/s	  513456 B/op	     133 allocs/op
BenchmarkTestdata/CitmCatalog/Marshal/Interface-10           	     642	   1851416 ns/op	 932.91 MB/s	  508000 B/op	       2 allocs/op
BenchmarkTestdata/CitmCatalog/Encode/Token/Streaming-10      	     684	   1745665 ns/op	 989.42 MB/s	   36109 B/op	     271 allocs/op
BenchmarkTestdata/CitmCatalog/Encode/Token/Buffered-10       	     691	   1729951 ns/op	 998.41 MB/s	   27813 B/op	     258 allocs/op
BenchmarkTestdata/CitmCatalog/Encode/Value/Streaming-10      	     717	   1655998 ns/op	1043.00 MB/s	 2564897 B/op	     271 allocs/op
BenchmarkTestdata/CitmCatalog/Encode/Value/Buffered-10       	     819	   1458285 ns/op	1184.41 MB/s	   26637 B/op	     241 allocs/op
BenchmarkTestdata/GolangSource/Marshal/Concrete-10           	     298	   4016621 ns/op	 483.11 MB/s	 2012869 B/op	       1 allocs/op
BenchmarkTestdata/GolangSource/Marshal/Interface-10          	     193	   6178584 ns/op	 314.06 MB/s	 1996611 B/op	       2 allocs/op
BenchmarkTestdata/GolangSource/Encode/Token/Streaming-10     	     182	   6550348 ns/op	 296.24 MB/s	   17776 B/op	     168 allocs/op
BenchmarkTestdata/GolangSource/Encode/Token/Buffered-10      	     184	   6475840 ns/op	 299.65 MB/s	    9344 B/op	     153 allocs/op
BenchmarkTestdata/GolangSource/Encode/Value/Streaming-10     	     278	   4267457 ns/op	 454.71 MB/s	10599377 B/op	     189 allocs/op
BenchmarkTestdata/GolangSource/Encode/Value/Buffered-10      	     333	   3589382 ns/op	 540.61 MB/s	    8408 B/op	     153 allocs/op
BenchmarkTestdata/StringEscaped/Marshal/Concrete-10          	   49074	     24113 ns/op	1744.39 MB/s	   18436 B/op	       1 allocs/op
BenchmarkTestdata/StringEscaped/Marshal/Interface-10         	   40398	     29844 ns/op	1409.42 MB/s	   18449 B/op	       2 allocs/op
BenchmarkTestdata/StringEscaped/Encode/Token/Streaming-10    	   37183	     32241 ns/op	1304.59 MB/s	   12624 B/op	      29 allocs/op
BenchmarkTestdata/StringEscaped/Encode/Token/Buffered-10     	   38955	     30725 ns/op	1368.97 MB/s	    4080 B/op	      19 allocs/op
BenchmarkTestdata/StringEscaped/Encode/Value/Streaming-10    	    4106	    289498 ns/op	 145.29 MB/s	  151016 B/op	     216 allocs/op
BenchmarkTestdata/StringEscaped/Encode/Value/Buffered-10     	    4256	    281495 ns/op	 149.42 MB/s	   67632 B/op	     201 allocs/op
BenchmarkTestdata/StringUnicode/Marshal/Concrete-10          	   49807	     24134 ns/op	 750.96 MB/s	   18436 B/op	       1 allocs/op
BenchmarkTestdata/StringUnicode/Marshal/Interface-10         	   40480	     29812 ns/op	 607.95 MB/s	   18449 B/op	       2 allocs/op
BenchmarkTestdata/StringUnicode/Encode/Token/Streaming-10    	   35911	     32421 ns/op	 559.02 MB/s	   12624 B/op	      29 allocs/op
BenchmarkTestdata/StringUnicode/Encode/Token/Buffered-10     	   38827	     30860 ns/op	 587.30 MB/s	    4080 B/op	      19 allocs/op
BenchmarkTestdata/StringUnicode/Encode/Value/Streaming-10    	   32996	     36130 ns/op	 501.63 MB/s	   87456 B/op	      33 allocs/op
BenchmarkTestdata/StringUnicode/Encode/Value/Buffered-10     	   41947	     28643 ns/op	 632.75 MB/s	    4072 B/op	      18 allocs/op
BenchmarkTestdata/SyntheaFhir/Marshal/Concrete-10            	     174	   6829914 ns/op	 294.07 MB/s	 3141771 B/op	    2569 allocs/op
BenchmarkTestdata/SyntheaFhir/Marshal/Interface-10           	     404	   2942877 ns/op	 682.49 MB/s	 1146976 B/op	       2 allocs/op
BenchmarkTestdata/SyntheaFhir/Encode/Token/Streaming-10      	     465	   2569125 ns/op	 781.78 MB/s	   11832 B/op	      77 allocs/op
BenchmarkTestdata/SyntheaFhir/Encode/Token/Buffered-10       	     474	   2523400 ns/op	 795.95 MB/s	    3528 B/op	      63 allocs/op
BenchmarkTestdata/SyntheaFhir/Encode/Value/Streaming-10      	     433	   2758368 ns/op	 728.15 MB/s	 6646266 B/op	      95 allocs/op
BenchmarkTestdata/SyntheaFhir/Encode/Value/Buffered-10       	     537	   2225622 ns/op	 902.44 MB/s	    3840 B/op	      61 allocs/op
BenchmarkTestdata/TwitterStatus/Marshal/Concrete-10          	    1549	    759064 ns/op	 831.96 MB/s	  501913 B/op	      59 allocs/op
BenchmarkTestdata/TwitterStatus/Marshal/Interface-10         	    1165	   1017282 ns/op	 620.79 MB/s	  469194 B/op	       2 allocs/op
BenchmarkTestdata/TwitterStatus/Encode/Token/Streaming-10    	    1071	   1115264 ns/op	 566.25 MB/s	   17464 B/op	      94 allocs/op
BenchmarkTestdata/TwitterStatus/Encode/Token/Buffered-10     	    1094	   1092146 ns/op	 578.23 MB/s	    9808 B/op	      81 allocs/op
BenchmarkTestdata/TwitterStatus/Encode/Value/Streaming-10    	    1006	   1167778 ns/op	 540.78 MB/s	 2551921 B/op	     119 allocs/op
BenchmarkTestdata/TwitterStatus/Encode/Value/Buffered-10     	    1222	    981393 ns/op	 643.49 MB/s	   13112 B/op	      89 allocs/op

@veqryn
Copy link
Contributor Author

veqryn commented Nov 9, 2023

looks like most of the benchmarks are within a half-percent of each other, then there are a few that are 2% faster with the PR, and a few more than are 3-4% slower with the PR. Margin of error is probably 2-3% on my laptop for small runs like this.
How are things looking for you now?

@veqryn
Copy link
Contributor Author

veqryn commented Nov 14, 2023

@dsnet The PR was updated with your suggestions. Please let me know what you think.

@dsnet
Copy link
Collaborator

dsnet commented Nov 15, 2023

Thanks for working on this, I'm a bit busy this week, so I might be able to get to this on the weekend.

@veqryn
Copy link
Contributor Author

veqryn commented Jan 9, 2024

hey @dsnet , just wondering if we can get this merged in now :)

@veqryn
Copy link
Contributor Author

veqryn commented Mar 7, 2024

rebased on master...

@veqryn
Copy link
Contributor Author

veqryn commented Apr 3, 2024

hi @dsnet , I am now using JSON v2 in production, via my v2 json slog handler: https://github.com/veqryn/slog-json

However, because go.mod replacement rules don't work well for libraries, I am forced to point slog-json at my fork of JSON v2 in order to get the single-line pretty-printing.

When we left off with this PR it sounded like you were ready to merge it after a final re-review. Is there anything I can do to get this moving again, please?

@dsnet
Copy link
Collaborator

dsnet commented Apr 11, 2024

Generally, LGTM. There are some cleanups and minor behavior changes, but it'll probably easier to just change that after submission than have a few more rounds of back-and-forth review.

@veqryn
Copy link
Contributor Author

veqryn commented Apr 11, 2024

Sounds great

@dsnet dsnet merged commit b15d3ef into go-json-experiment:master Apr 11, 2024
4 checks passed
@dsnet
Copy link
Collaborator

dsnet commented Apr 11, 2024

Thank you for the contribution. I apologize for the massive delay.

@veqryn
Copy link
Contributor Author

veqryn commented Apr 12, 2024

You are very welcome

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.

2 participants