Closed veqryn closed 5 months ago
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.
Of course. I have signed the Go CLA. Here is my most recent contribution, though small: https://github.com/golang/go/commit/65c53a1833a26467357b4aa6223e4dde5d6d7ed0 https://go-review.googlesource.com/c/go/+/524618
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?
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?
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.
If you're okay with it, I can take a stab at implementing this.
Ok. So here is what I plan to change, please let me know what you think:
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.
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.
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.
We also probably want to have the semantic that use of Multiline
or Indent
or IndentPrefix
implies SpaceAfterColon
if not already set.
Also for benchmarks, you probably want to run these instead:
go test -run=- -bench="Testdata//(Marshal|Encode)/"
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
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?
@dsnet The PR was updated with your suggestions. Please let me know what you think.
Thanks for working on this, I'm a bit busy this week, so I might be able to get to this on the weekend.
hey @dsnet , just wondering if we can get this merged in now :)
rebased on master...
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?
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.
Sounds great
Thank you for the contribution. I apologize for the massive delay.
You are very welcome
Discussion: In the same vein as the
WithIndent
andWithIndentPrefix
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:
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.
https://github.com/golang/go/discussions/63397#discussioncomment-7300039
PR Details: This PR adds two new boolean flag options:
SpaceAfterColon
andSpaceAfterComma
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.