pax_global_header 0000666 0000000 0000000 00000000064 14635552766 0014535 g ustar 00root root 0000000 0000000 52 comment=409f6478dae55ec63b12537561d28ba570d2d5a8
golang-github-goccy-go-json-0.10.3/ 0000775 0000000 0000000 00000000000 14635552766 0017021 5 ustar 00root root 0000000 0000000 golang-github-goccy-go-json-0.10.3/.codecov.yml 0000664 0000000 0000000 00000000727 14635552766 0021252 0 ustar 00root root 0000000 0000000 codecov:
require_ci_to_pass: yes
coverage:
precision: 2
round: down
range: "70...100"
status:
project:
default:
target: 70%
threshold: 2%
patch: off
changes: no
parsers:
gcov:
branch_detection:
conditional: yes
loop: yes
method: no
macro: no
comment:
layout: "header,diff"
behavior: default
require_changes: no
ignore:
- internal/encoder/vm_color
- internal/encoder/vm_color_indent
golang-github-goccy-go-json-0.10.3/.github/ 0000775 0000000 0000000 00000000000 14635552766 0020361 5 ustar 00root root 0000000 0000000 golang-github-goccy-go-json-0.10.3/.github/FUNDING.yml 0000664 0000000 0000000 00000000020 14635552766 0022166 0 ustar 00root root 0000000 0000000 github: [goccy]
golang-github-goccy-go-json-0.10.3/.github/workflows/ 0000775 0000000 0000000 00000000000 14635552766 0022416 5 ustar 00root root 0000000 0000000 golang-github-goccy-go-json-0.10.3/.github/workflows/go.yml 0000664 0000000 0000000 00000004470 14635552766 0023553 0 ustar 00root root 0000000 0000000 name: Go
on:
push:
branches:
- master
pull_request:
jobs:
build:
name: Build on limited environment
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v3
- name: build
run: docker-compose run go-json
test:
name: Test
strategy:
matrix:
os: [ "ubuntu-latest", "macos-latest", "windows-latest" ]
go-version: [ "1.19", "1.20", "1.21" ]
runs-on: ${{ matrix.os }}
steps:
- name: setup Go ${{ matrix.go-version }}
uses: actions/setup-go@v3
with:
go-version: ${{ matrix.go-version }}
- name: checkout
uses: actions/checkout@v3
- name: simple test
run: go test -v ./... -count=1
- name: test with GC pressure
run: go test -v ./... -count=1
env:
GOGC: 1
- name: test with race detector
run: go test -v -race ./... -count=1
lint:
name: Lint
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v3
- name: setup Go
uses: actions/setup-go@v3
with:
go-version: '1.21'
- name: lint
run: |
make lint
bench:
name: Benchmark
runs-on: ubuntu-latest
steps:
- name: setup Go
uses: actions/setup-go@v3
with:
go-version: '1.21'
- name: checkout ( feature )
uses: actions/checkout@v3
- name: run benchmark ( feature )
run: cd benchmarks && go test -bench GoJson | tee $HOME/new.txt
- name: install benchstat
run: go install golang.org/x/perf/cmd/benchstat@latest
- name: checkout ( master )
uses: actions/checkout@v3
with:
ref: master
- name: run benchmark ( master )
run: cd benchmarks && go test -bench GoJson | tee $HOME/old.txt
- name: compare benchmark results
run: benchstat $HOME/old.txt $HOME/new.txt
coverage:
name: Coverage
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v3
- name: setup Go
uses: actions/setup-go@v3
with:
go-version: '1.21'
- name: measure coverage
run: make cover
- uses: codecov/codecov-action@v4
with:
fail_ci_if_error: true
verbose: true
token: ${{ secrets.CODECOV_TOKEN }}
golang-github-goccy-go-json-0.10.3/.gitignore 0000664 0000000 0000000 00000000025 14635552766 0021006 0 ustar 00root root 0000000 0000000 cover.html
cover.out
golang-github-goccy-go-json-0.10.3/.golangci.yml 0000664 0000000 0000000 00000002730 14635552766 0021407 0 ustar 00root root 0000000 0000000 run:
skip-files:
- encode_optype.go
- ".*_test\\.go$"
linters-settings:
govet:
enable-all: true
disable:
- shadow
linters:
enable-all: true
disable:
- dogsled
- dupl
- exhaustive
- exhaustivestruct
- errorlint
- forbidigo
- funlen
- gci
- gochecknoglobals
- gochecknoinits
- gocognit
- gocritic
- gocyclo
- godot
- godox
- goerr113
- gofumpt
- gomnd
- gosec
- ifshort
- lll
- makezero
- nakedret
- nestif
- nlreturn
- paralleltest
- testpackage
- thelper
- wrapcheck
- interfacer
- lll
- nakedret
- nestif
- nlreturn
- testpackage
- wsl
- varnamelen
- nilnil
- ireturn
- govet
- forcetypeassert
- cyclop
- containedctx
- revive
- nosnakecase
- exhaustruct
- depguard
issues:
exclude-rules:
# not needed
- path: /*.go
text: "ST1003: should not use underscores in package names"
linters:
- stylecheck
- path: /*.go
text: "don't use an underscore in package name"
linters:
- golint
- path: rtype.go
linters:
- golint
- stylecheck
- path: error.go
linters:
- staticcheck
# Maximum issues count per one linter. Set to 0 to disable. Default is 50.
max-issues-per-linter: 0
# Maximum count of issues with the same text. Set to 0 to disable. Default is 3.
max-same-issues: 0
golang-github-goccy-go-json-0.10.3/CHANGELOG.md 0000664 0000000 0000000 00000026520 14635552766 0020637 0 ustar 00root root 0000000 0000000 # v0.10.2 - 2023/03/20
### New features
* Support DebugDOT option for debugging encoder ( #440 )
### Fix bugs
* Fix combination of embedding structure and omitempty option ( #442 )
# v0.10.1 - 2023/03/13
### Fix bugs
* Fix checkptr error for array decoder ( #415 )
* Fix added buffer size check when decoding key ( #430 )
* Fix handling of anonymous fields other than struct ( #431 )
* Fix to not optimize when lower conversion can't handle byte-by-byte ( #432 )
* Fix a problem that MarshalIndent does not work when UnorderedMap is specified ( #435 )
* Fix mapDecoder.DecodeStream() for empty objects containing whitespace ( #425 )
* Fix an issue that could not set the correct NextField for fields in the embedded structure ( #438 )
# v0.10.0 - 2022/11/29
### New features
* Support JSON Path ( #250 )
### Fix bugs
* Fix marshaler for map's key ( #409 )
# v0.9.11 - 2022/08/18
### Fix bugs
* Fix unexpected behavior when buffer ends with backslash ( #383 )
* Fix stream decoding of escaped character ( #387 )
# v0.9.10 - 2022/07/15
### Fix bugs
* Fix boundary exception of type caching ( #382 )
# v0.9.9 - 2022/07/15
### Fix bugs
* Fix encoding of directed interface with typed nil ( #377 )
* Fix embedded primitive type encoding using alias ( #378 )
* Fix slice/array type encoding with types implementing MarshalJSON ( #379 )
* Fix unicode decoding when the expected buffer state is not met after reading ( #380 )
# v0.9.8 - 2022/06/30
### Fix bugs
* Fix decoding of surrogate-pair ( #365 )
* Fix handling of embedded primitive type ( #366 )
* Add validation of escape sequence for decoder ( #367 )
* Fix stream tokenizing respecting UseNumber ( #369 )
* Fix encoding when struct pointer type that implements Marshal JSON is embedded ( #375 )
### Improve performance
* Improve performance of linkRecursiveCode ( #368 )
# v0.9.7 - 2022/04/22
### Fix bugs
#### Encoder
* Add filtering process for encoding on slow path ( #355 )
* Fix encoding of interface{} with pointer type ( #363 )
#### Decoder
* Fix map key decoder that implements UnmarshalJSON ( #353 )
* Fix decoding of []uint8 type ( #361 )
### New features
* Add DebugWith option for encoder ( #356 )
# v0.9.6 - 2022/03/22
### Fix bugs
* Correct the handling of the minimum value of int type for decoder ( #344 )
* Fix bugs of stream decoder's bufferSize ( #349 )
* Add a guard to use typeptr more safely ( #351 )
### Improve decoder performance
* Improve escapeString's performance ( #345 )
### Others
* Update go version for CI ( #347 )
# v0.9.5 - 2022/03/04
### Fix bugs
* Fix panic when decoding time.Time with context ( #328 )
* Fix reading the next character in buffer to nul consideration ( #338 )
* Fix incorrect handling on skipValue ( #341 )
### Improve decoder performance
* Improve performance when a payload contains escape sequence ( #334 )
# v0.9.4 - 2022/01/21
* Fix IsNilForMarshaler for string type with omitempty ( #323 )
* Fix the case where the embedded field is at the end ( #326 )
# v0.9.3 - 2022/01/14
* Fix logic of removing struct field for decoder ( #322 )
# v0.9.2 - 2022/01/14
* Add invalid decoder to delay type error judgment at decode ( #321 )
# v0.9.1 - 2022/01/11
* Fix encoding of MarshalText/MarshalJSON operation with head offset ( #319 )
# v0.9.0 - 2022/01/05
### New feature
* Supports dynamic filtering of struct fields ( #314 )
### Improve encoding performance
* Improve map encoding performance ( #310 )
* Optimize encoding path for escaped string ( #311 )
* Add encoding option for performance ( #312 )
### Fix bugs
* Fix panic at encoding map value on 1.18 ( #310 )
* Fix MarshalIndent for interface type ( #317 )
# v0.8.1 - 2021/12/05
* Fix operation conversion from PtrHead to Head in Recursive type ( #305 )
# v0.8.0 - 2021/12/02
* Fix embedded field conflict behavior ( #300 )
* Refactor compiler for encoder ( #301 #302 )
# v0.7.10 - 2021/10/16
* Fix conversion from pointer to uint64 ( #294 )
# v0.7.9 - 2021/09/28
* Fix encoding of nil value about interface type that has method ( #291 )
# v0.7.8 - 2021/09/01
* Fix mapassign_faststr for indirect struct type ( #283 )
* Fix encoding of not empty interface type ( #284 )
* Fix encoding of empty struct interface type ( #286 )
# v0.7.7 - 2021/08/25
* Fix invalid utf8 on stream decoder ( #279 )
* Fix buffer length bug on string stream decoder ( #280 )
Thank you @orisano !!
# v0.7.6 - 2021/08/13
* Fix nil slice assignment ( #276 )
* Improve error message ( #277 )
# v0.7.5 - 2021/08/12
* Fix encoding of embedded struct with tags ( #265 )
* Fix encoding of embedded struct that isn't first field ( #272 )
* Fix decoding of binary type with escaped char ( #273 )
# v0.7.4 - 2021/07/06
* Fix encoding of indirect layout structure ( #264 )
# v0.7.3 - 2021/06/29
* Fix encoding of pointer type in empty interface ( #262 )
# v0.7.2 - 2021/06/26
### Fix decoder
* Add decoder for func type to fix decoding of nil function value ( #257 )
* Fix stream decoding of []byte type ( #258 )
### Performance
* Improve decoding performance of map[string]interface{} type ( use `mapassign_faststr` ) ( #256 )
* Improve encoding performance of empty interface type ( remove recursive calling of `vm.Run` ) ( #259 )
### Benchmark
* Add bytedance/sonic as benchmark target ( #254 )
# v0.7.1 - 2021/06/18
### Fix decoder
* Fix error when unmarshal empty array ( #253 )
# v0.7.0 - 2021/06/12
### Support context for MarshalJSON and UnmarshalJSON ( #248 )
* json.MarshalContext(context.Context, interface{}, ...json.EncodeOption) ([]byte, error)
* json.NewEncoder(io.Writer).EncodeContext(context.Context, interface{}, ...json.EncodeOption) error
* json.UnmarshalContext(context.Context, []byte, interface{}, ...json.DecodeOption) error
* json.NewDecoder(io.Reader).DecodeContext(context.Context, interface{}) error
```go
type MarshalerContext interface {
MarshalJSON(context.Context) ([]byte, error)
}
type UnmarshalerContext interface {
UnmarshalJSON(context.Context, []byte) error
}
```
### Add DecodeFieldPriorityFirstWin option ( #242 )
In the default behavior, go-json, like encoding/json, will reflect the result of the last evaluation when a field with the same name exists. I've added new options to allow you to change this behavior. `json.DecodeFieldPriorityFirstWin` option reflects the result of the first evaluation if a field with the same name exists. This behavior has a performance advantage as it allows the subsequent strings to be skipped if all fields have been evaluated.
### Fix encoder
* Fix indent number contains recursive type ( #249 )
* Fix encoding of using empty interface as map key ( #244 )
### Fix decoder
* Fix decoding fields containing escaped characters ( #237 )
### Refactor
* Move some tests to subdirectory ( #243 )
* Refactor package layout for decoder ( #238 )
# v0.6.1 - 2021/06/02
### Fix encoder
* Fix value of totalLength for encoding ( #236 )
# v0.6.0 - 2021/06/01
### Support Colorize option for encoding (#233)
```go
b, err := json.MarshalWithOption(v, json.Colorize(json.DefaultColorScheme))
if err != nil {
...
}
fmt.Println(string(b)) // print colored json
```
### Refactor
* Fix opcode layout - Adjust memory layout of the opcode to 128 bytes in a 64-bit environment ( #230 )
* Refactor encode option ( #231 )
* Refactor escape string ( #232 )
# v0.5.1 - 2021/5/20
### Optimization
* Add type addrShift to enable bigger encoder/decoder cache ( #213 )
### Fix decoder
* Keep original reference of slice element ( #229 )
### Refactor
* Refactor Debug mode for encoding ( #226 )
* Generate VM sources for encoding ( #227 )
* Refactor validator for null/true/false for decoding ( #221 )
# v0.5.0 - 2021/5/9
### Supports using omitempty and string tags at the same time ( #216 )
### Fix decoder
* Fix stream decoder for unicode char ( #215 )
* Fix decoding of slice element ( #219 )
* Fix calculating of buffer length for stream decoder ( #220 )
### Refactor
* replace skipWhiteSpace goto by loop ( #212 )
# v0.4.14 - 2021/5/4
### Benchmark
* Add valyala/fastjson to benchmark ( #193 )
* Add benchmark task for CI ( #211 )
### Fix decoder
* Fix decoding of slice with unmarshal json type ( #198 )
* Fix decoding of null value for interface type that does not implement Unmarshaler ( #205 )
* Fix decoding of null value to []byte by json.Unmarshal ( #206 )
* Fix decoding of backslash char at the end of string ( #207 )
* Fix stream decoder for null/true/false value ( #208 )
* Fix stream decoder for slow reader ( #211 )
### Performance
* If cap of slice is enough, reuse slice data for compatibility with encoding/json ( #200 )
# v0.4.13 - 2021/4/20
### Fix json.Compact and json.Indent
* Support validation the input buffer for json.Compact and json.Indent ( #189 )
* Optimize json.Compact and json.Indent ( improve memory footprint ) ( #190 )
# v0.4.12 - 2021/4/15
### Fix encoder
* Fix unnecessary indent for empty slice type ( #181 )
* Fix encoding of omitempty feature for the slice or interface type ( #183 )
* Fix encoding custom types zero values with omitempty when marshaller exists ( #187 )
### Fix decoder
* Fix decoder for invalid top level value ( #184 )
* Fix decoder for invalid number value ( #185 )
# v0.4.11 - 2021/4/3
* Improve decoder performance for interface type
# v0.4.10 - 2021/4/2
### Fix encoder
* Fixed a bug when encoding slice and map containing recursive structures
* Fixed a logic to determine if indirect reference
# v0.4.9 - 2021/3/29
### Add debug mode
If you use `json.MarshalWithOption(v, json.Debug())` and `panic` occurred in `go-json`, produces debug information to console.
### Support a new feature to compatible with encoding/json
- invalid UTF-8 is coerced to valid UTF-8 ( without performance down )
### Fix encoder
- Fixed handling of MarshalJSON of function type
### Fix decoding of slice of pointer type
If there is a pointer value, go-json will use it. (This behavior is necessary to achieve the ability to prioritize pre-filled values). However, since slices are reused internally, there was a bug that referred to the previous pointer value. Therefore, it is not necessary to refer to the pointer value in advance for the slice element, so we explicitly initialize slice element by `nil`.
# v0.4.8 - 2021/3/21
### Reduce memory usage at compile time
* go-json have used about 2GB of memory at compile time, but now it can compile with about less than 550MB.
### Fix any encoder's bug
* Add many test cases for encoder
* Fix composite type ( slice/array/map )
* Fix pointer types
* Fix encoding of MarshalJSON or MarshalText or json.Number type
### Refactor encoder
* Change package layout for reducing memory usage at compile
* Remove anonymous and only operation
* Remove root property from encodeCompileContext and opcode
### Fix CI
* Add Go 1.16
* Remove Go 1.13
* Fix `make cover` task
### Number/Delim/Token/RawMessage use the types defined in encoding/json by type alias
# v0.4.7 - 2021/02/22
### Fix decoder
* Fix decoding of deep recursive structure
* Fix decoding of embedded unexported pointer field
* Fix invalid test case
* Fix decoding of invalid value
* Fix decoding of prefilled value
* Fix not being able to return UnmarshalTypeError when it should be returned
* Fix decoding of null value
* Fix decoding of type of null string
* Use pre allocated pointer if exists it at decoding
### Reduce memory usage at compile
* Integrate int/int8/int16/int32/int64 and uint/uint8/uint16/uint32/uint64 operation to reduce memory usage at compile
### Remove unnecessary optype
golang-github-goccy-go-json-0.10.3/LICENSE 0000664 0000000 0000000 00000002060 14635552766 0020024 0 ustar 00root root 0000000 0000000 MIT License
Copyright (c) 2020 Masaaki Goshima
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
golang-github-goccy-go-json-0.10.3/Makefile 0000664 0000000 0000000 00000001554 14635552766 0020466 0 ustar 00root root 0000000 0000000 PKG := github.com/goccy/go-json
BIN_DIR := $(CURDIR)/bin
PKGS := $(shell go list ./... | grep -v internal/cmd|grep -v test)
COVER_PKGS := $(foreach pkg,$(PKGS),$(subst $(PKG),.,$(pkg)))
COMMA := ,
EMPTY :=
SPACE := $(EMPTY) $(EMPTY)
COVERPKG_OPT := $(subst $(SPACE),$(COMMA),$(COVER_PKGS))
$(BIN_DIR):
@mkdir -p $(BIN_DIR)
.PHONY: cover
cover:
go test -coverpkg=$(COVERPKG_OPT) -coverprofile=cover.out ./...
.PHONY: cover-html
cover-html: cover
go tool cover -html=cover.out
.PHONY: lint
lint: golangci-lint
$(BIN_DIR)/golangci-lint run
golangci-lint: | $(BIN_DIR)
@{ \
set -e; \
GOLANGCI_LINT_TMP_DIR=$$(mktemp -d); \
cd $$GOLANGCI_LINT_TMP_DIR; \
go mod init tmp; \
GOBIN=$(BIN_DIR) go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.54.2; \
rm -rf $$GOLANGCI_LINT_TMP_DIR; \
}
.PHONY: generate
generate:
go generate ./internal/...
golang-github-goccy-go-json-0.10.3/README.md 0000664 0000000 0000000 00000047446 14635552766 0020317 0 ustar 00root root 0000000 0000000 # go-json

[](https://pkg.go.dev/github.com/goccy/go-json?tab=doc)
[](https://codecov.io/gh/goccy/go-json)
Fast JSON encoder/decoder compatible with encoding/json for Go
# Roadmap
```
* version ( expected release date )
* v0.9.0
|
| while maintaining compatibility with encoding/json, we will add convenient APIs
|
v
* v1.0.0
```
We are accepting requests for features that will be implemented between v0.9.0 and v.1.0.0.
If you have the API you need, please submit your issue [here](https://github.com/goccy/go-json/issues).
# Features
- Drop-in replacement of `encoding/json`
- Fast ( See [Benchmark section](https://github.com/goccy/go-json#benchmarks) )
- Flexible customization with options
- Coloring the encoded string
- Can propagate context.Context to `MarshalJSON` or `UnmarshalJSON`
- Can dynamically filter the fields of the structure type-safely
# Installation
```
go get github.com/goccy/go-json
```
# How to use
Replace import statement from `encoding/json` to `github.com/goccy/go-json`
```
-import "encoding/json"
+import "github.com/goccy/go-json"
```
# JSON library comparison
| name | encoder | decoder | compatible with `encoding/json` |
| :----: | :------: | :-----: | :-----------------------------: |
| encoding/json | yes | yes | N/A |
| [json-iterator/go](https://github.com/json-iterator/go) | yes | yes | partial |
| [easyjson](https://github.com/mailru/easyjson) | yes | yes | no |
| [gojay](https://github.com/francoispqt/gojay) | yes | yes | no |
| [segmentio/encoding/json](https://github.com/segmentio/encoding/tree/master/json) | yes | yes | partial |
| [jettison](https://github.com/wI2L/jettison) | yes | no | no |
| [simdjson-go](https://github.com/minio/simdjson-go) | no | yes | no |
| goccy/go-json | yes | yes | yes |
- `json-iterator/go` isn't compatible with `encoding/json` in many ways (e.g. https://github.com/json-iterator/go/issues/229 ), but it hasn't been supported for a long time.
- `segmentio/encoding/json` is well supported for encoders, but some are not supported for decoder APIs such as `Token` ( streaming decode )
## Other libraries
- [jingo](https://github.com/bet365/jingo)
I tried the benchmark but it didn't work.
Also, it seems to panic when it receives an unexpected value because there is no error handling...
- [ffjson](https://github.com/pquerna/ffjson)
Benchmarking gave very slow results.
It seems that it is assumed that the user will use the buffer pool properly.
Also, development seems to have already stopped
# Benchmarks
```
$ cd benchmarks
$ go test -bench .
```
## Encode
## Decode
# Fuzzing
[go-json-fuzz](https://github.com/goccy/go-json-fuzz) is the repository for fuzzing tests.
If you run the test in this repository and find a bug, please commit to corpus to go-json-fuzz and report the issue to [go-json](https://github.com/goccy/go-json/issues).
# How it works
`go-json` is very fast in both encoding and decoding compared to other libraries.
It's easier to implement by using automatic code generation for performance or by using a dedicated interface, but `go-json` dares to stick to compatibility with `encoding/json` and is the simple interface. Despite this, we are developing with the aim of being the fastest library.
Here, we explain the various speed-up techniques implemented by `go-json`.
## Basic technique
The techniques listed here are the ones used by most of the libraries listed above.
### Buffer reuse
Since the only value required for the result of `json.Marshal(interface{}) ([]byte, error)` is `[]byte`, the only value that must be allocated during encoding is the return value `[]byte` .
Also, as the number of allocations increases, the performance will be affected, so the number of allocations should be kept as low as possible when creating `[]byte`.
Therefore, there is a technique to reduce the number of times a new buffer must be allocated by reusing the buffer used for the previous encoding by using `sync.Pool`.
Finally, you allocate a buffer that is as long as the resulting buffer and copy the contents into it, you only need to allocate the buffer once in theory.
```go
type buffer struct {
data []byte
}
var bufPool = sync.Pool{
New: func() interface{} {
return &buffer{data: make([]byte, 0, 1024)}
},
}
buf := bufPool.Get().(*buffer)
data := encode(buf.data) // reuse buf.data
newBuf := make([]byte, len(data))
copy(newBuf, buf)
buf.data = data
bufPool.Put(buf)
```
### Elimination of reflection
As you know, the reflection operation is very slow.
Therefore, using the fact that the address position where the type information is stored is fixed for each binary ( we call this `typeptr` ),
we can use the address in the type information to call a pre-built optimized process.
For example, you can get the address to the type information from `interface{}` as follows and you can use that information to call a process that does not have reflection.
To process without reflection, pass a pointer (`unsafe.Pointer`) to the value is stored.
```go
type emptyInterface struct {
typ unsafe.Pointer
ptr unsafe.Pointer
}
var typeToEncoder = map[uintptr]func(unsafe.Pointer)([]byte, error){}
func Marshal(v interface{}) ([]byte, error) {
iface := (*emptyInterface)(unsafe.Pointer(&v)
typeptr := uintptr(iface.typ)
if enc, exists := typeToEncoder[typeptr]; exists {
return enc(iface.ptr)
}
...
}
```
※ In reality, `typeToEncoder` can be referenced by multiple goroutines, so exclusive control is required.
## Unique speed-up technique
## Encoder
### Do not escape arguments of `Marshal`
`json.Marshal` and `json.Unmarshal` receive `interface{}` value and they perform type determination dynamically to process.
In normal case, you need to use the `reflect` library to determine the type dynamically, but since `reflect.Type` is defined as `interface`, when you call the method of `reflect.Type`, The reflect's argument is escaped.
Therefore, the arguments for `Marshal` and `Unmarshal` are always escaped to the heap.
However, `go-json` can use the feature of `reflect.Type` while avoiding escaping.
`reflect.Type` is defined as `interface`, but in reality `reflect.Type` is implemented only by the structure `rtype` defined in the `reflect` package.
For this reason, to date `reflect.Type` is the same as `*reflect.rtype`.
Therefore, by directly handling `*reflect.rtype`, which is an implementation of `reflect.Type`, it is possible to avoid escaping because it changes from `interface` to using `struct`.
The technique for working with `*reflect.rtype` directly from `go-json` is implemented at [rtype.go](https://github.com/goccy/go-json/blob/master/internal/runtime/rtype.go)
Also, the same technique is cut out as a library ( https://github.com/goccy/go-reflect )
Initially this feature was the default behavior of `go-json`.
But after careful testing, I found that I passed a large value to `json.Marshal()` and if the argument could not be assigned to the stack, it could not be properly escaped to the heap (a bug in the Go compiler).
Therefore, this feature will be provided as an **optional** until this issue is resolved.
To use it, add `NoEscape` like `MarshalNoEscape()`
### Encoding using opcode sequence
I explained that you can use `typeptr` to call a pre-built process from type information.
In other libraries, this dedicated process is processed by making it an function calling like anonymous function, but function calls are inherently slow processes and should be avoided as much as possible.
Therefore, `go-json` adopted the Instruction-based execution processing system, which is also used to implement virtual machines for programming language.
If it is the first type to encode, create the opcode ( instruction ) sequence required for encoding.
From the second time onward, use `typeptr` to get the cached pre-built opcode sequence and encode it based on it. An example of the opcode sequence is shown below.
```go
json.Marshal(struct{
X int `json:"x"`
Y string `json:"y"`
}{X: 1, Y: "hello"})
```
When encoding a structure like the one above, create a sequence of opcodes like this:
```
- opStructFieldHead ( `{` )
- opStructFieldInt ( `"x": 1,` )
- opStructFieldString ( `"y": "hello"` )
- opStructEnd ( `}` )
- opEnd
```
※ When processing each operation, write the letters on the right.
In addition, each opcode is managed by the following structure (
Pseudo code ).
```go
type opType int
const (
opStructFieldHead opType = iota
opStructFieldInt
opStructFieldStirng
opStructEnd
opEnd
)
type opcode struct {
op opType
key []byte
next *opcode
}
```
The process of encoding using the opcode sequence is roughly implemented as follows.
```go
func encode(code *opcode, b []byte, p unsafe.Pointer) ([]byte, error) {
for {
switch code.op {
case opStructFieldHead:
b = append(b, '{')
code = code.next
case opStructFieldInt:
b = append(b, code.key...)
b = appendInt((*int)(unsafe.Pointer(uintptr(p)+code.offset)))
code = code.next
case opStructFieldString:
b = append(b, code.key...)
b = appendString((*string)(unsafe.Pointer(uintptr(p)+code.offset)))
code = code.next
case opStructEnd:
b = append(b, '}')
code = code.next
case opEnd:
goto END
}
}
END:
return b, nil
}
```
In this way, the huge `switch-case` is used to encode by manipulating the linked list opcodes to avoid unnecessary function calls.
### Opcode sequence optimization
One of the advantages of encoding using the opcode sequence is the ease of optimization.
The opcode sequence mentioned above is actually converted into the following optimized operations and used.
```
- opStructFieldHeadInt ( `{"x": 1,` )
- opStructEndString ( `"y": "hello"}` )
- opEnd
```
It has been reduced from 5 opcodes to 3 opcodes !
Reducing the number of opcodees means reducing the number of branches with `switch-case`.
In other words, the closer the number of operations is to 1, the faster the processing can be performed.
In `go-json`, optimization to reduce the number of opcodes itself like the above and it speeds up by preparing opcodes with optimized paths.
### Change recursive call from CALL to JMP
Recursive processing is required during encoding if the type is defined recursively as follows:
```go
type T struct {
X int
U *U
}
type U struct {
T *T
}
b, err := json.Marshal(&T{
X: 1,
U: &U{
T: &T{
X: 2,
},
},
})
fmt.Println(string(b)) // {"X":1,"U":{"T":{"X":2,"U":null}}}
```
In `go-json`, recursive processing is processed by the operation type of ` opStructFieldRecursive`.
In this operation, after acquiring the opcode sequence used for recursive processing, the function is **not** called recursively as it is, but the necessary values are saved by itself and implemented by moving to the next operation.
The technique of implementing recursive processing with the `JMP` operation while avoiding the `CALL` operation is a famous technique for implementing a high-speed virtual machine.
For more details, please refer to [the article](https://engineering.mercari.com/blog/entry/1599563768-081104c850) ( but Japanese only ).
### Dispatch by typeptr from map to slice
When retrieving the data cached from the type information by `typeptr`, we usually use map.
Map requires exclusive control, so use `sync.Map` for a naive implementation.
However, this is slow, so it's a good idea to use the `atomic` package for exclusive control as implemented by `segmentio/encoding/json` ( https://github.com/segmentio/encoding/blob/master/json/codec.go#L41-L55 ).
This implementation slows down the set instead of speeding up the get, but it works well because of the nature of the library, it encodes much more for the same type.
However, as a result of profiling, I noticed that `runtime.mapaccess2` accounts for a significant percentage of the execution time. So I thought if I could change the lookup from map to slice.
There is an API named `typelinks` defined in the `runtime` package that the `reflect` package uses internally.
This allows you to get all the type information defined in the binary at runtime.
The fact that all type information can be acquired means that by constructing slices in advance with the acquired total number of type information, it is possible to look up with the value of `typeptr` without worrying about out-of-range access.
However, if there is too much type information, it will use a lot of memory, so by default we will only use this optimization if the slice size fits within **2Mib** .
If this approach is not available, it will fall back to the `atomic` based process described above.
If you want to know more, please refer to the implementation [here](https://github.com/goccy/go-json/blob/master/internal/runtime/type.go#L36-L100)
## Decoder
### Dispatch by typeptr from map to slice
Like the encoder, the decoder also uses typeptr to call the dedicated process.
### Faster termination character inspection using NUL character
In order to decode, you have to traverse the input buffer character by position.
At that time, if you check whether the buffer has reached the end, it will be very slow.
`buf` : `[]byte` type variable. holds the string passed to the decoder
`cursor` : `int64` type variable. holds the current read position
```go
buflen := len(buf)
for ; cursor < buflen; cursor++ { // compare cursor and buflen at all times, it is so slow.
switch buf[cursor] {
case ' ', '\n', '\r', '\t':
}
}
```
Therefore, by adding the `NUL` (`\000`) character to the end of the read buffer as shown below, it is possible to check the termination character at the same time as other characters.
```go
for {
switch buf[cursor] {
case ' ', '\n', '\r', '\t':
case '\000':
return nil
}
cursor++
}
```
### Use Boundary Check Elimination
Due to the `NUL` character optimization, the Go compiler does a boundary check every time, even though `buf[cursor]` does not cause out-of-range access.
Therefore, `go-json` eliminates boundary check by fetching characters for hotspot by pointer operation. For example, the following code.
```go
func char(ptr unsafe.Pointer, offset int64) byte {
return *(*byte)(unsafe.Pointer(uintptr(ptr) + uintptr(offset)))
}
p := (*sliceHeader)(&unsafe.Pointer(buf)).data
for {
switch char(p, cursor) {
case ' ', '\n', '\r', '\t':
case '\000':
return nil
}
cursor++
}
```
### Checking the existence of fields of struct using Bitmaps
I found by the profiling result, in the struct decode, lookup process for field was taking a long time.
For example, consider decoding a string like `{"a":1,"b":2,"c":3}` into the following structure:
```go
type T struct {
A int `json:"a"`
B int `json:"b"`
C int `json:"c"`
}
```
At this time, it was found that it takes a lot of time to acquire the decoding process corresponding to the field from the field name as shown below during the decoding process.
```go
fieldName := decodeKey(buf, cursor) // "a" or "b" or "c"
decoder, exists := fieldToDecoderMap[fieldName] // so slow
if exists {
decoder(buf, cursor)
} else {
skipValue(buf, cursor)
}
```
To improve this process, `json-iterator/go` is optimized so that it can be branched by switch-case when the number of fields in the structure is 10 or less (switch-case is faster than map). However, there is a risk of hash collision because the value hashed by the FNV algorithm is used for conditional branching. Also, `gojay` processes this part at high speed by letting the library user yourself write `switch-case`.
`go-json` considers and implements a new approach that is different from these. I call this **bitmap field optimization**.
The range of values per character can be represented by `[256]byte`. Also, if the number of fields in the structure is 8 or less, `int8` type can represent the state of each field.
In other words, it has the following structure.
- Base ( 8bit ): `00000000`
- Key "a": `00000001` ( assign key "a" to the first bit )
- Key "b": `00000010` ( assign key "b" to the second bit )
- Key "c": `00000100` ( assign key "c" to the third bit )
Bitmap structure is the following
```
| key index(0) |
------------------------
0 | 00000000 |
1 | 00000000 |
~~ | |
97 (a) | 00000001 |
98 (b) | 00000010 |
99 (c) | 00000100 |
~~ | |
255 | 00000000 |
```
You can think of this as a Bitmap with a height of `256` and a width of the maximum string length in the field name.
In other words, it can be represented by the following type .
```go
[maxFieldKeyLength][256]int8
```
When decoding a field character, check whether the corresponding character exists by referring to the pre-built bitmap like the following.
```go
var curBit int8 = math.MaxInt8 // 11111111
c := char(buf, cursor)
bit := bitmap[keyIdx][c]
curBit &= bit
if curBit == 0 {
// not found field
}
```
If `curBit` is not `0` until the end of the field string, then the string is
You may have hit one of the fields.
But the possibility is that if the decoded string is shorter than the field string, you will get a false hit.
- input: `{"a":1}`
```go
type T struct {
X int `json:"abc"`
}
```
※ Since `a` is shorter than `abc`, it can decode to the end of the field character without `curBit` being 0.
Rest assured. In this case, it doesn't matter because you can tell if you hit by comparing the string length of `a` with the string length of `abc`.
Finally, calculate the position of the bit where `1` is set and get the corresponding value, and you're done.
Using this technique, field lookups are possible with only bitwise operations and access to slices.
`go-json` uses a similar technique for fields with 9 or more and 16 or less fields. At this time, Bitmap is constructed as `[maxKeyLen][256]int16` type.
Currently, this optimization is not performed when the maximum length of the field name is long (specifically, 64 bytes or more) in addition to the limitation of the number of fields from the viewpoint of saving memory usage.
### Others
I have done a lot of other optimizations. I will find time to write about them. If you have any questions about what's written here or other optimizations, please visit the `#go-json` channel on `gophers.slack.com` .
## Reference
Regarding the story of go-json, there are the following articles in Japanese only.
- https://speakerdeck.com/goccy/zui-su-falsejsonraiburariwoqiu-mete
- https://engineering.mercari.com/blog/entry/1599563768-081104c850/
# Looking for Sponsors
I'm looking for sponsors this library. This library is being developed as a personal project in my spare time. If you want a quick response or problem resolution when using this library in your project, please register as a [sponsor](https://github.com/sponsors/goccy). I will cooperate as much as possible. Of course, this library is developed as an MIT license, so you can use it freely for free.
# License
MIT
golang-github-goccy-go-json-0.10.3/benchmarks/ 0000775 0000000 0000000 00000000000 14635552766 0021136 5 ustar 00root root 0000000 0000000 golang-github-goccy-go-json-0.10.3/benchmarks/bench_test.go 0000664 0000000 0000000 00000033175 14635552766 0023614 0 ustar 00root root 0000000 0000000 // Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Large data benchmark.
// The JSON data is a summary of agl's changes in the
// go, webkit, and chromium open source projects.
// We benchmark converting between the JSON form
// and in-memory data structures.
package benchmark
import (
"bytes"
"compress/gzip"
"fmt"
"io"
"os"
"strings"
"testing"
stdjson "encoding/json"
"github.com/goccy/go-json"
jsoniter "github.com/json-iterator/go"
segmentiojson "github.com/segmentio/encoding/json"
"github.com/wI2L/jettison"
)
type codeResponse struct {
Tree *codeNode `json:"tree"`
Username string `json:"username"`
}
type codeNode struct {
Name string `json:"name"`
Kids []*codeNode `json:"kids"`
CLWeight float64 `json:"cl_weight"`
Touches int `json:"touches"`
MinT int64 `json:"min_t"`
MaxT int64 `json:"max_t"`
MeanT int64 `json:"mean_t"`
}
var codeJSON []byte
var codeStruct codeResponse
func codeInit() {
f, err := os.Open("testdata/code.json.gz")
if err != nil {
panic(err)
}
defer f.Close()
gz, err := gzip.NewReader(f)
if err != nil {
panic(err)
}
data, err := io.ReadAll(gz)
if err != nil {
panic(err)
}
codeJSON = data
if err := stdjson.Unmarshal(codeJSON, &codeStruct); err != nil {
panic("unmarshal code.json: " + err.Error())
}
{
stdjsonbytes, err := stdjson.Marshal(&codeStruct)
if err != nil {
panic("marshal code.json: " + err.Error())
}
jsonbytes, err := json.Marshal(&codeStruct)
if err != nil {
panic("marshal code.json: " + err.Error())
}
if len(stdjsonbytes) != len(jsonbytes) {
panic(fmt.Sprintf("stdjson = %d but go-json = %d", len(stdjsonbytes), len(jsonbytes)))
}
}
if _, err := json.Marshal(&codeStruct); err != nil {
panic("marshal code.json: " + err.Error())
}
if !bytes.Equal(data, codeJSON) {
println("different lengths", len(data), len(codeJSON))
for i := 0; i < len(data) && i < len(codeJSON); i++ {
if data[i] != codeJSON[i] {
println("re-marshal: changed at byte", i)
println("orig: ", string(codeJSON[i-10:i+10]))
println("new: ", string(data[i-10:i+10]))
break
}
}
panic("re-marshal code.json: different result")
}
}
func Benchmark_EncodeBigData_GoJson(b *testing.B) {
b.ReportAllocs()
if codeJSON == nil {
b.StopTimer()
codeInit()
b.StartTimer()
}
b.RunParallel(func(pb *testing.PB) {
enc := json.NewEncoder(io.Discard)
for pb.Next() {
if err := enc.Encode(&codeStruct); err != nil {
b.Fatal("Encode:", err)
}
}
})
b.SetBytes(int64(len(codeJSON)))
}
func Benchmark_EncodeBigData_EncodingJson(b *testing.B) {
b.ReportAllocs()
if codeJSON == nil {
b.StopTimer()
codeInit()
b.StartTimer()
}
b.RunParallel(func(pb *testing.PB) {
enc := stdjson.NewEncoder(io.Discard)
for pb.Next() {
if err := enc.Encode(&codeStruct); err != nil {
b.Fatal("Encode:", err)
}
}
})
b.SetBytes(int64(len(codeJSON)))
}
func Benchmark_EncodeBigData_JsonIter(b *testing.B) {
b.ReportAllocs()
if codeJSON == nil {
b.StopTimer()
codeInit()
b.StartTimer()
}
var json = jsoniter.ConfigCompatibleWithStandardLibrary
b.RunParallel(func(pb *testing.PB) {
enc := json.NewEncoder(io.Discard)
for pb.Next() {
if err := enc.Encode(&codeStruct); err != nil {
b.Fatal("Encode:", err)
}
}
})
b.SetBytes(int64(len(codeJSON)))
}
func Benchmark_EncodeBigData_SegmentioJson(b *testing.B) {
b.ReportAllocs()
if codeJSON == nil {
b.StopTimer()
codeInit()
b.StartTimer()
}
b.RunParallel(func(pb *testing.PB) {
enc := segmentiojson.NewEncoder(io.Discard)
for pb.Next() {
if err := enc.Encode(&codeStruct); err != nil {
b.Fatal("Encode:", err)
}
}
})
b.SetBytes(int64(len(codeJSON)))
}
func Benchmark_MarshalBigData_GoJson(b *testing.B) {
b.ReportAllocs()
if codeJSON == nil {
b.StopTimer()
codeInit()
b.StartTimer()
}
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
if _, err := json.Marshal(&codeStruct); err != nil {
b.Fatal("Marshal:", err)
}
}
})
b.SetBytes(int64(len(codeJSON)))
}
func Benchmark_MarshalBigData_EncodingJson(b *testing.B) {
b.ReportAllocs()
if codeJSON == nil {
b.StopTimer()
codeInit()
b.StartTimer()
}
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
if _, err := stdjson.Marshal(&codeStruct); err != nil {
b.Fatal("Marshal:", err)
}
}
})
b.SetBytes(int64(len(codeJSON)))
}
func Benchmark_MarshalBigData_JsonIter(b *testing.B) {
b.ReportAllocs()
if codeJSON == nil {
b.StopTimer()
codeInit()
b.StartTimer()
}
var json = jsoniter.ConfigCompatibleWithStandardLibrary
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
if _, err := json.Marshal(&codeStruct); err != nil {
b.Fatal("Marshal:", err)
}
}
})
b.SetBytes(int64(len(codeJSON)))
}
func Benchmark_MarshalBigData_Jettison(b *testing.B) {
b.ReportAllocs()
if codeJSON == nil {
b.StopTimer()
codeInit()
b.StartTimer()
}
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
if _, err := jettison.Marshal(&codeStruct); err != nil {
b.Fatal("Marshal:", err)
}
}
})
b.SetBytes(int64(len(codeJSON)))
}
func Benchmark_MarshalBigData_SegmentioJson(b *testing.B) {
b.ReportAllocs()
if codeJSON == nil {
b.StopTimer()
codeInit()
b.StartTimer()
}
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
if _, err := segmentiojson.Marshal(&codeStruct); err != nil {
b.Fatal("Marshal:", err)
}
}
})
b.SetBytes(int64(len(codeJSON)))
}
func benchMarshalBytes(n int, marshaler func(interface{}) ([]byte, error)) func(*testing.B) {
sample := []byte("hello world")
// Use a struct pointer, to avoid an allocation when passing it as an
// interface parameter to Marshal.
v := &struct {
Bytes []byte
}{
bytes.Repeat(sample, (n/len(sample))+1)[:n],
}
return func(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := marshaler(v); err != nil {
b.Fatal("Marshal:", err)
}
}
}
}
func Benchmark_MarshalBytes_EncodingJson(b *testing.B) {
// 32 fits within encodeState.scratch.
b.Run("32", benchMarshalBytes(32, stdjson.Marshal))
// 256 doesn't fit in encodeState.scratch, but is small enough to
// allocate and avoid the slower base64.NewEncoder.
b.Run("256", benchMarshalBytes(256, stdjson.Marshal))
// 4096 is large enough that we want to avoid allocating for it.
b.Run("4096", benchMarshalBytes(4096, stdjson.Marshal))
}
func Benchmark_MarshalBytes_JsonIter(b *testing.B) {
var json = jsoniter.ConfigCompatibleWithStandardLibrary
// 32 fits within encodeState.scratch.
b.Run("32", benchMarshalBytes(32, json.Marshal))
// 256 doesn't fit in encodeState.scratch, but is small enough to
// allocate and avoid the slower base64.NewEncoder.
b.Run("256", benchMarshalBytes(256, json.Marshal))
// 4096 is large enough that we want to avoid allocating for it.
b.Run("4096", benchMarshalBytes(4096, json.Marshal))
}
func Benchmark_MarshalBytes_GoJson(b *testing.B) {
b.ReportAllocs()
// 32 fits within encodeState.scratch.
b.Run("32", benchMarshalBytes(32, json.Marshal))
// 256 doesn't fit in encodeState.scratch, but is small enough to
// allocate and avoid the slower base64.NewEncoder.
b.Run("256", benchMarshalBytes(256, json.Marshal))
// 4096 is large enough that we want to avoid allocating for it.
b.Run("4096", benchMarshalBytes(4096, json.Marshal))
}
func Benchmark_EncodeRawMessage_EncodingJson(b *testing.B) {
b.ReportAllocs()
m := struct {
A int
B json.RawMessage
}{}
b.RunParallel(func(pb *testing.PB) {
enc := stdjson.NewEncoder(io.Discard)
for pb.Next() {
if err := enc.Encode(&m); err != nil {
b.Fatal("Encode:", err)
}
}
})
}
func Benchmark_EncodeRawMessage_JsonIter(b *testing.B) {
b.ReportAllocs()
m := struct {
A int
B json.RawMessage
}{}
var json = jsoniter.ConfigCompatibleWithStandardLibrary
b.RunParallel(func(pb *testing.PB) {
enc := json.NewEncoder(io.Discard)
for pb.Next() {
if err := enc.Encode(&m); err != nil {
b.Fatal("Encode:", err)
}
}
})
}
func Benchmark_EncodeRawMessage_GoJson(b *testing.B) {
b.ReportAllocs()
m := struct {
A int
B json.RawMessage
}{}
b.RunParallel(func(pb *testing.PB) {
enc := json.NewEncoder(io.Discard)
for pb.Next() {
if err := enc.Encode(&m); err != nil {
b.Fatal("Encode:", err)
}
}
})
}
func Benchmark_MarshalString_EncodingJson(b *testing.B) {
b.ReportAllocs()
j := struct {
Bar string `json:"bar,string"`
}{
Bar: `foobar`,
}
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
if _, err := stdjson.Marshal(&j); err != nil {
b.Fatal(err)
}
}
})
}
func Benchmark_MarshalString_JsonIter(b *testing.B) {
b.ReportAllocs()
j := struct {
Bar string `json:"bar,string"`
}{
Bar: `foobar`,
}
var json = jsoniter.ConfigCompatibleWithStandardLibrary
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
if _, err := json.Marshal(&j); err != nil {
b.Fatal(err)
}
}
})
}
func Benchmark_MarshalString_GoJson(b *testing.B) {
b.ReportAllocs()
j := struct {
Bar string `json:"bar,string"`
}{
Bar: `foobar`,
}
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
if _, err := json.Marshal(&j); err != nil {
b.Fatal(err)
}
}
})
}
func BenchmarkCodeDecoder(b *testing.B) {
b.ReportAllocs()
if codeJSON == nil {
b.StopTimer()
codeInit()
b.StartTimer()
}
b.RunParallel(func(pb *testing.PB) {
var buf bytes.Buffer
dec := json.NewDecoder(&buf)
var r codeResponse
for pb.Next() {
buf.Write(codeJSON)
// hide EOF
buf.WriteByte('\n')
buf.WriteByte('\n')
buf.WriteByte('\n')
if err := dec.Decode(&r); err != nil {
if err != io.EOF {
b.Fatal("Decode:", err)
}
}
}
})
b.SetBytes(int64(len(codeJSON)))
}
func BenchmarkUnicodeDecoder(b *testing.B) {
b.ReportAllocs()
j := []byte(`"\uD83D\uDE01"`)
b.SetBytes(int64(len(j)))
r := bytes.NewReader(j)
dec := json.NewDecoder(r)
var out string
b.ResetTimer()
for i := 0; i < b.N; i++ {
if err := dec.Decode(&out); err != nil {
if err != io.EOF {
b.Fatal("Decode:", err)
}
}
r.Seek(0, 0)
}
}
func BenchmarkDecoderStream(b *testing.B) {
b.ReportAllocs()
b.StopTimer()
var buf bytes.Buffer
dec := json.NewDecoder(&buf)
buf.WriteString(`"` + strings.Repeat("x", 1000000) + `"` + "\n\n\n")
var x interface{}
if err := dec.Decode(&x); err != nil {
b.Fatal("Decode:", err)
}
ones := strings.Repeat(" 1\n", 300000) + "\n\n\n"
b.StartTimer()
for i := 0; i < b.N; i++ {
if i%300000 == 0 {
buf.WriteString(ones)
}
x = nil
if err := dec.Decode(&x); err != nil || x != 1.0 {
if err != io.EOF {
b.Fatalf("Decode: %v after %d", err, i)
}
}
}
}
func BenchmarkCodeUnmarshal(b *testing.B) {
b.ReportAllocs()
if codeJSON == nil {
b.StopTimer()
codeInit()
b.StartTimer()
}
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
var r codeResponse
if err := json.Unmarshal(codeJSON, &r); err != nil {
b.Fatal("Unmarshal:", err)
}
}
})
b.SetBytes(int64(len(codeJSON)))
}
func BenchmarkCodeUnmarshalReuse(b *testing.B) {
b.ReportAllocs()
if codeJSON == nil {
b.StopTimer()
codeInit()
b.StartTimer()
}
b.RunParallel(func(pb *testing.PB) {
var r codeResponse
for pb.Next() {
if err := json.Unmarshal(codeJSON, &r); err != nil {
b.Fatal("Unmarshal:", err)
}
}
})
b.SetBytes(int64(len(codeJSON)))
}
func BenchmarkUnmarshalString(b *testing.B) {
b.ReportAllocs()
data := []byte(`"hello, world"`)
b.RunParallel(func(pb *testing.PB) {
var s string
for pb.Next() {
if err := json.Unmarshal(data, &s); err != nil {
b.Fatal("Unmarshal:", err)
}
}
})
}
func BenchmarkUnmarshalFloat64(b *testing.B) {
b.ReportAllocs()
data := []byte(`3.14`)
b.RunParallel(func(pb *testing.PB) {
var f float64
for pb.Next() {
if err := json.Unmarshal(data, &f); err != nil {
b.Fatal("Unmarshal:", err)
}
}
})
}
func BenchmarkUnmarshalInt64(b *testing.B) {
b.ReportAllocs()
data := []byte(`3`)
b.RunParallel(func(pb *testing.PB) {
var x int64
for pb.Next() {
if err := json.Unmarshal(data, &x); err != nil {
b.Fatal("Unmarshal:", err)
}
}
})
}
func BenchmarkIssue10335(b *testing.B) {
b.ReportAllocs()
j := []byte(`{"a":{ }}`)
b.RunParallel(func(pb *testing.PB) {
var s struct{}
for pb.Next() {
if err := json.Unmarshal(j, &s); err != nil {
b.Fatal(err)
}
}
})
}
func BenchmarkUnmapped(b *testing.B) {
b.ReportAllocs()
j := []byte(`{"s": "hello", "y": 2, "o": {"x": 0}, "a": [1, 99, {"x": 1}]}`)
b.RunParallel(func(pb *testing.PB) {
var s struct{}
for pb.Next() {
if err := json.Unmarshal(j, &s); err != nil {
b.Fatal(err)
}
}
})
}
func Benchmark_Compact_EncodingJson(b *testing.B) {
b.ReportAllocs()
if codeJSON == nil {
b.StopTimer()
codeInit()
b.StartTimer()
}
for i := 0; i < b.N; i++ {
var buf bytes.Buffer
if err := stdjson.Compact(&buf, codeJSON); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Compact_GoJson(b *testing.B) {
b.ReportAllocs()
if codeJSON == nil {
b.StopTimer()
codeInit()
b.StartTimer()
}
for i := 0; i < b.N; i++ {
var buf bytes.Buffer
if err := json.Compact(&buf, codeJSON); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Indent_EncodingJson(b *testing.B) {
b.ReportAllocs()
if codeJSON == nil {
b.StopTimer()
codeInit()
b.StartTimer()
}
for i := 0; i < b.N; i++ {
var buf bytes.Buffer
if err := stdjson.Indent(&buf, codeJSON, "-", " "); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Indent_GoJson(b *testing.B) {
b.ReportAllocs()
if codeJSON == nil {
b.StopTimer()
codeInit()
b.StartTimer()
}
for i := 0; i < b.N; i++ {
var buf bytes.Buffer
if err := json.Indent(&buf, codeJSON, "-", " "); err != nil {
b.Fatal(err)
}
}
}
golang-github-goccy-go-json-0.10.3/benchmarks/decode_test.go 0000664 0000000 0000000 00000027277 14635552766 0023766 0 ustar 00root root 0000000 0000000 package benchmark
import (
"bytes"
"encoding/json"
"testing"
gojay "github.com/francoispqt/gojay"
gojson "github.com/goccy/go-json"
jsoniter "github.com/json-iterator/go"
segmentiojson "github.com/segmentio/encoding/json"
fastjson "github.com/valyala/fastjson"
)
func Benchmark_Decode_SmallStruct_Unmarshal_EncodingJson(b *testing.B) {
b.ReportAllocs()
for n := 0; n < b.N; n++ {
result := SmallPayload{}
if err := json.Unmarshal(SmallFixture, &result); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Decode_SmallStruct_Unmarshal_FastJson(b *testing.B) {
smallFixture := string(SmallFixture)
b.ReportAllocs()
for n := 0; n < b.N; n++ {
var p fastjson.Parser
if _, err := p.Parse(smallFixture); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Decode_SmallStruct_Unmarshal_SegmentioJson(b *testing.B) {
b.ReportAllocs()
for n := 0; n < b.N; n++ {
result := SmallPayload{}
if err := segmentiojson.Unmarshal(SmallFixture, &result); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Decode_SmallStruct_Unmarshal_JsonIter(b *testing.B) {
b.ReportAllocs()
for n := 0; n < b.N; n++ {
result := SmallPayload{}
if err := jsoniter.Unmarshal(SmallFixture, &result); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Decode_SmallStruct_Unmarshal_GoJay(b *testing.B) {
b.ReportAllocs()
for n := 0; n < b.N; n++ {
result := SmallPayload{}
if err := gojay.UnmarshalJSONObject(SmallFixture, &result); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Decode_SmallStruct_Unmarshal_GoJayUnsafe(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
result := SmallPayload{}
if err := gojay.Unsafe.UnmarshalJSONObject(SmallFixture, &result); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Decode_SmallStruct_Unmarshal_GoJson(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
result := SmallPayload{}
if err := gojson.Unmarshal(SmallFixture, &result); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Decode_SmallStruct_Unmarshal_GoJsonNoEscape(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
result := SmallPayload{}
if err := gojson.UnmarshalNoEscape(SmallFixture, &result); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Decode_SmallStruct_Stream_EncodingJson(b *testing.B) {
b.ReportAllocs()
reader := bytes.NewReader(SmallFixture)
for i := 0; i < b.N; i++ {
result := SmallPayload{}
reader.Reset(SmallFixture)
if err := json.NewDecoder(reader).Decode(&result); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Decode_SmallStruct_Stream_SegmentioJson(b *testing.B) {
b.ReportAllocs()
reader := bytes.NewReader(SmallFixture)
for i := 0; i < b.N; i++ {
result := SmallPayload{}
reader.Reset(SmallFixture)
if err := segmentiojson.NewDecoder(reader).Decode(&result); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Decode_SmallStruct_Stream_JsonIter(b *testing.B) {
b.ReportAllocs()
reader := bytes.NewReader(SmallFixture)
for i := 0; i < b.N; i++ {
result := SmallPayload{}
reader.Reset(SmallFixture)
if err := jsoniter.NewDecoder(reader).Decode(&result); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Decode_SmallStruct_Stream_GoJay(b *testing.B) {
b.ReportAllocs()
reader := bytes.NewReader(SmallFixture)
for n := 0; n < b.N; n++ {
reader.Reset(SmallFixture)
result := SmallPayload{}
if err := gojay.NewDecoder(reader).DecodeObject(&result); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Decode_SmallStruct_Stream_GoJson(b *testing.B) {
b.ReportAllocs()
reader := bytes.NewReader(SmallFixture)
for i := 0; i < b.N; i++ {
result := SmallPayload{}
reader.Reset(SmallFixture)
if err := gojson.NewDecoder(reader).Decode(&result); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Decode_MediumStruct_Unmarshal_EncodingJson(b *testing.B) {
b.ReportAllocs()
for n := 0; n < b.N; n++ {
result := MediumPayload{}
if err := json.Unmarshal(MediumFixture, &result); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Decode_MediumStruct_Unmarshal_FastJson(b *testing.B) {
mediumFixture := string(MediumFixture)
b.ReportAllocs()
for n := 0; n < b.N; n++ {
var p fastjson.Parser
if _, err := p.Parse(mediumFixture); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Decode_MediumStruct_Unmarshal_SegmentioJson(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
result := MediumPayload{}
if err := segmentiojson.Unmarshal(MediumFixture, &result); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Decode_MediumStruct_Unmarshal_JsonIter(b *testing.B) {
b.ReportAllocs()
for n := 0; n < b.N; n++ {
result := MediumPayload{}
if err := jsoniter.Unmarshal(MediumFixture, &result); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Decode_MediumStruct_Unmarshal_GoJay(b *testing.B) {
b.ReportAllocs()
for n := 0; n < b.N; n++ {
result := MediumPayload{}
if err := gojay.UnmarshalJSONObject(MediumFixture, &result); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Decode_MediumStruct_Unmarshal_GoJayUnsafe(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
result := MediumPayload{}
if err := gojay.Unsafe.UnmarshalJSONObject(MediumFixture, &result); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Decode_MediumStruct_Unmarshal_GoJson(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
result := MediumPayload{}
if err := gojson.Unmarshal(MediumFixture, &result); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Decode_MediumStruct_Unmarshal_GoJsonNoEscape(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
result := MediumPayload{}
if err := gojson.UnmarshalNoEscape(MediumFixture, &result); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Decode_MediumStruct_Stream_EncodingJson(b *testing.B) {
b.ReportAllocs()
reader := bytes.NewReader(MediumFixture)
for i := 0; i < b.N; i++ {
result := MediumPayload{}
reader.Reset(MediumFixture)
if err := json.NewDecoder(reader).Decode(&result); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Decode_MediumStruct_Stream_SegmentioJson(b *testing.B) {
b.ReportAllocs()
reader := bytes.NewReader(MediumFixture)
for n := 0; n < b.N; n++ {
reader.Reset(MediumFixture)
result := MediumPayload{}
if err := segmentiojson.NewDecoder(reader).Decode(&result); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Decode_MediumStruct_Stream_JsonIter(b *testing.B) {
b.ReportAllocs()
reader := bytes.NewReader(MediumFixture)
for i := 0; i < b.N; i++ {
result := MediumPayload{}
reader.Reset(MediumFixture)
if err := jsoniter.NewDecoder(reader).Decode(&result); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Decode_MediumStruct_Stream_GoJay(b *testing.B) {
b.ReportAllocs()
reader := bytes.NewReader(MediumFixture)
for n := 0; n < b.N; n++ {
reader.Reset(MediumFixture)
result := MediumPayload{}
if err := gojay.NewDecoder(reader).DecodeObject(&result); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Decode_MediumStruct_Stream_GoJson(b *testing.B) {
b.ReportAllocs()
reader := bytes.NewReader(MediumFixture)
for i := 0; i < b.N; i++ {
result := MediumPayload{}
reader.Reset(MediumFixture)
if err := gojson.NewDecoder(reader).Decode(&result); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Decode_LargeStruct_Unmarshal_EncodingJson(b *testing.B) {
b.ReportAllocs()
for n := 0; n < b.N; n++ {
result := LargePayload{}
if err := json.Unmarshal(LargeFixture, &result); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Decode_LargeStruct_Unmarshal_FastJson(b *testing.B) {
largeFixture := string(LargeFixture)
b.ReportAllocs()
for n := 0; n < b.N; n++ {
var p fastjson.Parser
if _, err := p.Parse(largeFixture); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Decode_LargeStruct_Unmarshal_SegmentioJson(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
result := LargePayload{}
if err := segmentiojson.Unmarshal(LargeFixture, &result); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Decode_LargeStruct_Unmarshal_JsonIter(b *testing.B) {
b.ReportAllocs()
for n := 0; n < b.N; n++ {
result := LargePayload{}
if err := jsoniter.Unmarshal(LargeFixture, &result); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Decode_LargeStruct_Unmarshal_GoJay(b *testing.B) {
b.ReportAllocs()
for n := 0; n < b.N; n++ {
result := LargePayload{}
if err := gojay.UnmarshalJSONObject(LargeFixture, &result); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Decode_LargeStruct_Unmarshal_GoJayUnsafe(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
result := LargePayload{}
if err := gojay.Unsafe.UnmarshalJSONObject(LargeFixture, &result); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Decode_LargeStruct_Unmarshal_GoJson(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
result := LargePayload{}
if err := gojson.Unmarshal(LargeFixture, &result); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Decode_LargeStruct_Unmarshal_GoJsonNoEscape(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
result := LargePayload{}
if err := gojson.UnmarshalNoEscape(LargeFixture, &result); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Decode_LargeStruct_Unmarshal_GoJsonFirstWinMode(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
result := LargePayload{}
if err := gojson.UnmarshalWithOption(
LargeFixture,
&result,
gojson.DecodeFieldPriorityFirstWin(),
); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Decode_LargeStruct_Unmarshal_GoJsonNoEscapeFirstWinMode(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
result := LargePayload{}
if err := gojson.UnmarshalNoEscape(
LargeFixture,
&result,
gojson.DecodeFieldPriorityFirstWin(),
); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Decode_LargeStruct_Stream_EncodingJson(b *testing.B) {
b.ReportAllocs()
reader := bytes.NewReader(LargeFixture)
for i := 0; i < b.N; i++ {
result := LargePayload{}
reader.Reset(LargeFixture)
if err := json.NewDecoder(reader).Decode(&result); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Decode_LargeStruct_Stream_SegmentioJson(b *testing.B) {
b.ReportAllocs()
reader := bytes.NewReader(LargeFixture)
for i := 0; i < b.N; i++ {
result := LargePayload{}
reader.Reset(LargeFixture)
if err := segmentiojson.NewDecoder(reader).Decode(&result); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Decode_LargeStruct_Stream_JsonIter(b *testing.B) {
b.ReportAllocs()
reader := bytes.NewReader(LargeFixture)
for i := 0; i < b.N; i++ {
result := LargePayload{}
reader.Reset(LargeFixture)
if err := jsoniter.NewDecoder(reader).Decode(&result); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Decode_LargeStruct_Stream_GoJay(b *testing.B) {
b.ReportAllocs()
reader := bytes.NewReader(LargeFixture)
for n := 0; n < b.N; n++ {
reader.Reset(LargeFixture)
result := LargePayload{}
if err := gojay.NewDecoder(reader).DecodeObject(&result); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Decode_LargeStruct_Stream_GoJson(b *testing.B) {
b.ReportAllocs()
reader := bytes.NewReader(LargeFixture)
for i := 0; i < b.N; i++ {
result := LargePayload{}
reader.Reset(LargeFixture)
if err := gojson.NewDecoder(reader).Decode(&result); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Decode_LargeStruct_Stream_GoJsonFirstWinMode(b *testing.B) {
b.ReportAllocs()
reader := bytes.NewReader(LargeFixture)
for i := 0; i < b.N; i++ {
result := LargePayload{}
reader.Reset(LargeFixture)
if err := gojson.NewDecoder(reader).DecodeWithOption(
&result,
gojson.DecodeFieldPriorityFirstWin(),
); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Decode_LargeSlice_EscapedString_GoJson(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
var v []string
if err := gojson.Unmarshal(LargeSliceEscapedString, &v); err != nil {
b.Fatal(err)
}
}
}
golang-github-goccy-go-json-0.10.3/benchmarks/encode_test.go 0000664 0000000 0000000 00000046442 14635552766 0023773 0 ustar 00root root 0000000 0000000 package benchmark
import (
"bytes"
"context"
"encoding/json"
"testing"
gojay "github.com/francoispqt/gojay"
gojson "github.com/goccy/go-json"
jsoniter "github.com/json-iterator/go"
"github.com/pquerna/ffjson/ffjson"
segmentiojson "github.com/segmentio/encoding/json"
"github.com/wI2L/jettison"
)
func Benchmark_Encode_SmallStruct_EncodingJson(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := json.Marshal(NewSmallPayload()); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_SmallStruct_FFJson(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := ffjson.Marshal(NewSmallPayloadFFJson()); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_SmallStruct_JsonIter(b *testing.B) {
var json = jsoniter.ConfigCompatibleWithStandardLibrary
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := json.Marshal(NewSmallPayload()); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_SmallStruct_EasyJson(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := NewSmallPayloadEasyJson().MarshalJSON(); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_SmallStruct_Jettison(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := jettison.Marshal(NewSmallPayload()); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_SmallStruct_GoJay(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := gojay.MarshalJSONObject(NewSmallPayload()); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_SmallStruct_SegmentioJson(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := segmentiojson.Marshal(NewSmallPayload()); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_SmallStruct_GoJsonColored(b *testing.B) {
colorOpt := gojson.Colorize(gojson.DefaultColorScheme)
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := gojson.MarshalWithOption(NewSmallPayload(), colorOpt); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_SmallStruct_GoJson(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := gojson.Marshal(NewSmallPayload()); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_SmallStruct_GoJsonNoEscape(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := gojson.MarshalNoEscape(NewSmallPayload()); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_SmallStructCached_EncodingJson(b *testing.B) {
cached := NewSmallPayload()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := json.Marshal(cached); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_SmallStructCached_FFJson(b *testing.B) {
cached := NewSmallPayloadFFJson()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := ffjson.Marshal(cached); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_SmallStructCached_JsonIter(b *testing.B) {
var json = jsoniter.ConfigCompatibleWithStandardLibrary
cached := NewSmallPayload()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := json.Marshal(cached); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_SmallStructCached_EasyJson(b *testing.B) {
cached := NewSmallPayloadEasyJson()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := cached.MarshalJSON(); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_SmallStructCached_Jettison(b *testing.B) {
cached := NewSmallPayload()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := jettison.Marshal(cached); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_SmallStructCached_GoJay(b *testing.B) {
cached := NewSmallPayload()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := gojay.MarshalJSONObject(cached); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_SmallStructCached_SegmentioJson(b *testing.B) {
cached := NewSmallPayload()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := segmentiojson.Marshal(cached); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_SmallStructCached_GoJsonColored(b *testing.B) {
cached := NewSmallPayload()
colorOpt := gojson.Colorize(gojson.DefaultColorScheme)
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := gojson.MarshalWithOption(cached, colorOpt); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_SmallStructCached_GoJson(b *testing.B) {
cached := NewSmallPayload()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := gojson.Marshal(cached); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_SmallStructCached_GoJsonNoEscape(b *testing.B) {
cached := NewSmallPayload()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := gojson.MarshalNoEscape(cached); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_MediumStruct_EncodingJson(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := json.Marshal(NewMediumPayload()); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_MediumStruct_JsonIter(b *testing.B) {
var json = jsoniter.ConfigCompatibleWithStandardLibrary
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := json.Marshal(NewMediumPayload()); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_MediumStruct_EasyJson(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := NewMediumPayloadEasyJson().MarshalJSON(); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_MediumStruct_Jettison(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := jettison.Marshal(NewMediumPayload()); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_MediumStruct_GoJay(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := gojay.MarshalJSONObject(NewMediumPayload()); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_MediumStruct_SegmentioJson(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := segmentiojson.Marshal(NewMediumPayload()); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_MediumStruct_GoJsonColored(b *testing.B) {
colorOpt := gojson.Colorize(gojson.DefaultColorScheme)
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := gojson.MarshalWithOption(NewMediumPayload(), colorOpt); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_MediumStruct_GoJson(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := gojson.Marshal(NewMediumPayload()); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_MediumStruct_GoJsonNoEscape(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := gojson.MarshalNoEscape(NewMediumPayload()); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_MediumStructCached_EncodingJson(b *testing.B) {
cached := NewMediumPayload()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := json.Marshal(cached); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_MediumStructCached_JsonIter(b *testing.B) {
var json = jsoniter.ConfigCompatibleWithStandardLibrary
cached := NewMediumPayload()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := json.Marshal(cached); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_MediumStructCached_EasyJson(b *testing.B) {
cached := NewMediumPayloadEasyJson()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := cached.MarshalJSON(); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_MediumStructCached_Jettison(b *testing.B) {
cached := NewMediumPayload()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := jettison.Marshal(cached); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_MediumStructCached_GoJay(b *testing.B) {
cached := NewMediumPayload()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := gojay.MarshalJSONObject(cached); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_MediumStructCached_SegmentioJson(b *testing.B) {
cached := NewMediumPayload()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := segmentiojson.Marshal(cached); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_MediumStructCached_GoJsonColored(b *testing.B) {
cached := NewMediumPayload()
colorOpt := gojson.Colorize(gojson.DefaultColorScheme)
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := gojson.MarshalWithOption(cached, colorOpt); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_MediumStructCached_GoJson(b *testing.B) {
cached := NewMediumPayload()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := gojson.Marshal(cached); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_MediumStructCached_GoJsonNoEscape(b *testing.B) {
cached := NewMediumPayload()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := gojson.MarshalNoEscape(cached); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_LargeStruct_EncodingJson(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := json.Marshal(NewLargePayload()); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_LargeStruct_JsonIter(b *testing.B) {
var json = jsoniter.ConfigCompatibleWithStandardLibrary
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := json.Marshal(NewLargePayload()); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_LargeStruct_EasyJson(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := NewLargePayloadEasyJson().MarshalJSON(); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_LargeStruct_Jettison(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := jettison.Marshal(NewLargePayload()); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_LargeStruct_GoJay(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := gojay.MarshalJSONObject(NewLargePayload()); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_LargeStruct_SegmentioJson(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := segmentiojson.Marshal(NewLargePayload()); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_LargeStruct_GoJsonColored(b *testing.B) {
colorOpt := gojson.Colorize(gojson.DefaultColorScheme)
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := gojson.MarshalWithOption(NewLargePayload(), colorOpt); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_LargeStruct_GoJson(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := gojson.Marshal(NewLargePayload()); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_LargeStruct_GoJsonNoEscape(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := gojson.MarshalNoEscape(NewLargePayload()); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_LargeStructCached_EncodingJson(b *testing.B) {
cached := NewLargePayload()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := json.Marshal(cached); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_LargeStructCached_JsonIter(b *testing.B) {
var json = jsoniter.ConfigCompatibleWithStandardLibrary
cached := NewLargePayload()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := json.Marshal(cached); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_LargeStructCached_EasyJson(b *testing.B) {
cached := NewLargePayloadEasyJson()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := cached.MarshalJSON(); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_LargeStructCached_Jettison(b *testing.B) {
cached := NewLargePayload()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := jettison.Marshal(cached); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_LargeStructCached_GoJay(b *testing.B) {
cached := NewLargePayload()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := gojay.MarshalJSONObject(cached); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_LargeStructCached_SegmentioJson(b *testing.B) {
cached := NewLargePayload()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := segmentiojson.Marshal(cached); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_LargeStructCached_GoJsonColored(b *testing.B) {
cached := NewLargePayload()
colorOpt := gojson.Colorize(gojson.DefaultColorScheme)
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := gojson.MarshalWithOption(cached, colorOpt); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_LargeStructCached_GoJson(b *testing.B) {
cached := NewLargePayload()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := gojson.Marshal(cached); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_LargeStructCached_GoJsonNoEscape(b *testing.B) {
cached := NewLargePayload()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := gojson.MarshalNoEscape(cached); err != nil {
b.Fatal(err)
}
}
}
func benchMapValue() map[string]interface{} {
return map[string]interface{}{
"a": 1,
"b": 2.1,
"c": "hello",
"d": struct {
V int
}{
V: 1,
},
"e": true,
}
}
func Benchmark_Encode_MapInterface_EncodingJson(b *testing.B) {
v := benchMapValue()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := json.Marshal(v); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_MapInterface_JsonIter(b *testing.B) {
v := benchMapValue()
var json = jsoniter.ConfigCompatibleWithStandardLibrary
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := json.Marshal(v); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_MapInterface_Jettison(b *testing.B) {
v := benchMapValue()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := jettison.Marshal(v); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_MapInterface_SegmentioJson(b *testing.B) {
v := benchMapValue()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := segmentiojson.Marshal(v); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_MapInterface_GoJson(b *testing.B) {
v := benchMapValue()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := gojson.Marshal(v); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_Interface_SegmentioJson(b *testing.B) {
v := []interface{}{1}
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := segmentiojson.Marshal(v); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_Interface_GoJson(b *testing.B) {
v := []interface{}{1}
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := gojson.Marshal(v); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_Bool_EncodingJson(b *testing.B) {
b.ReportAllocs()
var buf bytes.Buffer
enc := json.NewEncoder(&buf)
for i := 0; i < b.N; i++ {
if err := enc.Encode(true); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_Bool_JsonIter(b *testing.B) {
var json = jsoniter.ConfigCompatibleWithStandardLibrary
b.ReportAllocs()
var buf bytes.Buffer
enc := json.NewEncoder(&buf)
for i := 0; i < b.N; i++ {
if err := enc.Encode(true); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_Bool_SegmentioJson(b *testing.B) {
b.ReportAllocs()
var buf bytes.Buffer
enc := segmentiojson.NewEncoder(&buf)
for i := 0; i < b.N; i++ {
if err := enc.Encode(true); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_Bool_GoJson(b *testing.B) {
b.ReportAllocs()
var buf bytes.Buffer
enc := gojson.NewEncoder(&buf)
for i := 0; i < b.N; i++ {
if err := enc.Encode(true); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Marshal_Bool_EncodingJson(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := json.Marshal(true); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Marshal_Bool_JsonIter(b *testing.B) {
var json = jsoniter.ConfigCompatibleWithStandardLibrary
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := json.Marshal(true); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Marshal_Bool_Jettison(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := jettison.Marshal(true); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Marshal_Bool_SegmentioJson(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := segmentiojson.Marshal(true); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Marshal_Bool_GoJson(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := gojson.Marshal(true); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_Int_EncodingJson(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := json.Marshal(1); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_Int_JsonIter(b *testing.B) {
var json = jsoniter.ConfigCompatibleWithStandardLibrary
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := json.Marshal(1); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_Int_Jettison(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := jettison.Marshal(1); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_Int_SegmentioJson(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := segmentiojson.Marshal(1); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_Int_GoJson(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := gojson.Marshal(1); err != nil {
b.Fatal(err)
}
}
}
type marshaler struct{}
func (*marshaler) MarshalJSON() ([]byte, error) {
return []byte(`"hello"`), nil
}
func Benchmark_Encode_MarshalJSON_EncodingJson(b *testing.B) {
v := &marshaler{}
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := json.Marshal(v); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_MarshalJSON_JsonIter(b *testing.B) {
v := &marshaler{}
var json = jsoniter.ConfigCompatibleWithStandardLibrary
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := json.Marshal(v); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_MarshalJSON_Jettison(b *testing.B) {
v := &marshaler{}
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := jettison.Marshal(v); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_MarshalJSON_SegmentioJson(b *testing.B) {
v := &marshaler{}
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := segmentiojson.Marshal(v); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_MarshalJSON_GoJson(b *testing.B) {
v := &marshaler{}
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := gojson.Marshal(v); err != nil {
b.Fatal(err)
}
}
}
type queryTestX struct {
XA int
XB string
XC *queryTestY
XD bool
XE float32
}
type queryTestY struct {
YA int
YB string
YC bool
YD float32
}
func Benchmark_Encode_FilterByMap(b *testing.B) {
v := &queryTestX{
XA: 1,
XB: "xb",
XC: &queryTestY{
YA: 2,
YB: "yb",
YC: true,
YD: 4,
},
XD: true,
XE: 5,
}
b.ReportAllocs()
for i := 0; i < b.N; i++ {
filteredMap := map[string]interface{}{
"XA": v.XA,
"XB": v.XB,
"XC": map[string]interface{}{
"YA": v.XC.YA,
"YB": v.XC.YB,
},
}
if _, err := gojson.Marshal(filteredMap); err != nil {
b.Fatal(err)
}
}
}
func Benchmark_Encode_FilterByFieldQuery(b *testing.B) {
query, err := gojson.BuildFieldQuery(
"XA",
"XB",
gojson.BuildSubFieldQuery("XC").Fields(
"YA",
"YB",
),
)
if err != nil {
b.Fatal(err)
}
v := &queryTestX{
XA: 1,
XB: "xb",
XC: &queryTestY{
YA: 2,
YB: "yb",
YC: true,
YD: 4,
},
XD: true,
XE: 5,
}
ctx := gojson.SetFieldQueryToContext(context.Background(), query)
b.ReportAllocs()
for i := 0; i < b.N; i++ {
if _, err := gojson.MarshalContext(ctx, v); err != nil {
b.Fatal(err)
}
}
}
golang-github-goccy-go-json-0.10.3/benchmarks/go.mod 0000664 0000000 0000000 00000001177 14635552766 0022252 0 ustar 00root root 0000000 0000000 module benchmark
go 1.19
require (
github.com/francoispqt/gojay v1.2.13
github.com/goccy/go-json v0.0.0-00010101000000-000000000000
github.com/json-iterator/go v1.1.10
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe
github.com/pquerna/ffjson v0.0.0-20190930134022-aa0246cd15f7
github.com/segmentio/encoding v0.2.4
github.com/valyala/fastjson v1.6.3
github.com/wI2L/jettison v0.7.1
)
require (
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.1 // indirect
github.com/stretchr/testify v1.7.0 // indirect
)
replace github.com/goccy/go-json => ../
golang-github-goccy-go-json-0.10.3/benchmarks/go.sum 0000664 0000000 0000000 00000047224 14635552766 0022302 0 ustar 00root root 0000000 0000000 cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.37.0/go.mod h1:TS1dMSSfndXH133OKGwekG838Om/cQT0BUHV3HcBgoo=
dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU=
dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU=
dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4=
dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU=
git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk=
github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe h1:W/GaMY0y69G4cFlmsC6B9sbuo2fP8OFP1ABjt4kPz+w=
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pquerna/ffjson v0.0.0-20190930134022-aa0246cd15f7 h1:xoIK0ctDddBMnc74udxJYBqlo9Ylnsp1waqjLsnef20=
github.com/pquerna/ffjson v0.0.0-20190930134022-aa0246cd15f7/go.mod h1:YARuvh7BUWHNhzDq2OM5tzR2RiCcN2D7sapiKyCel/M=
github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/segmentio/encoding v0.1.10/go.mod h1:RWhr02uzMB9gQC1x+MfYxedtmBibb9cZ6Vv9VxRSSbw=
github.com/segmentio/encoding v0.2.4 h1:TQRXhTlXj4urZe3Z5QVgxs9Ad1i7GYHg9peAtjOPe28=
github.com/segmentio/encoding v0.2.4/go.mod h1:MJjRE6bMDocliO2FyFC2Dusp+uYdBfHWh5Bw7QyExto=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY=
github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM=
github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0=
github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ=
github.com/shurcooL/gofontwoff v0.0.0-20180329035133-29b52fc0a18d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw=
github.com/shurcooL/gopherjslib v0.0.0-20160914041154-feb6d3990c2c/go.mod h1:8d3azKNyqcHP1GaQE/c6dDgjkgSx2BZ4IoEi4F1reUI=
github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU=
github.com/shurcooL/highlight_go v0.0.0-20181028180052-98c3abbbae20/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag=
github.com/shurcooL/home v0.0.0-20181020052607-80b7ffcb30f9/go.mod h1:+rgNQw2P9ARFAs37qieuu7ohDNQ3gds9msbT2yn85sg=
github.com/shurcooL/htmlg v0.0.0-20170918183704-d01228ac9e50/go.mod h1:zPn1wHpTIePGnXSHpsVPWEktKXHr6+SS6x/IKRb7cpw=
github.com/shurcooL/httperror v0.0.0-20170206035902-86b7830d14cc/go.mod h1:aYMfkZ6DWSJPJ6c4Wwz3QtW22G7mf/PEgaB9k/ik5+Y=
github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
github.com/shurcooL/httpgzip v0.0.0-20180522190206-b1c53ac65af9/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q=
github.com/shurcooL/issues v0.0.0-20181008053335-6292fdc1e191/go.mod h1:e2qWDig5bLteJ4fwvDAc2NHzqFEthkqn7aOZAOpj+PQ=
github.com/shurcooL/issuesapp v0.0.0-20180602232740-048589ce2241/go.mod h1:NPpHK2TI7iSaM0buivtFUc9offApnI0Alt/K8hcHy0I=
github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122/go.mod h1:b5uSkrEVM1jQUspwbixRBhaIjIzL2xazXp6kntxYle0=
github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ=
github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk=
github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4=
github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw=
github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE=
github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
github.com/valyala/fastjson v1.6.3 h1:tAKFnnwmeMGPbwJ7IwxcTPCNr3uIzoIj3/Fh90ra4xc=
github.com/valyala/fastjson v1.6.3/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=
github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM=
github.com/wI2L/jettison v0.7.1 h1:XNq/WvSOAiJhFww9F5JZZcBZtKFL2Y/9WHHEHLDq9TE=
github.com/wI2L/jettison v0.7.1/go.mod h1:dj49nOP41M7x6Jql62BqqF/+nW+XJgBaWzJR0hd6M84=
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg=
google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck=
sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0=
golang-github-goccy-go-json-0.10.3/benchmarks/large_payload.go 0000664 0000000 0000000 00000076443 14635552766 0024306 0 ustar 00root root 0000000 0000000 package benchmark
import (
"strconv"
"strings"
"github.com/francoispqt/gojay"
)
type DSUser struct {
Username string
}
func (m *DSUser) UnmarshalJSONObject(dec *gojay.Decoder, key string) error {
switch key {
case "username":
return dec.AddString(&m.Username)
}
return nil
}
func (m *DSUser) NKeys() int {
return 1
}
func (m *DSUser) IsNil() bool {
return m == nil
}
func (m *DSUser) MarshalJSONObject(enc *gojay.Encoder) {
enc.AddStringKey("username", m.Username)
}
type DSTopic struct {
Id int
Slug string
}
func (m *DSTopic) UnmarshalJSONObject(dec *gojay.Decoder, key string) error {
switch key {
case "id":
return dec.AddInt(&m.Id)
case "slug":
return dec.AddString(&m.Slug)
}
return nil
}
func (m *DSTopic) NKeys() int {
return 2
}
func (m *DSTopic) IsNil() bool {
return m == nil
}
func (m *DSTopic) MarshalJSONObject(enc *gojay.Encoder) {
enc.AddIntKey("id", m.Id)
enc.AddStringKey("slug", m.Slug)
}
type DSTopics []*DSTopic
func (t *DSTopics) UnmarshalJSONArray(dec *gojay.Decoder) error {
dsTopic := &DSTopic{}
*t = append(*t, dsTopic)
return dec.AddObject(dsTopic)
}
func (m *DSTopics) MarshalJSONArray(enc *gojay.Encoder) {
for _, e := range *m {
enc.AddObject(e)
}
}
func (m *DSTopics) IsNil() bool {
return m == nil
}
type DSTopicsList struct {
Topics DSTopics
MoreTopicsUrl string
}
func (m *DSTopicsList) UnmarshalJSONObject(dec *gojay.Decoder, key string) error {
switch key {
case "topics":
m.Topics = DSTopics{}
return dec.AddArray(&m.Topics)
case "more_topics_url":
return dec.AddString(&m.MoreTopicsUrl)
}
return nil
}
func (m *DSTopicsList) NKeys() int {
return 2
}
func (m *DSTopicsList) IsNil() bool {
return m == nil
}
func (m *DSTopicsList) MarshalJSONObject(enc *gojay.Encoder) {
enc.AddArrayKey("users", &m.Topics)
enc.AddStringKey("more_topics_url", m.MoreTopicsUrl)
}
type DSUsers []*DSUser
func (t *DSUsers) UnmarshalJSONArray(dec *gojay.Decoder) error {
dsUser := DSUser{}
*t = append(*t, &dsUser)
return dec.AddObject(&dsUser)
}
func (m *DSUsers) MarshalJSONArray(enc *gojay.Encoder) {
for _, e := range *m {
enc.AddObject(e)
}
}
func (m *DSUsers) IsNil() bool {
return m == nil
}
type LargePayload struct {
Users DSUsers
Topics *DSTopicsList
}
//easyjson:json
type LargePayloadEasyJson struct {
Users DSUsers
Topics *DSTopicsList
}
func (m *LargePayload) UnmarshalJSONObject(dec *gojay.Decoder, key string) error {
switch key {
case "users":
return dec.AddArray(&m.Users)
case "topics":
m.Topics = &DSTopicsList{}
return dec.AddObject(m.Topics)
}
return nil
}
func (m *LargePayload) NKeys() int {
return 2
}
func (m *LargePayload) MarshalJSONObject(enc *gojay.Encoder) {
enc.AddArrayKey("users", &m.Users)
enc.AddObjectKey("topics", m.Topics)
}
func (m *LargePayload) IsNil() bool {
return m == nil
}
var LargeFixture = []byte(`
{"users":[{"id":-1,"username":"system","avatar_template":"/user_avatar/discourse.metabase.com/system/{size}/6_1.png"},{"id":89,"username":"zergot","avatar_template":"https://avatars.discourse.org/v2/letter/z/0ea827/{size}.png"},{"id":1,"username":"sameer","avatar_template":"https://avatars.discourse.org/v2/letter/s/bbce88/{size}.png"},{"id":84,"username":"HenryMirror","avatar_template":"https://avatars.discourse.org/v2/letter/h/ecd19e/{size}.png"},{"id":73,"username":"fimp","avatar_template":"https://avatars.discourse.org/v2/letter/f/ee59a6/{size}.png"},{"id":14,"username":"agilliland","avatar_template":"/user_avatar/discourse.metabase.com/agilliland/{size}/26_1.png"},{"id":87,"username":"amir","avatar_template":"https://avatars.discourse.org/v2/letter/a/c37758/{size}.png"},{"id":82,"username":"waseem","avatar_template":"https://avatars.discourse.org/v2/letter/w/9dc877/{size}.png"},{"id":78,"username":"tovenaar","avatar_template":"https://avatars.discourse.org/v2/letter/t/9de0a6/{size}.png"},{"id":74,"username":"Ben","avatar_template":"https://avatars.discourse.org/v2/letter/b/df788c/{size}.png"},{"id":71,"username":"MarkLaFay","avatar_template":"https://avatars.discourse.org/v2/letter/m/3bc359/{size}.png"},{"id":72,"username":"camsaul","avatar_template":"/user_avatar/discourse.metabase.com/camsaul/{size}/70_1.png"},{"id":53,"username":"mhjb","avatar_template":"/user_avatar/discourse.metabase.com/mhjb/{size}/54_1.png"},{"id":58,"username":"jbwiv","avatar_template":"https://avatars.discourse.org/v2/letter/j/6bbea6/{size}.png"},{"id":70,"username":"Maggs","avatar_template":"https://avatars.discourse.org/v2/letter/m/bbce88/{size}.png"},{"id":69,"username":"andrefaria","avatar_template":"/user_avatar/discourse.metabase.com/andrefaria/{size}/65_1.png"},{"id":60,"username":"bencarter78","avatar_template":"/user_avatar/discourse.metabase.com/bencarter78/{size}/59_1.png"},{"id":55,"username":"vikram","avatar_template":"https://avatars.discourse.org/v2/letter/v/e47774/{size}.png"},{"id":68,"username":"edchan77","avatar_template":"/user_avatar/discourse.metabase.com/edchan77/{size}/66_1.png"},{"id":9,"username":"karthikd","avatar_template":"https://avatars.discourse.org/v2/letter/k/cab0a1/{size}.png"},{"id":23,"username":"arthurz","avatar_template":"/user_avatar/discourse.metabase.com/arthurz/{size}/32_1.png"},{"id":3,"username":"tom","avatar_template":"/user_avatar/discourse.metabase.com/tom/{size}/21_1.png"},{"id":50,"username":"LeoNogueira","avatar_template":"/user_avatar/discourse.metabase.com/leonogueira/{size}/52_1.png"},{"id":66,"username":"ss06vi","avatar_template":"https://avatars.discourse.org/v2/letter/s/3ab097/{size}.png"},{"id":34,"username":"mattcollins","avatar_template":"/user_avatar/discourse.metabase.com/mattcollins/{size}/41_1.png"},{"id":51,"username":"krmmalik","avatar_template":"/user_avatar/discourse.metabase.com/krmmalik/{size}/53_1.png"},{"id":46,"username":"odysseas","avatar_template":"https://avatars.discourse.org/v2/letter/o/5f8ce5/{size}.png"},{"id":5,"username":"jonthewayne","avatar_template":"/user_avatar/discourse.metabase.com/jonthewayne/{size}/18_1.png"},{"id":11,"username":"anandiyer","avatar_template":"/user_avatar/discourse.metabase.com/anandiyer/{size}/23_1.png"},{"id":25,"username":"alnorth","avatar_template":"/user_avatar/discourse.metabase.com/alnorth/{size}/34_1.png"},{"id":52,"username":"j_at_svg","avatar_template":"https://avatars.discourse.org/v2/letter/j/96bed5/{size}.png"},{"id":42,"username":"styts","avatar_template":"/user_avatar/discourse.metabase.com/styts/{size}/47_1.png"}],"topics":{"can_create_topic":false,"more_topics_url":"/c/uncategorized/l/latest?page=1","draft":null,"draft_key":"new_topic","draft_sequence":null,"per_page":30,"topics":[{"id":8,"title":"Welcome to Metabase's Discussion Forum","fancy_title":"Welcome to Metabase’s Discussion Forum","slug":"welcome-to-metabases-discussion-forum","posts_count":1,"reply_count":0,"highest_post_number":1,"image_url":"/images/welcome/discourse-edit-post-animated.gif","created_at":"2015-10-17T00:14:49.526Z","last_posted_at":"2015-10-17T00:14:49.557Z","bumped":true,"bumped_at":"2015-10-21T02:32:22.486Z","unseen":false,"pinned":true,"unpinned":null,"excerpt":"Welcome to Metabase's discussion forum. This is a place to get help on installation, setting up as well as sharing tips and tricks.","visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":197,"like_count":0,"has_summary":false,"archetype":"regular","last_poster_username":"system","category_id":1,"pinned_globally":true,"posters":[{"extras":"latest single","description":"Original Poster, Most Recent Poster","user_id":-1}]},{"id":169,"title":"Formatting Dates","fancy_title":"Formatting Dates","slug":"formatting-dates","posts_count":1,"reply_count":0,"highest_post_number":1,"image_url":null,"created_at":"2016-01-14T06:30:45.311Z","last_posted_at":"2016-01-14T06:30:45.397Z","bumped":true,"bumped_at":"2016-01-14T06:30:45.397Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":11,"like_count":0,"has_summary":false,"archetype":"regular","last_poster_username":"zergot","category_id":1,"pinned_globally":false,"posters":[{"extras":"latest single","description":"Original Poster, Most Recent Poster","user_id":89}]},{"id":168,"title":"Setting for google api key","fancy_title":"Setting for google api key","slug":"setting-for-google-api-key","posts_count":2,"reply_count":0,"highest_post_number":2,"image_url":null,"created_at":"2016-01-13T17:14:31.799Z","last_posted_at":"2016-01-14T06:24:03.421Z","bumped":true,"bumped_at":"2016-01-14T06:24:03.421Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":16,"like_count":0,"has_summary":false,"archetype":"regular","last_poster_username":"zergot","category_id":1,"pinned_globally":false,"posters":[{"extras":"latest single","description":"Original Poster, Most Recent Poster","user_id":89}]},{"id":167,"title":"Cannot see non-US timezones on the admin","fancy_title":"Cannot see non-US timezones on the admin","slug":"cannot-see-non-us-timezones-on-the-admin","posts_count":1,"reply_count":0,"highest_post_number":1,"image_url":null,"created_at":"2016-01-13T17:07:36.764Z","last_posted_at":"2016-01-13T17:07:36.831Z","bumped":true,"bumped_at":"2016-01-13T17:07:36.831Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":11,"like_count":0,"has_summary":false,"archetype":"regular","last_poster_username":"zergot","category_id":1,"pinned_globally":false,"posters":[{"extras":"latest single","description":"Original Poster, Most Recent Poster","user_id":89}]},{"id":164,"title":"External (Metabase level) linkages in data schema","fancy_title":"External (Metabase level) linkages in data schema","slug":"external-metabase-level-linkages-in-data-schema","posts_count":4,"reply_count":1,"highest_post_number":4,"image_url":null,"created_at":"2016-01-11T13:51:02.286Z","last_posted_at":"2016-01-12T11:06:37.259Z","bumped":true,"bumped_at":"2016-01-12T11:06:37.259Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":32,"like_count":0,"has_summary":false,"archetype":"regular","last_poster_username":"zergot","category_id":1,"pinned_globally":false,"posters":[{"extras":"latest","description":"Original Poster, Most Recent Poster","user_id":89},{"extras":null,"description":"Frequent Poster","user_id":1}]},{"id":155,"title":"Query working on \"Questions\" but not in \"Pulses\"","fancy_title":"Query working on “Questions” but not in “Pulses”","slug":"query-working-on-questions-but-not-in-pulses","posts_count":3,"reply_count":0,"highest_post_number":3,"image_url":null,"created_at":"2016-01-01T14:06:10.083Z","last_posted_at":"2016-01-08T22:37:51.772Z","bumped":true,"bumped_at":"2016-01-08T22:37:51.772Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":72,"like_count":0,"has_summary":false,"archetype":"regular","last_poster_username":"agilliland","category_id":1,"pinned_globally":false,"posters":[{"extras":null,"description":"Original Poster","user_id":84},{"extras":null,"description":"Frequent Poster","user_id":73},{"extras":"latest","description":"Most Recent Poster","user_id":14}]},{"id":161,"title":"Pulses posted to Slack don't show question output","fancy_title":"Pulses posted to Slack don’t show question output","slug":"pulses-posted-to-slack-dont-show-question-output","posts_count":2,"reply_count":0,"highest_post_number":2,"image_url":"/uploads/default/original/1X/9d2806517bf3598b10be135b2c58923b47ba23e7.png","created_at":"2016-01-08T22:09:58.205Z","last_posted_at":"2016-01-08T22:28:44.685Z","bumped":true,"bumped_at":"2016-01-08T22:28:44.685Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":34,"like_count":0,"has_summary":false,"archetype":"regular","last_poster_username":"sameer","category_id":1,"pinned_globally":false,"posters":[{"extras":null,"description":"Original Poster","user_id":87},{"extras":"latest","description":"Most Recent Poster","user_id":1}]},{"id":152,"title":"Should we build Kafka connecter or Kafka plugin","fancy_title":"Should we build Kafka connecter or Kafka plugin","slug":"should-we-build-kafka-connecter-or-kafka-plugin","posts_count":4,"reply_count":1,"highest_post_number":4,"image_url":null,"created_at":"2015-12-28T20:37:23.501Z","last_posted_at":"2015-12-31T18:16:45.477Z","bumped":true,"bumped_at":"2015-12-31T18:16:45.477Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":84,"like_count":0,"has_summary":false,"archetype":"regular","last_poster_username":"sameer","category_id":1,"pinned_globally":false,"posters":[{"extras":null,"description":"Original Poster","user_id":82},{"extras":"latest","description":"Most Recent Poster, Frequent Poster","user_id":1}]},{"id":147,"title":"Change X and Y on graph","fancy_title":"Change X and Y on graph","slug":"change-x-and-y-on-graph","posts_count":1,"reply_count":0,"highest_post_number":1,"image_url":null,"created_at":"2015-12-21T17:52:46.581Z","last_posted_at":"2015-12-21T17:52:46.684Z","bumped":true,"bumped_at":"2015-12-21T18:19:13.003Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":68,"like_count":0,"has_summary":false,"archetype":"regular","last_poster_username":"tovenaar","category_id":1,"pinned_globally":false,"posters":[{"extras":"latest single","description":"Original Poster, Most Recent Poster","user_id":78}]},{"id":142,"title":"Issues sending mail via office365 relay","fancy_title":"Issues sending mail via office365 relay","slug":"issues-sending-mail-via-office365-relay","posts_count":5,"reply_count":2,"highest_post_number":5,"image_url":null,"created_at":"2015-12-16T10:38:47.315Z","last_posted_at":"2015-12-21T09:26:27.167Z","bumped":true,"bumped_at":"2015-12-21T09:26:27.167Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":122,"like_count":0,"has_summary":false,"archetype":"regular","last_poster_username":"Ben","category_id":1,"pinned_globally":false,"posters":[{"extras":"latest","description":"Original Poster, Most Recent Poster","user_id":74},{"extras":null,"description":"Frequent Poster","user_id":1}]},{"id":137,"title":"I see triplicates of my mongoDB collections","fancy_title":"I see triplicates of my mongoDB collections","slug":"i-see-triplicates-of-my-mongodb-collections","posts_count":3,"reply_count":0,"highest_post_number":3,"image_url":null,"created_at":"2015-12-14T13:33:03.426Z","last_posted_at":"2015-12-17T18:40:05.487Z","bumped":true,"bumped_at":"2015-12-17T18:40:05.487Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":97,"like_count":0,"has_summary":false,"archetype":"regular","last_poster_username":"MarkLaFay","category_id":1,"pinned_globally":false,"posters":[{"extras":"latest","description":"Original Poster, Most Recent Poster","user_id":71},{"extras":null,"description":"Frequent Poster","user_id":14}]},{"id":140,"title":"Google Analytics plugin","fancy_title":"Google Analytics plugin","slug":"google-analytics-plugin","posts_count":1,"reply_count":0,"highest_post_number":1,"image_url":null,"created_at":"2015-12-15T13:00:55.644Z","last_posted_at":"2015-12-15T13:00:55.705Z","bumped":true,"bumped_at":"2015-12-15T13:00:55.705Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":105,"like_count":0,"has_summary":false,"archetype":"regular","last_poster_username":"fimp","category_id":1,"pinned_globally":false,"posters":[{"extras":"latest single","description":"Original Poster, Most Recent Poster","user_id":73}]},{"id":138,"title":"With-mongo-connection failed: bad connection details:","fancy_title":"With-mongo-connection failed: bad connection details:","slug":"with-mongo-connection-failed-bad-connection-details","posts_count":1,"reply_count":0,"highest_post_number":1,"image_url":null,"created_at":"2015-12-14T17:28:11.041Z","last_posted_at":"2015-12-14T17:28:11.111Z","bumped":true,"bumped_at":"2015-12-14T17:28:11.111Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":56,"like_count":0,"has_summary":false,"archetype":"regular","last_poster_username":"MarkLaFay","category_id":1,"pinned_globally":false,"posters":[{"extras":"latest single","description":"Original Poster, Most Recent Poster","user_id":71}]},{"id":133,"title":"\"We couldn't understand your question.\" when I query mongoDB","fancy_title":"“We couldn’t understand your question.” when I query mongoDB","slug":"we-couldnt-understand-your-question-when-i-query-mongodb","posts_count":3,"reply_count":0,"highest_post_number":3,"image_url":null,"created_at":"2015-12-11T17:38:30.576Z","last_posted_at":"2015-12-14T13:31:26.395Z","bumped":true,"bumped_at":"2015-12-14T13:31:26.395Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":107,"like_count":0,"has_summary":false,"archetype":"regular","last_poster_username":"MarkLaFay","category_id":1,"pinned_globally":false,"posters":[{"extras":"latest","description":"Original Poster, Most Recent Poster","user_id":71},{"extras":null,"description":"Frequent Poster","user_id":72}]},{"id":129,"title":"My bar charts are all thin","fancy_title":"My bar charts are all thin","slug":"my-bar-charts-are-all-thin","posts_count":4,"reply_count":1,"highest_post_number":4,"image_url":"/uploads/default/original/1X/41bcf3b2a00dc7cfaff01cb3165d35d32a85bf1d.png","created_at":"2015-12-09T22:09:56.394Z","last_posted_at":"2015-12-11T19:00:45.289Z","bumped":true,"bumped_at":"2015-12-11T19:00:45.289Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":116,"like_count":0,"has_summary":false,"archetype":"regular","last_poster_username":"mhjb","category_id":1,"pinned_globally":false,"posters":[{"extras":"latest","description":"Original Poster, Most Recent Poster","user_id":53},{"extras":null,"description":"Frequent Poster","user_id":1}]},{"id":106,"title":"What is the expected return order of columns for graphing results when using raw SQL?","fancy_title":"What is the expected return order of columns for graphing results when using raw SQL?","slug":"what-is-the-expected-return-order-of-columns-for-graphing-results-when-using-raw-sql","posts_count":3,"reply_count":0,"highest_post_number":3,"image_url":null,"created_at":"2015-11-24T19:07:14.561Z","last_posted_at":"2015-12-11T17:04:14.149Z","bumped":true,"bumped_at":"2015-12-11T17:04:14.149Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":153,"like_count":0,"has_summary":false,"archetype":"regular","last_poster_username":"jbwiv","category_id":1,"pinned_globally":false,"posters":[{"extras":"latest","description":"Original Poster, Most Recent Poster","user_id":58},{"extras":null,"description":"Frequent Poster","user_id":14}]},{"id":131,"title":"Set site url from admin panel","fancy_title":"Set site url from admin panel","slug":"set-site-url-from-admin-panel","posts_count":2,"reply_count":0,"highest_post_number":2,"image_url":null,"created_at":"2015-12-10T06:22:46.042Z","last_posted_at":"2015-12-10T19:12:57.449Z","bumped":true,"bumped_at":"2015-12-10T19:12:57.449Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":77,"like_count":0,"has_summary":false,"archetype":"regular","last_poster_username":"sameer","category_id":1,"pinned_globally":false,"posters":[{"extras":null,"description":"Original Poster","user_id":70},{"extras":"latest","description":"Most Recent Poster","user_id":1}]},{"id":127,"title":"Internationalization (i18n)","fancy_title":"Internationalization (i18n)","slug":"internationalization-i18n","posts_count":2,"reply_count":0,"highest_post_number":2,"image_url":null,"created_at":"2015-12-08T16:55:37.397Z","last_posted_at":"2015-12-09T16:49:55.816Z","bumped":true,"bumped_at":"2015-12-09T16:49:55.816Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":85,"like_count":0,"has_summary":false,"archetype":"regular","last_poster_username":"agilliland","category_id":1,"pinned_globally":false,"posters":[{"extras":null,"description":"Original Poster","user_id":69},{"extras":"latest","description":"Most Recent Poster","user_id":14}]},{"id":109,"title":"Returning raw data with no filters always returns We couldn't understand your question","fancy_title":"Returning raw data with no filters always returns We couldn’t understand your question","slug":"returning-raw-data-with-no-filters-always-returns-we-couldnt-understand-your-question","posts_count":3,"reply_count":1,"highest_post_number":3,"image_url":null,"created_at":"2015-11-25T21:35:01.315Z","last_posted_at":"2015-12-09T10:26:12.255Z","bumped":true,"bumped_at":"2015-12-09T10:26:12.255Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":133,"like_count":0,"has_summary":false,"archetype":"regular","last_poster_username":"bencarter78","category_id":1,"pinned_globally":false,"posters":[{"extras":"latest","description":"Original Poster, Most Recent Poster","user_id":60},{"extras":null,"description":"Frequent Poster","user_id":14}]},{"id":103,"title":"Support for Cassandra?","fancy_title":"Support for Cassandra?","slug":"support-for-cassandra","posts_count":5,"reply_count":1,"highest_post_number":5,"image_url":null,"created_at":"2015-11-20T06:45:31.741Z","last_posted_at":"2015-12-09T03:18:51.274Z","bumped":true,"bumped_at":"2015-12-09T03:18:51.274Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":169,"like_count":0,"has_summary":false,"archetype":"regular","last_poster_username":"vikram","category_id":1,"pinned_globally":false,"posters":[{"extras":"latest","description":"Original Poster, Most Recent Poster","user_id":55},{"extras":null,"description":"Frequent Poster","user_id":1}]},{"id":128,"title":"Mongo query with Date breaks [solved: Mongo 3.0 required]","fancy_title":"Mongo query with Date breaks [solved: Mongo 3.0 required]","slug":"mongo-query-with-date-breaks-solved-mongo-3-0-required","posts_count":5,"reply_count":0,"highest_post_number":5,"image_url":null,"created_at":"2015-12-08T18:30:56.562Z","last_posted_at":"2015-12-08T21:03:02.421Z","bumped":true,"bumped_at":"2015-12-08T21:03:02.421Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":102,"like_count":1,"has_summary":false,"archetype":"regular","last_poster_username":"edchan77","category_id":1,"pinned_globally":false,"posters":[{"extras":"latest","description":"Original Poster, Most Recent Poster","user_id":68},{"extras":null,"description":"Frequent Poster","user_id":1}]},{"id":23,"title":"Can this connect to MS SQL Server?","fancy_title":"Can this connect to MS SQL Server?","slug":"can-this-connect-to-ms-sql-server","posts_count":7,"reply_count":1,"highest_post_number":7,"image_url":null,"created_at":"2015-10-21T18:52:37.987Z","last_posted_at":"2015-12-07T17:41:51.609Z","bumped":true,"bumped_at":"2015-12-07T17:41:51.609Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":367,"like_count":0,"has_summary":false,"archetype":"regular","last_poster_username":"sameer","category_id":1,"pinned_globally":false,"posters":[{"extras":null,"description":"Original Poster","user_id":9},{"extras":null,"description":"Frequent Poster","user_id":23},{"extras":null,"description":"Frequent Poster","user_id":3},{"extras":null,"description":"Frequent Poster","user_id":50},{"extras":"latest","description":"Most Recent Poster","user_id":1}]},{"id":121,"title":"Cannot restart metabase in docker","fancy_title":"Cannot restart metabase in docker","slug":"cannot-restart-metabase-in-docker","posts_count":5,"reply_count":1,"highest_post_number":5,"image_url":null,"created_at":"2015-12-04T21:28:58.137Z","last_posted_at":"2015-12-04T23:02:00.488Z","bumped":true,"bumped_at":"2015-12-04T23:02:00.488Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":96,"like_count":0,"has_summary":false,"archetype":"regular","last_poster_username":"sameer","category_id":1,"pinned_globally":false,"posters":[{"extras":null,"description":"Original Poster","user_id":66},{"extras":"latest","description":"Most Recent Poster, Frequent Poster","user_id":1}]},{"id":85,"title":"Edit Max Rows Count","fancy_title":"Edit Max Rows Count","slug":"edit-max-rows-count","posts_count":4,"reply_count":2,"highest_post_number":4,"image_url":null,"created_at":"2015-11-11T23:46:52.917Z","last_posted_at":"2015-11-24T01:01:14.569Z","bumped":true,"bumped_at":"2015-11-24T01:01:14.569Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":169,"like_count":1,"has_summary":false,"archetype":"regular","last_poster_username":"sameer","category_id":1,"pinned_globally":false,"posters":[{"extras":null,"description":"Original Poster","user_id":34},{"extras":"latest","description":"Most Recent Poster, Frequent Poster","user_id":1}]},{"id":96,"title":"Creating charts by querying more than one table at a time","fancy_title":"Creating charts by querying more than one table at a time","slug":"creating-charts-by-querying-more-than-one-table-at-a-time","posts_count":6,"reply_count":4,"highest_post_number":6,"image_url":null,"created_at":"2015-11-17T11:20:18.442Z","last_posted_at":"2015-11-21T02:12:25.995Z","bumped":true,"bumped_at":"2015-11-21T02:12:25.995Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":217,"like_count":0,"has_summary":false,"archetype":"regular","last_poster_username":"sameer","category_id":1,"pinned_globally":false,"posters":[{"extras":null,"description":"Original Poster","user_id":51},{"extras":"latest","description":"Most Recent Poster, Frequent Poster","user_id":1}]},{"id":90,"title":"Trying to add RDS postgresql as the database fails silently","fancy_title":"Trying to add RDS postgresql as the database fails silently","slug":"trying-to-add-rds-postgresql-as-the-database-fails-silently","posts_count":4,"reply_count":2,"highest_post_number":4,"image_url":null,"created_at":"2015-11-14T23:45:02.967Z","last_posted_at":"2015-11-21T01:08:45.915Z","bumped":true,"bumped_at":"2015-11-21T01:08:45.915Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":162,"like_count":0,"has_summary":false,"archetype":"regular","last_poster_username":"sameer","category_id":1,"pinned_globally":false,"posters":[{"extras":null,"description":"Original Poster","user_id":46},{"extras":"latest","description":"Most Recent Poster, Frequent Poster","user_id":1}]},{"id":17,"title":"Deploy to Heroku isn't working","fancy_title":"Deploy to Heroku isn’t working","slug":"deploy-to-heroku-isnt-working","posts_count":9,"reply_count":3,"highest_post_number":9,"image_url":null,"created_at":"2015-10-21T16:42:03.096Z","last_posted_at":"2015-11-20T18:34:14.044Z","bumped":true,"bumped_at":"2015-11-20T18:34:14.044Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":332,"like_count":2,"has_summary":false,"archetype":"regular","last_poster_username":"agilliland","category_id":1,"pinned_globally":false,"posters":[{"extras":null,"description":"Original Poster","user_id":5},{"extras":null,"description":"Frequent Poster","user_id":3},{"extras":null,"description":"Frequent Poster","user_id":11},{"extras":null,"description":"Frequent Poster","user_id":25},{"extras":"latest","description":"Most Recent Poster","user_id":14}]},{"id":100,"title":"Can I use DATEPART() in SQL queries?","fancy_title":"Can I use DATEPART() in SQL queries?","slug":"can-i-use-datepart-in-sql-queries","posts_count":2,"reply_count":0,"highest_post_number":2,"image_url":null,"created_at":"2015-11-17T23:15:58.033Z","last_posted_at":"2015-11-18T00:19:48.763Z","bumped":true,"bumped_at":"2015-11-18T00:19:48.763Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":112,"like_count":1,"has_summary":false,"archetype":"regular","last_poster_username":"sameer","category_id":1,"pinned_globally":false,"posters":[{"extras":null,"description":"Original Poster","user_id":53},{"extras":"latest","description":"Most Recent Poster","user_id":1}]},{"id":98,"title":"Feature Request: LDAP Authentication","fancy_title":"Feature Request: LDAP Authentication","slug":"feature-request-ldap-authentication","posts_count":1,"reply_count":0,"highest_post_number":1,"image_url":null,"created_at":"2015-11-17T17:22:44.484Z","last_posted_at":"2015-11-17T17:22:44.577Z","bumped":true,"bumped_at":"2015-11-17T17:22:44.577Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":97,"like_count":0,"has_summary":false,"archetype":"regular","last_poster_username":"j_at_svg","category_id":1,"pinned_globally":false,"posters":[{"extras":"latest single","description":"Original Poster, Most Recent Poster","user_id":52}]},{"id":87,"title":"Migrating from internal H2 to Postgres","fancy_title":"Migrating from internal H2 to Postgres","slug":"migrating-from-internal-h2-to-postgres","posts_count":2,"reply_count":0,"highest_post_number":2,"image_url":null,"created_at":"2015-11-12T14:36:06.745Z","last_posted_at":"2015-11-12T18:05:10.796Z","bumped":true,"bumped_at":"2015-11-12T18:05:10.796Z","unseen":false,"pinned":false,"unpinned":null,"visible":true,"closed":false,"archived":false,"bookmarked":null,"liked":null,"views":111,"like_count":0,"has_summary":false,"archetype":"regular","last_poster_username":"sameer","category_id":1,"pinned_globally":false,"posters":[{"extras":null,"description":"Original Poster","user_id":42},{"extras":"latest","description":"Most Recent Poster","user_id":1}]}]}}
`)
func NewLargePayload() *LargePayload {
dsUsers := DSUsers{}
dsTopics := DSTopics{}
for i := 0; i < 100; i++ {
str := "test" + strconv.Itoa(i)
dsUsers = append(
dsUsers,
&DSUser{
Username: str,
},
)
dsTopics = append(
dsTopics,
&DSTopic{
Id: i,
Slug: str,
},
)
}
return &LargePayload{
Users: dsUsers,
Topics: &DSTopicsList{
Topics: dsTopics,
MoreTopicsUrl: "http://test.com",
},
}
}
func NewLargePayloadEasyJson() *LargePayloadEasyJson {
dsUsers := DSUsers{}
dsTopics := DSTopics{}
for i := 0; i < 100; i++ {
str := "test" + strconv.Itoa(i)
dsUsers = append(
dsUsers,
&DSUser{
Username: str,
},
)
dsTopics = append(
dsTopics,
&DSTopic{
Id: i,
Slug: str,
},
)
}
return &LargePayloadEasyJson{
Users: dsUsers,
Topics: &DSTopicsList{
Topics: dsTopics,
MoreTopicsUrl: "http://test.com",
},
}
}
var LargeSliceEscapedString = []byte("[" + strings.Repeat(",\"simple plain text\\r\\n\"", 10000)[1:] + "]")
golang-github-goccy-go-json-0.10.3/benchmarks/large_payload_easyjson.go 0000664 0000000 0000000 00000015675 14635552766 0026221 0 ustar 00root root 0000000 0000000 // Code generated by easyjson for marshaling/unmarshaling. DO NOT EDIT.
package benchmark
import (
json "encoding/json"
easyjson "github.com/mailru/easyjson"
jlexer "github.com/mailru/easyjson/jlexer"
jwriter "github.com/mailru/easyjson/jwriter"
)
// suppress unused package warning
var (
_ *json.RawMessage
_ *jlexer.Lexer
_ *jwriter.Writer
_ easyjson.Marshaler
)
func easyjsonD519278DecodeBenchmark(in *jlexer.Lexer, out *LargePayloadEasyJson) {
isTopLevel := in.IsStart()
if in.IsNull() {
if isTopLevel {
in.Consumed()
}
in.Skip()
return
}
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
in.WantColon()
if in.IsNull() {
in.Skip()
in.WantComma()
continue
}
switch key {
case "Users":
if in.IsNull() {
in.Skip()
out.Users = nil
} else {
in.Delim('[')
if out.Users == nil {
if !in.IsDelim(']') {
out.Users = make(DSUsers, 0, 8)
} else {
out.Users = DSUsers{}
}
} else {
out.Users = (out.Users)[:0]
}
for !in.IsDelim(']') {
var v1 *DSUser
if in.IsNull() {
in.Skip()
v1 = nil
} else {
if v1 == nil {
v1 = new(DSUser)
}
easyjsonD519278DecodeBenchmark1(in, v1)
}
out.Users = append(out.Users, v1)
in.WantComma()
}
in.Delim(']')
}
case "Topics":
if in.IsNull() {
in.Skip()
out.Topics = nil
} else {
if out.Topics == nil {
out.Topics = new(DSTopicsList)
}
easyjsonD519278DecodeBenchmark2(in, out.Topics)
}
default:
in.SkipRecursive()
}
in.WantComma()
}
in.Delim('}')
if isTopLevel {
in.Consumed()
}
}
func easyjsonD519278EncodeBenchmark(out *jwriter.Writer, in LargePayloadEasyJson) {
out.RawByte('{')
first := true
_ = first
{
const prefix string = ",\"Users\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
if in.Users == nil && (out.Flags&jwriter.NilSliceAsEmpty) == 0 {
out.RawString("null")
} else {
out.RawByte('[')
for v2, v3 := range in.Users {
if v2 > 0 {
out.RawByte(',')
}
if v3 == nil {
out.RawString("null")
} else {
easyjsonD519278EncodeBenchmark1(out, *v3)
}
}
out.RawByte(']')
}
}
{
const prefix string = ",\"Topics\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
if in.Topics == nil {
out.RawString("null")
} else {
easyjsonD519278EncodeBenchmark2(out, *in.Topics)
}
}
out.RawByte('}')
}
// MarshalJSON supports json.Marshaler interface
func (v LargePayloadEasyJson) MarshalJSON() ([]byte, error) {
w := jwriter.Writer{}
easyjsonD519278EncodeBenchmark(&w, v)
return w.Buffer.BuildBytes(), w.Error
}
// MarshalEasyJSON supports easyjson.Marshaler interface
func (v LargePayloadEasyJson) MarshalEasyJSON(w *jwriter.Writer) {
easyjsonD519278EncodeBenchmark(w, v)
}
// UnmarshalJSON supports json.Unmarshaler interface
func (v *LargePayloadEasyJson) UnmarshalJSON(data []byte) error {
r := jlexer.Lexer{Data: data}
easyjsonD519278DecodeBenchmark(&r, v)
return r.Error()
}
// UnmarshalEasyJSON supports easyjson.Unmarshaler interface
func (v *LargePayloadEasyJson) UnmarshalEasyJSON(l *jlexer.Lexer) {
easyjsonD519278DecodeBenchmark(l, v)
}
func easyjsonD519278DecodeBenchmark2(in *jlexer.Lexer, out *DSTopicsList) {
isTopLevel := in.IsStart()
if in.IsNull() {
if isTopLevel {
in.Consumed()
}
in.Skip()
return
}
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
in.WantColon()
if in.IsNull() {
in.Skip()
in.WantComma()
continue
}
switch key {
case "Topics":
if in.IsNull() {
in.Skip()
out.Topics = nil
} else {
in.Delim('[')
if out.Topics == nil {
if !in.IsDelim(']') {
out.Topics = make(DSTopics, 0, 8)
} else {
out.Topics = DSTopics{}
}
} else {
out.Topics = (out.Topics)[:0]
}
for !in.IsDelim(']') {
var v4 *DSTopic
if in.IsNull() {
in.Skip()
v4 = nil
} else {
if v4 == nil {
v4 = new(DSTopic)
}
easyjsonD519278DecodeBenchmark3(in, v4)
}
out.Topics = append(out.Topics, v4)
in.WantComma()
}
in.Delim(']')
}
case "MoreTopicsUrl":
out.MoreTopicsUrl = string(in.String())
default:
in.SkipRecursive()
}
in.WantComma()
}
in.Delim('}')
if isTopLevel {
in.Consumed()
}
}
func easyjsonD519278EncodeBenchmark2(out *jwriter.Writer, in DSTopicsList) {
out.RawByte('{')
first := true
_ = first
{
const prefix string = ",\"Topics\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
if in.Topics == nil && (out.Flags&jwriter.NilSliceAsEmpty) == 0 {
out.RawString("null")
} else {
out.RawByte('[')
for v5, v6 := range in.Topics {
if v5 > 0 {
out.RawByte(',')
}
if v6 == nil {
out.RawString("null")
} else {
easyjsonD519278EncodeBenchmark3(out, *v6)
}
}
out.RawByte(']')
}
}
{
const prefix string = ",\"MoreTopicsUrl\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.MoreTopicsUrl))
}
out.RawByte('}')
}
func easyjsonD519278DecodeBenchmark3(in *jlexer.Lexer, out *DSTopic) {
isTopLevel := in.IsStart()
if in.IsNull() {
if isTopLevel {
in.Consumed()
}
in.Skip()
return
}
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
in.WantColon()
if in.IsNull() {
in.Skip()
in.WantComma()
continue
}
switch key {
case "Id":
out.Id = int(in.Int())
case "Slug":
out.Slug = string(in.String())
default:
in.SkipRecursive()
}
in.WantComma()
}
in.Delim('}')
if isTopLevel {
in.Consumed()
}
}
func easyjsonD519278EncodeBenchmark3(out *jwriter.Writer, in DSTopic) {
out.RawByte('{')
first := true
_ = first
{
const prefix string = ",\"Id\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.Int(int(in.Id))
}
{
const prefix string = ",\"Slug\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.Slug))
}
out.RawByte('}')
}
func easyjsonD519278DecodeBenchmark1(in *jlexer.Lexer, out *DSUser) {
isTopLevel := in.IsStart()
if in.IsNull() {
if isTopLevel {
in.Consumed()
}
in.Skip()
return
}
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
in.WantColon()
if in.IsNull() {
in.Skip()
in.WantComma()
continue
}
switch key {
case "Username":
out.Username = string(in.String())
default:
in.SkipRecursive()
}
in.WantComma()
}
in.Delim('}')
if isTopLevel {
in.Consumed()
}
}
func easyjsonD519278EncodeBenchmark1(out *jwriter.Writer, in DSUser) {
out.RawByte('{')
first := true
_ = first
{
const prefix string = ",\"Username\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.Username))
}
out.RawByte('}')
}
golang-github-goccy-go-json-0.10.3/benchmarks/medium_payload.go 0000664 0000000 0000000 00000015606 14635552766 0024466 0 ustar 00root root 0000000 0000000 package benchmark
import "github.com/francoispqt/gojay"
// Response from Clearbit API. Size: 2.4kb
var MediumFixture = []byte(`{
"person": {
"id": "d50887ca-a6ce-4e59-b89f-14f0b5d03b03",
"name": {
"fullName": "Leonid Bugaev",
"givenName": "Leonid",
"familyName": "Bugaev"
},
"email": "leonsbox@gmail.com",
"gender": "male",
"location": "Saint Petersburg, Saint Petersburg, RU",
"geo": {
"city": "Saint Petersburg",
"state": "Saint Petersburg",
"country": "Russia",
"lat": 59.9342802,
"lng": 30.3350986
},
"bio": "Senior engineer at Granify.com",
"site": "http://flickfaver.com",
"avatar": "https://d1ts43dypk8bqh.cloudfront.net/v1/avatars/d50887ca-a6ce-4e59-b89f-14f0b5d03b03",
"employment": {
"name": "www.latera.ru",
"title": "Software Engineer",
"domain": "gmail.com"
},
"facebook": {
"handle": "leonid.bugaev"
},
"github": {
"handle": "buger",
"id": 14009,
"avatar": "https://avatars.githubusercontent.com/u/14009?v=3",
"company": "Granify",
"blog": "http://leonsbox.com",
"followers": 95,
"following": 10
},
"twitter": {
"handle": "flickfaver",
"id": 77004410,
"bio": null,
"followers": 2,
"following": 1,
"statuses": 5,
"favorites": 0,
"location": "",
"site": "http://flickfaver.com",
"avatar": null
},
"linkedin": {
"handle": "in/leonidbugaev"
},
"googleplus": {
"handle": null
},
"angellist": {
"handle": "leonid-bugaev",
"id": 61541,
"bio": "Senior engineer at Granify.com",
"blog": "http://buger.github.com",
"site": "http://buger.github.com",
"followers": 41,
"avatar": "https://d1qb2nb5cznatu.cloudfront.net/users/61541-medium_jpg?1405474390"
},
"klout": {
"handle": null,
"score": null
},
"foursquare": {
"handle": null
},
"aboutme": {
"handle": "leonid.bugaev",
"bio": null,
"avatar": null
},
"gravatar": {
"handle": "buger",
"urls": [
],
"avatar": "http://1.gravatar.com/avatar/f7c8edd577d13b8930d5522f28123510",
"avatars": [
{
"url": "http://1.gravatar.com/avatar/f7c8edd577d13b8930d5522f28123510",
"type": "thumbnail"
}
]
},
"fuzzy": false
},
"company": null
}`)
type CBAvatar struct {
Url string
}
func (m *CBAvatar) UnmarshalJSONObject(dec *gojay.Decoder, key string) error {
switch key {
case "avatars":
return dec.AddString(&m.Url)
}
return nil
}
func (m *CBAvatar) NKeys() int {
return 1
}
func (m *CBAvatar) MarshalJSONObject(enc *gojay.Encoder) {
enc.AddStringKey("url", m.Url)
}
func (m *CBAvatar) IsNil() bool {
return m == nil
}
type Avatars []*CBAvatar
func (t *Avatars) UnmarshalJSONArray(dec *gojay.Decoder) error {
avatar := CBAvatar{}
*t = append(*t, &avatar)
return dec.AddObject(&avatar)
}
func (m *Avatars) MarshalJSONArray(enc *gojay.Encoder) {
for _, e := range *m {
enc.AddObject(e)
}
}
func (m *Avatars) IsNil() bool {
return m == nil
}
type CBGravatar struct {
Avatars Avatars
}
func (m *CBGravatar) UnmarshalJSONObject(dec *gojay.Decoder, key string) error {
switch key {
case "avatars":
return dec.AddArray(&m.Avatars)
}
return nil
}
func (m *CBGravatar) NKeys() int {
return 1
}
func (m *CBGravatar) MarshalJSONObject(enc *gojay.Encoder) {
enc.AddArrayKey("avatars", &m.Avatars)
}
func (m *CBGravatar) IsNil() bool {
return m == nil
}
type CBGithub struct {
Followers int
}
func (m *CBGithub) UnmarshalJSONObject(dec *gojay.Decoder, key string) error {
switch key {
case "followers":
return dec.AddInt(&m.Followers)
}
return nil
}
func (m *CBGithub) NKeys() int {
return 1
}
func (m *CBGithub) MarshalJSONObject(enc *gojay.Encoder) {
enc.AddIntKey("followers", m.Followers)
}
func (m *CBGithub) IsNil() bool {
return m == nil
}
type CBName struct {
FullName string `json:"fullName"`
}
func (m *CBName) UnmarshalJSONObject(dec *gojay.Decoder, key string) error {
switch key {
case "fullName":
return dec.AddString(&m.FullName)
}
return nil
}
func (m *CBName) NKeys() int {
return 1
}
func (m *CBName) MarshalJSONObject(enc *gojay.Encoder) {
enc.AddStringKey("fullName", m.FullName)
}
func (m *CBName) IsNil() bool {
return m == nil
}
type CBPerson struct {
Name *CBName `json:"name"`
Github *CBGithub `json:"github"`
Gravatar *CBGravatar
}
func (m *CBPerson) UnmarshalJSONObject(dec *gojay.Decoder, key string) error {
switch key {
case "name":
m.Name = &CBName{}
return dec.AddObject(m.Name)
case "github":
m.Github = &CBGithub{}
return dec.AddObject(m.Github)
case "gravatar":
m.Gravatar = &CBGravatar{}
return dec.AddObject(m.Gravatar)
}
return nil
}
func (m *CBPerson) NKeys() int {
return 3
}
func (m *CBPerson) MarshalJSONObject(enc *gojay.Encoder) {
enc.AddObjectKey("name", m.Name)
enc.AddObjectKey("github", m.Github)
enc.AddObjectKey("gravatar", m.Gravatar)
}
func (m *CBPerson) IsNil() bool {
return m == nil
}
type MediumPayload struct {
Person *CBPerson `json:"person"`
Company string `json:"company"`
}
//easyjson:json
type MediumPayloadEasyJson struct {
Person *CBPerson `json:"person"`
Company string `json:"company"`
}
func (m *MediumPayload) UnmarshalJSONObject(dec *gojay.Decoder, key string) error {
switch key {
case "person":
m.Person = &CBPerson{}
return dec.AddObject(m.Person)
case "company":
dec.AddString(&m.Company)
}
return nil
}
func (m *MediumPayload) NKeys() int {
return 2
}
func (m *MediumPayload) MarshalJSONObject(enc *gojay.Encoder) {
enc.AddObjectKey("person", m.Person)
// enc.AddStringKey("company", m.Company)
}
func (m *MediumPayload) IsNil() bool {
return m == nil
}
func NewMediumPayload() *MediumPayload {
return &MediumPayload{
Company: "test",
Person: &CBPerson{
Name: &CBName{
FullName: "test",
},
Github: &CBGithub{
Followers: 100,
},
Gravatar: &CBGravatar{
Avatars: Avatars{
&CBAvatar{
Url: "http://test.com",
},
&CBAvatar{
Url: "http://test.com",
},
&CBAvatar{
Url: "http://test.com",
},
&CBAvatar{
Url: "http://test.com",
},
&CBAvatar{
Url: "http://test.com",
},
&CBAvatar{
Url: "http://test.com",
},
&CBAvatar{
Url: "http://test.com",
},
&CBAvatar{
Url: "http://test.com",
},
},
},
},
}
}
func NewMediumPayloadEasyJson() *MediumPayloadEasyJson {
return &MediumPayloadEasyJson{
Company: "test",
Person: &CBPerson{
Name: &CBName{
FullName: "test",
},
Github: &CBGithub{
Followers: 100,
},
Gravatar: &CBGravatar{
Avatars: Avatars{
&CBAvatar{
Url: "http://test.com",
},
&CBAvatar{
Url: "http://test.com",
},
&CBAvatar{
Url: "http://test.com",
},
&CBAvatar{
Url: "http://test.com",
},
&CBAvatar{
Url: "http://test.com",
},
&CBAvatar{
Url: "http://test.com",
},
&CBAvatar{
Url: "http://test.com",
},
&CBAvatar{
Url: "http://test.com",
},
},
},
},
}
}
golang-github-goccy-go-json-0.10.3/benchmarks/medium_payload_easyjson.go 0000664 0000000 0000000 00000020674 14635552766 0026402 0 ustar 00root root 0000000 0000000 // Code generated by easyjson for marshaling/unmarshaling. DO NOT EDIT.
package benchmark
import (
json "encoding/json"
easyjson "github.com/mailru/easyjson"
jlexer "github.com/mailru/easyjson/jlexer"
jwriter "github.com/mailru/easyjson/jwriter"
)
// suppress unused package warning
var (
_ *json.RawMessage
_ *jlexer.Lexer
_ *jwriter.Writer
_ easyjson.Marshaler
)
func easyjson8ca7813eDecodeBenchmark(in *jlexer.Lexer, out *MediumPayloadEasyJson) {
isTopLevel := in.IsStart()
if in.IsNull() {
if isTopLevel {
in.Consumed()
}
in.Skip()
return
}
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
in.WantColon()
if in.IsNull() {
in.Skip()
in.WantComma()
continue
}
switch key {
case "person":
if in.IsNull() {
in.Skip()
out.Person = nil
} else {
if out.Person == nil {
out.Person = new(CBPerson)
}
easyjson8ca7813eDecodeBenchmark1(in, out.Person)
}
case "company":
out.Company = string(in.String())
default:
in.SkipRecursive()
}
in.WantComma()
}
in.Delim('}')
if isTopLevel {
in.Consumed()
}
}
func easyjson8ca7813eEncodeBenchmark(out *jwriter.Writer, in MediumPayloadEasyJson) {
out.RawByte('{')
first := true
_ = first
{
const prefix string = ",\"person\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
if in.Person == nil {
out.RawString("null")
} else {
easyjson8ca7813eEncodeBenchmark1(out, *in.Person)
}
}
{
const prefix string = ",\"company\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.Company))
}
out.RawByte('}')
}
// MarshalJSON supports json.Marshaler interface
func (v MediumPayloadEasyJson) MarshalJSON() ([]byte, error) {
w := jwriter.Writer{}
easyjson8ca7813eEncodeBenchmark(&w, v)
return w.Buffer.BuildBytes(), w.Error
}
// MarshalEasyJSON supports easyjson.Marshaler interface
func (v MediumPayloadEasyJson) MarshalEasyJSON(w *jwriter.Writer) {
easyjson8ca7813eEncodeBenchmark(w, v)
}
// UnmarshalJSON supports json.Unmarshaler interface
func (v *MediumPayloadEasyJson) UnmarshalJSON(data []byte) error {
r := jlexer.Lexer{Data: data}
easyjson8ca7813eDecodeBenchmark(&r, v)
return r.Error()
}
// UnmarshalEasyJSON supports easyjson.Unmarshaler interface
func (v *MediumPayloadEasyJson) UnmarshalEasyJSON(l *jlexer.Lexer) {
easyjson8ca7813eDecodeBenchmark(l, v)
}
func easyjson8ca7813eDecodeBenchmark1(in *jlexer.Lexer, out *CBPerson) {
isTopLevel := in.IsStart()
if in.IsNull() {
if isTopLevel {
in.Consumed()
}
in.Skip()
return
}
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
in.WantColon()
if in.IsNull() {
in.Skip()
in.WantComma()
continue
}
switch key {
case "name":
if in.IsNull() {
in.Skip()
out.Name = nil
} else {
if out.Name == nil {
out.Name = new(CBName)
}
easyjson8ca7813eDecodeBenchmark2(in, out.Name)
}
case "github":
if in.IsNull() {
in.Skip()
out.Github = nil
} else {
if out.Github == nil {
out.Github = new(CBGithub)
}
easyjson8ca7813eDecodeBenchmark3(in, out.Github)
}
case "Gravatar":
if in.IsNull() {
in.Skip()
out.Gravatar = nil
} else {
if out.Gravatar == nil {
out.Gravatar = new(CBGravatar)
}
easyjson8ca7813eDecodeBenchmark4(in, out.Gravatar)
}
default:
in.SkipRecursive()
}
in.WantComma()
}
in.Delim('}')
if isTopLevel {
in.Consumed()
}
}
func easyjson8ca7813eEncodeBenchmark1(out *jwriter.Writer, in CBPerson) {
out.RawByte('{')
first := true
_ = first
{
const prefix string = ",\"name\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
if in.Name == nil {
out.RawString("null")
} else {
easyjson8ca7813eEncodeBenchmark2(out, *in.Name)
}
}
{
const prefix string = ",\"github\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
if in.Github == nil {
out.RawString("null")
} else {
easyjson8ca7813eEncodeBenchmark3(out, *in.Github)
}
}
{
const prefix string = ",\"Gravatar\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
if in.Gravatar == nil {
out.RawString("null")
} else {
easyjson8ca7813eEncodeBenchmark4(out, *in.Gravatar)
}
}
out.RawByte('}')
}
func easyjson8ca7813eDecodeBenchmark4(in *jlexer.Lexer, out *CBGravatar) {
isTopLevel := in.IsStart()
if in.IsNull() {
if isTopLevel {
in.Consumed()
}
in.Skip()
return
}
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
in.WantColon()
if in.IsNull() {
in.Skip()
in.WantComma()
continue
}
switch key {
case "Avatars":
if in.IsNull() {
in.Skip()
out.Avatars = nil
} else {
in.Delim('[')
if out.Avatars == nil {
if !in.IsDelim(']') {
out.Avatars = make(Avatars, 0, 8)
} else {
out.Avatars = Avatars{}
}
} else {
out.Avatars = (out.Avatars)[:0]
}
for !in.IsDelim(']') {
var v1 *CBAvatar
if in.IsNull() {
in.Skip()
v1 = nil
} else {
if v1 == nil {
v1 = new(CBAvatar)
}
easyjson8ca7813eDecodeBenchmark5(in, v1)
}
out.Avatars = append(out.Avatars, v1)
in.WantComma()
}
in.Delim(']')
}
default:
in.SkipRecursive()
}
in.WantComma()
}
in.Delim('}')
if isTopLevel {
in.Consumed()
}
}
func easyjson8ca7813eEncodeBenchmark4(out *jwriter.Writer, in CBGravatar) {
out.RawByte('{')
first := true
_ = first
{
const prefix string = ",\"Avatars\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
if in.Avatars == nil && (out.Flags&jwriter.NilSliceAsEmpty) == 0 {
out.RawString("null")
} else {
out.RawByte('[')
for v2, v3 := range in.Avatars {
if v2 > 0 {
out.RawByte(',')
}
if v3 == nil {
out.RawString("null")
} else {
easyjson8ca7813eEncodeBenchmark5(out, *v3)
}
}
out.RawByte(']')
}
}
out.RawByte('}')
}
func easyjson8ca7813eDecodeBenchmark5(in *jlexer.Lexer, out *CBAvatar) {
isTopLevel := in.IsStart()
if in.IsNull() {
if isTopLevel {
in.Consumed()
}
in.Skip()
return
}
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
in.WantColon()
if in.IsNull() {
in.Skip()
in.WantComma()
continue
}
switch key {
case "Url":
out.Url = string(in.String())
default:
in.SkipRecursive()
}
in.WantComma()
}
in.Delim('}')
if isTopLevel {
in.Consumed()
}
}
func easyjson8ca7813eEncodeBenchmark5(out *jwriter.Writer, in CBAvatar) {
out.RawByte('{')
first := true
_ = first
{
const prefix string = ",\"Url\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.Url))
}
out.RawByte('}')
}
func easyjson8ca7813eDecodeBenchmark3(in *jlexer.Lexer, out *CBGithub) {
isTopLevel := in.IsStart()
if in.IsNull() {
if isTopLevel {
in.Consumed()
}
in.Skip()
return
}
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
in.WantColon()
if in.IsNull() {
in.Skip()
in.WantComma()
continue
}
switch key {
case "Followers":
out.Followers = int(in.Int())
default:
in.SkipRecursive()
}
in.WantComma()
}
in.Delim('}')
if isTopLevel {
in.Consumed()
}
}
func easyjson8ca7813eEncodeBenchmark3(out *jwriter.Writer, in CBGithub) {
out.RawByte('{')
first := true
_ = first
{
const prefix string = ",\"Followers\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.Int(int(in.Followers))
}
out.RawByte('}')
}
func easyjson8ca7813eDecodeBenchmark2(in *jlexer.Lexer, out *CBName) {
isTopLevel := in.IsStart()
if in.IsNull() {
if isTopLevel {
in.Consumed()
}
in.Skip()
return
}
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
in.WantColon()
if in.IsNull() {
in.Skip()
in.WantComma()
continue
}
switch key {
case "fullName":
out.FullName = string(in.String())
default:
in.SkipRecursive()
}
in.WantComma()
}
in.Delim('}')
if isTopLevel {
in.Consumed()
}
}
func easyjson8ca7813eEncodeBenchmark2(out *jwriter.Writer, in CBName) {
out.RawByte('{')
first := true
_ = first
{
const prefix string = ",\"fullName\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.FullName))
}
out.RawByte('}')
}
golang-github-goccy-go-json-0.10.3/benchmarks/path_test.go 0000664 0000000 0000000 00000000647 14635552766 0023467 0 ustar 00root root 0000000 0000000 package benchmark
import (
"testing"
gojson "github.com/goccy/go-json"
)
func Benchmark_Decode_SmallStruct_UnmarshalPath_GoJson(b *testing.B) {
path, err := gojson.CreatePath("$.st")
if err != nil {
b.Fatal(err)
}
b.ReportAllocs()
for i := 0; i < b.N; i++ {
var v int
if err := path.Unmarshal(SmallFixture, &v); err != nil {
b.Fatal(err)
}
if v != 1 {
b.Fatal("failed to unmarshal path")
}
}
}
golang-github-goccy-go-json-0.10.3/benchmarks/slow_reader_test.go 0000664 0000000 0000000 00000003500 14635552766 0025030 0 ustar 00root root 0000000 0000000 package benchmark
import (
"bytes"
"encoding/json"
"fmt"
"reflect"
"testing"
gojson "github.com/goccy/go-json"
)
// Benchmark decoding from a slow io.Reader that never fills the buffer completely
func Benchmark_Decode_SlowReader_EncodingJson(b *testing.B) {
var expected LargePayload
if err := json.Unmarshal(LargeFixture, &expected); err != nil {
b.Fatal(err)
}
for _, chunkSize := range [5]int{16384, 4096, 1024, 256, 64} {
b.Run(fmt.Sprintf("chunksize %v", chunkSize), func(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
index = 0
var got LargePayload
if err := json.NewDecoder(slowReader{chunkSize: chunkSize}).Decode(&got); err != nil {
b.Fatal(err)
}
if !reflect.DeepEqual(expected, got) {
b.Fatalf("failed to decode. expected:[%+v] but got:[%+v]", expected, got)
}
}
})
}
}
func Benchmark_Decode_SlowReader_GoJson(b *testing.B) {
var expected LargePayload
if err := json.Unmarshal(LargeFixture, &expected); err != nil {
b.Fatal(err)
}
for _, chunkSize := range []int{16384, 4096, 1024, 256, 64} {
b.Run(fmt.Sprintf("chunksize %v", chunkSize), func(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
index = 0
var got LargePayload
if err := gojson.NewDecoder(slowReader{chunkSize: chunkSize}).Decode(&got); err != nil {
b.Fatal(err)
}
if !reflect.DeepEqual(expected, got) {
b.Fatalf("failed to decode. expected:[%+v] but got:[%+v]", expected, got)
}
}
})
}
}
type slowReader struct {
chunkSize int
}
var index int
func (s slowReader) Read(p []byte) (n int, err error) {
smallBuf := make([]byte, Min(s.chunkSize, len(p)))
x := bytes.NewReader(LargeFixture)
n, err = x.ReadAt(smallBuf, int64(index))
index += n
copy(p, smallBuf)
return
}
func Min(x, y int) int {
if x < y {
return x
}
return y
}
golang-github-goccy-go-json-0.10.3/benchmarks/small_payload.go 0000664 0000000 0000000 00000004430 14635552766 0024307 0 ustar 00root root 0000000 0000000 package benchmark
import "github.com/francoispqt/gojay"
var SmallFixture = []byte(`{"st": 1,"sid": 486,"tt": "active","gr": 0,"uuid": "de305d54-75b4-431b-adb2-eb6b9e546014","ip": "127.0.0.1","ua": "user_agent","tz": -6,"v": 1}`)
// ffjson:skip
type SmallPayload struct {
St int
Sid int
Tt string
Gr int
Uuid string
Ip string
Ua string
Tz int
V int
}
type SmallPayloadFFJson struct {
St int
Sid int
Tt string
Gr int
Uuid string
Ip string
Ua string
Tz int
V int
}
//easyjson:json
type SmallPayloadEasyJson struct {
St int
Sid int
Tt string
Gr int
Uuid string
Ip string
Ua string
Tz int
V int
}
func (t *SmallPayload) MarshalJSONObject(enc *gojay.Encoder) {
enc.AddIntKey("st", t.St)
enc.AddIntKey("sid", t.Sid)
enc.AddStringKey("tt", t.Tt)
enc.AddIntKey("gr", t.Gr)
enc.AddStringKey("uuid", t.Uuid)
enc.AddStringKey("ip", t.Ip)
enc.AddStringKey("ua", t.Ua)
enc.AddIntKey("tz", t.Tz)
enc.AddIntKey("v", t.V)
}
func (t *SmallPayload) IsNil() bool {
return t == nil
}
func (t *SmallPayload) UnmarshalJSONObject(dec *gojay.Decoder, key string) error {
switch key {
case "st":
return dec.AddInt(&t.St)
case "sid":
return dec.AddInt(&t.Sid)
case "gr":
return dec.AddInt(&t.Gr)
case "tz":
return dec.AddInt(&t.Tz)
case "v":
return dec.AddInt(&t.V)
case "tt":
return dec.AddString(&t.Tt)
case "uuid":
return dec.AddString(&t.Uuid)
case "ip":
return dec.AddString(&t.Ip)
case "ua":
return dec.AddString(&t.Ua)
}
return nil
}
func (t *SmallPayload) NKeys() int {
return 9
}
func NewSmallPayload() *SmallPayload {
return &SmallPayload{
St: 1,
Sid: 2,
Tt: "TestString",
Gr: 4,
Uuid: "8f9a65eb-4807-4d57-b6e0-bda5d62f1429",
Ip: "127.0.0.1",
Ua: "Mozilla",
Tz: 8,
V: 6,
}
}
func NewSmallPayloadEasyJson() *SmallPayloadEasyJson {
return &SmallPayloadEasyJson{
St: 1,
Sid: 2,
Tt: "TestString",
Gr: 4,
Uuid: "8f9a65eb-4807-4d57-b6e0-bda5d62f1429",
Ip: "127.0.0.1",
Ua: "Mozilla",
Tz: 8,
V: 6,
}
}
func NewSmallPayloadFFJson() *SmallPayloadFFJson {
return &SmallPayloadFFJson{
St: 1,
Sid: 2,
Tt: "TestString",
Gr: 4,
Uuid: "8f9a65eb-4807-4d57-b6e0-bda5d62f1429",
Ip: "127.0.0.1",
Ua: "Mozilla",
Tz: 8,
V: 6,
}
}
golang-github-goccy-go-json-0.10.3/benchmarks/small_payload_easyjson.go 0000664 0000000 0000000 00000007046 14635552766 0026230 0 ustar 00root root 0000000 0000000 // Code generated by easyjson for marshaling/unmarshaling. DO NOT EDIT.
package benchmark
import (
json "encoding/json"
easyjson "github.com/mailru/easyjson"
jlexer "github.com/mailru/easyjson/jlexer"
jwriter "github.com/mailru/easyjson/jwriter"
)
// suppress unused package warning
var (
_ *json.RawMessage
_ *jlexer.Lexer
_ *jwriter.Writer
_ easyjson.Marshaler
)
func easyjson21677a1cDecodeBenchmark(in *jlexer.Lexer, out *SmallPayloadEasyJson) {
isTopLevel := in.IsStart()
if in.IsNull() {
if isTopLevel {
in.Consumed()
}
in.Skip()
return
}
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
in.WantColon()
if in.IsNull() {
in.Skip()
in.WantComma()
continue
}
switch key {
case "St":
out.St = int(in.Int())
case "Sid":
out.Sid = int(in.Int())
case "Tt":
out.Tt = string(in.String())
case "Gr":
out.Gr = int(in.Int())
case "Uuid":
out.Uuid = string(in.String())
case "Ip":
out.Ip = string(in.String())
case "Ua":
out.Ua = string(in.String())
case "Tz":
out.Tz = int(in.Int())
case "V":
out.V = int(in.Int())
default:
in.SkipRecursive()
}
in.WantComma()
}
in.Delim('}')
if isTopLevel {
in.Consumed()
}
}
func easyjson21677a1cEncodeBenchmark(out *jwriter.Writer, in SmallPayloadEasyJson) {
out.RawByte('{')
first := true
_ = first
{
const prefix string = ",\"St\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.Int(int(in.St))
}
{
const prefix string = ",\"Sid\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.Int(int(in.Sid))
}
{
const prefix string = ",\"Tt\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.Tt))
}
{
const prefix string = ",\"Gr\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.Int(int(in.Gr))
}
{
const prefix string = ",\"Uuid\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.Uuid))
}
{
const prefix string = ",\"Ip\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.Ip))
}
{
const prefix string = ",\"Ua\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.Ua))
}
{
const prefix string = ",\"Tz\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.Int(int(in.Tz))
}
{
const prefix string = ",\"V\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.Int(int(in.V))
}
out.RawByte('}')
}
// MarshalJSON supports json.Marshaler interface
func (v SmallPayloadEasyJson) MarshalJSON() ([]byte, error) {
w := jwriter.Writer{}
easyjson21677a1cEncodeBenchmark(&w, v)
return w.Buffer.BuildBytes(), w.Error
}
// MarshalEasyJSON supports easyjson.Marshaler interface
func (v SmallPayloadEasyJson) MarshalEasyJSON(w *jwriter.Writer) {
easyjson21677a1cEncodeBenchmark(w, v)
}
// UnmarshalJSON supports json.Unmarshaler interface
func (v *SmallPayloadEasyJson) UnmarshalJSON(data []byte) error {
r := jlexer.Lexer{Data: data}
easyjson21677a1cDecodeBenchmark(&r, v)
return r.Error()
}
// UnmarshalEasyJSON supports easyjson.Unmarshaler interface
func (v *SmallPayloadEasyJson) UnmarshalEasyJSON(l *jlexer.Lexer) {
easyjson21677a1cDecodeBenchmark(l, v)
}
golang-github-goccy-go-json-0.10.3/benchmarks/small_payload_ffjson.go 0000664 0000000 0000000 00000030477 14635552766 0025666 0 ustar 00root root 0000000 0000000 // Code generated by ffjson . DO NOT EDIT.
// source: small_payload.go
package benchmark
import (
"bytes"
"fmt"
fflib "github.com/pquerna/ffjson/fflib/v1"
)
// MarshalJSON marshal bytes to json - template
func (j *SmallPayloadFFJson) MarshalJSON() ([]byte, error) {
var buf fflib.Buffer
if j == nil {
buf.WriteString("null")
return buf.Bytes(), nil
}
err := j.MarshalJSONBuf(&buf)
if err != nil {
return nil, err
}
return buf.Bytes(), nil
}
// MarshalJSONBuf marshal buff to json - template
func (j *SmallPayloadFFJson) MarshalJSONBuf(buf fflib.EncodingBuffer) error {
if j == nil {
buf.WriteString("null")
return nil
}
var err error
var obj []byte
_ = obj
_ = err
buf.WriteString(`{"St":`)
fflib.FormatBits2(buf, uint64(j.St), 10, j.St < 0)
buf.WriteString(`,"Sid":`)
fflib.FormatBits2(buf, uint64(j.Sid), 10, j.Sid < 0)
buf.WriteString(`,"Tt":`)
fflib.WriteJsonString(buf, string(j.Tt))
buf.WriteString(`,"Gr":`)
fflib.FormatBits2(buf, uint64(j.Gr), 10, j.Gr < 0)
buf.WriteString(`,"Uuid":`)
fflib.WriteJsonString(buf, string(j.Uuid))
buf.WriteString(`,"Ip":`)
fflib.WriteJsonString(buf, string(j.Ip))
buf.WriteString(`,"Ua":`)
fflib.WriteJsonString(buf, string(j.Ua))
buf.WriteString(`,"Tz":`)
fflib.FormatBits2(buf, uint64(j.Tz), 10, j.Tz < 0)
buf.WriteString(`,"V":`)
fflib.FormatBits2(buf, uint64(j.V), 10, j.V < 0)
buf.WriteByte('}')
return nil
}
const (
ffjtSmallPayloadFFJsonbase = iota
ffjtSmallPayloadFFJsonnosuchkey
ffjtSmallPayloadFFJsonSt
ffjtSmallPayloadFFJsonSid
ffjtSmallPayloadFFJsonTt
ffjtSmallPayloadFFJsonGr
ffjtSmallPayloadFFJsonUuid
ffjtSmallPayloadFFJsonIp
ffjtSmallPayloadFFJsonUa
ffjtSmallPayloadFFJsonTz
ffjtSmallPayloadFFJsonV
)
var ffjKeySmallPayloadFFJsonSt = []byte("St")
var ffjKeySmallPayloadFFJsonSid = []byte("Sid")
var ffjKeySmallPayloadFFJsonTt = []byte("Tt")
var ffjKeySmallPayloadFFJsonGr = []byte("Gr")
var ffjKeySmallPayloadFFJsonUuid = []byte("Uuid")
var ffjKeySmallPayloadFFJsonIp = []byte("Ip")
var ffjKeySmallPayloadFFJsonUa = []byte("Ua")
var ffjKeySmallPayloadFFJsonTz = []byte("Tz")
var ffjKeySmallPayloadFFJsonV = []byte("V")
// UnmarshalJSON umarshall json - template of ffjson
func (j *SmallPayloadFFJson) UnmarshalJSON(input []byte) error {
fs := fflib.NewFFLexer(input)
return j.UnmarshalJSONFFLexer(fs, fflib.FFParse_map_start)
}
// UnmarshalJSONFFLexer fast json unmarshall - template ffjson
func (j *SmallPayloadFFJson) UnmarshalJSONFFLexer(fs *fflib.FFLexer, state fflib.FFParseState) error {
var err error
currentKey := ffjtSmallPayloadFFJsonbase
_ = currentKey
tok := fflib.FFTok_init
wantedTok := fflib.FFTok_init
mainparse:
for {
tok = fs.Scan()
// println(fmt.Sprintf("debug: tok: %v state: %v", tok, state))
if tok == fflib.FFTok_error {
goto tokerror
}
switch state {
case fflib.FFParse_map_start:
if tok != fflib.FFTok_left_bracket {
wantedTok = fflib.FFTok_left_bracket
goto wrongtokenerror
}
state = fflib.FFParse_want_key
continue
case fflib.FFParse_after_value:
if tok == fflib.FFTok_comma {
state = fflib.FFParse_want_key
} else if tok == fflib.FFTok_right_bracket {
goto done
} else {
wantedTok = fflib.FFTok_comma
goto wrongtokenerror
}
case fflib.FFParse_want_key:
// json {} ended. goto exit. woo.
if tok == fflib.FFTok_right_bracket {
goto done
}
if tok != fflib.FFTok_string {
wantedTok = fflib.FFTok_string
goto wrongtokenerror
}
kn := fs.Output.Bytes()
if len(kn) <= 0 {
// "" case. hrm.
currentKey = ffjtSmallPayloadFFJsonnosuchkey
state = fflib.FFParse_want_colon
goto mainparse
} else {
switch kn[0] {
case 'G':
if bytes.Equal(ffjKeySmallPayloadFFJsonGr, kn) {
currentKey = ffjtSmallPayloadFFJsonGr
state = fflib.FFParse_want_colon
goto mainparse
}
case 'I':
if bytes.Equal(ffjKeySmallPayloadFFJsonIp, kn) {
currentKey = ffjtSmallPayloadFFJsonIp
state = fflib.FFParse_want_colon
goto mainparse
}
case 'S':
if bytes.Equal(ffjKeySmallPayloadFFJsonSt, kn) {
currentKey = ffjtSmallPayloadFFJsonSt
state = fflib.FFParse_want_colon
goto mainparse
} else if bytes.Equal(ffjKeySmallPayloadFFJsonSid, kn) {
currentKey = ffjtSmallPayloadFFJsonSid
state = fflib.FFParse_want_colon
goto mainparse
}
case 'T':
if bytes.Equal(ffjKeySmallPayloadFFJsonTt, kn) {
currentKey = ffjtSmallPayloadFFJsonTt
state = fflib.FFParse_want_colon
goto mainparse
} else if bytes.Equal(ffjKeySmallPayloadFFJsonTz, kn) {
currentKey = ffjtSmallPayloadFFJsonTz
state = fflib.FFParse_want_colon
goto mainparse
}
case 'U':
if bytes.Equal(ffjKeySmallPayloadFFJsonUuid, kn) {
currentKey = ffjtSmallPayloadFFJsonUuid
state = fflib.FFParse_want_colon
goto mainparse
} else if bytes.Equal(ffjKeySmallPayloadFFJsonUa, kn) {
currentKey = ffjtSmallPayloadFFJsonUa
state = fflib.FFParse_want_colon
goto mainparse
}
case 'V':
if bytes.Equal(ffjKeySmallPayloadFFJsonV, kn) {
currentKey = ffjtSmallPayloadFFJsonV
state = fflib.FFParse_want_colon
goto mainparse
}
}
if fflib.SimpleLetterEqualFold(ffjKeySmallPayloadFFJsonV, kn) {
currentKey = ffjtSmallPayloadFFJsonV
state = fflib.FFParse_want_colon
goto mainparse
}
if fflib.SimpleLetterEqualFold(ffjKeySmallPayloadFFJsonTz, kn) {
currentKey = ffjtSmallPayloadFFJsonTz
state = fflib.FFParse_want_colon
goto mainparse
}
if fflib.SimpleLetterEqualFold(ffjKeySmallPayloadFFJsonUa, kn) {
currentKey = ffjtSmallPayloadFFJsonUa
state = fflib.FFParse_want_colon
goto mainparse
}
if fflib.SimpleLetterEqualFold(ffjKeySmallPayloadFFJsonIp, kn) {
currentKey = ffjtSmallPayloadFFJsonIp
state = fflib.FFParse_want_colon
goto mainparse
}
if fflib.SimpleLetterEqualFold(ffjKeySmallPayloadFFJsonUuid, kn) {
currentKey = ffjtSmallPayloadFFJsonUuid
state = fflib.FFParse_want_colon
goto mainparse
}
if fflib.SimpleLetterEqualFold(ffjKeySmallPayloadFFJsonGr, kn) {
currentKey = ffjtSmallPayloadFFJsonGr
state = fflib.FFParse_want_colon
goto mainparse
}
if fflib.SimpleLetterEqualFold(ffjKeySmallPayloadFFJsonTt, kn) {
currentKey = ffjtSmallPayloadFFJsonTt
state = fflib.FFParse_want_colon
goto mainparse
}
if fflib.EqualFoldRight(ffjKeySmallPayloadFFJsonSid, kn) {
currentKey = ffjtSmallPayloadFFJsonSid
state = fflib.FFParse_want_colon
goto mainparse
}
if fflib.EqualFoldRight(ffjKeySmallPayloadFFJsonSt, kn) {
currentKey = ffjtSmallPayloadFFJsonSt
state = fflib.FFParse_want_colon
goto mainparse
}
currentKey = ffjtSmallPayloadFFJsonnosuchkey
state = fflib.FFParse_want_colon
goto mainparse
}
case fflib.FFParse_want_colon:
if tok != fflib.FFTok_colon {
wantedTok = fflib.FFTok_colon
goto wrongtokenerror
}
state = fflib.FFParse_want_value
continue
case fflib.FFParse_want_value:
if tok == fflib.FFTok_left_brace || tok == fflib.FFTok_left_bracket || tok == fflib.FFTok_integer || tok == fflib.FFTok_double || tok == fflib.FFTok_string || tok == fflib.FFTok_bool || tok == fflib.FFTok_null {
switch currentKey {
case ffjtSmallPayloadFFJsonSt:
goto handle_St
case ffjtSmallPayloadFFJsonSid:
goto handle_Sid
case ffjtSmallPayloadFFJsonTt:
goto handle_Tt
case ffjtSmallPayloadFFJsonGr:
goto handle_Gr
case ffjtSmallPayloadFFJsonUuid:
goto handle_Uuid
case ffjtSmallPayloadFFJsonIp:
goto handle_Ip
case ffjtSmallPayloadFFJsonUa:
goto handle_Ua
case ffjtSmallPayloadFFJsonTz:
goto handle_Tz
case ffjtSmallPayloadFFJsonV:
goto handle_V
case ffjtSmallPayloadFFJsonnosuchkey:
err = fs.SkipField(tok)
if err != nil {
return fs.WrapErr(err)
}
state = fflib.FFParse_after_value
goto mainparse
}
} else {
goto wantedvalue
}
}
}
handle_St:
/* handler: j.St type=int kind=int quoted=false*/
{
if tok != fflib.FFTok_integer && tok != fflib.FFTok_null {
return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for int", tok))
}
}
{
if tok == fflib.FFTok_null {
} else {
tval, err := fflib.ParseInt(fs.Output.Bytes(), 10, 64)
if err != nil {
return fs.WrapErr(err)
}
j.St = int(tval)
}
}
state = fflib.FFParse_after_value
goto mainparse
handle_Sid:
/* handler: j.Sid type=int kind=int quoted=false*/
{
if tok != fflib.FFTok_integer && tok != fflib.FFTok_null {
return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for int", tok))
}
}
{
if tok == fflib.FFTok_null {
} else {
tval, err := fflib.ParseInt(fs.Output.Bytes(), 10, 64)
if err != nil {
return fs.WrapErr(err)
}
j.Sid = int(tval)
}
}
state = fflib.FFParse_after_value
goto mainparse
handle_Tt:
/* handler: j.Tt type=string kind=string quoted=false*/
{
{
if tok != fflib.FFTok_string && tok != fflib.FFTok_null {
return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok))
}
}
if tok == fflib.FFTok_null {
} else {
outBuf := fs.Output.Bytes()
j.Tt = string(string(outBuf))
}
}
state = fflib.FFParse_after_value
goto mainparse
handle_Gr:
/* handler: j.Gr type=int kind=int quoted=false*/
{
if tok != fflib.FFTok_integer && tok != fflib.FFTok_null {
return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for int", tok))
}
}
{
if tok == fflib.FFTok_null {
} else {
tval, err := fflib.ParseInt(fs.Output.Bytes(), 10, 64)
if err != nil {
return fs.WrapErr(err)
}
j.Gr = int(tval)
}
}
state = fflib.FFParse_after_value
goto mainparse
handle_Uuid:
/* handler: j.Uuid type=string kind=string quoted=false*/
{
{
if tok != fflib.FFTok_string && tok != fflib.FFTok_null {
return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok))
}
}
if tok == fflib.FFTok_null {
} else {
outBuf := fs.Output.Bytes()
j.Uuid = string(string(outBuf))
}
}
state = fflib.FFParse_after_value
goto mainparse
handle_Ip:
/* handler: j.Ip type=string kind=string quoted=false*/
{
{
if tok != fflib.FFTok_string && tok != fflib.FFTok_null {
return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok))
}
}
if tok == fflib.FFTok_null {
} else {
outBuf := fs.Output.Bytes()
j.Ip = string(string(outBuf))
}
}
state = fflib.FFParse_after_value
goto mainparse
handle_Ua:
/* handler: j.Ua type=string kind=string quoted=false*/
{
{
if tok != fflib.FFTok_string && tok != fflib.FFTok_null {
return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok))
}
}
if tok == fflib.FFTok_null {
} else {
outBuf := fs.Output.Bytes()
j.Ua = string(string(outBuf))
}
}
state = fflib.FFParse_after_value
goto mainparse
handle_Tz:
/* handler: j.Tz type=int kind=int quoted=false*/
{
if tok != fflib.FFTok_integer && tok != fflib.FFTok_null {
return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for int", tok))
}
}
{
if tok == fflib.FFTok_null {
} else {
tval, err := fflib.ParseInt(fs.Output.Bytes(), 10, 64)
if err != nil {
return fs.WrapErr(err)
}
j.Tz = int(tval)
}
}
state = fflib.FFParse_after_value
goto mainparse
handle_V:
/* handler: j.V type=int kind=int quoted=false*/
{
if tok != fflib.FFTok_integer && tok != fflib.FFTok_null {
return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for int", tok))
}
}
{
if tok == fflib.FFTok_null {
} else {
tval, err := fflib.ParseInt(fs.Output.Bytes(), 10, 64)
if err != nil {
return fs.WrapErr(err)
}
j.V = int(tval)
}
}
state = fflib.FFParse_after_value
goto mainparse
wantedvalue:
return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok))
wrongtokenerror:
return fs.WrapErr(fmt.Errorf("ffjson: wanted token: %v, but got token: %v output=%s", wantedTok, tok, fs.Output.String()))
tokerror:
if fs.BigError != nil {
return fs.WrapErr(fs.BigError)
}
err = fs.Error.ToError()
if err != nil {
return fs.WrapErr(err)
}
panic("ffjson-generated: unreachable, please report bug.")
done:
return nil
}
golang-github-goccy-go-json-0.10.3/benchmarks/testdata/ 0000775 0000000 0000000 00000000000 14635552766 0022747 5 ustar 00root root 0000000 0000000 golang-github-goccy-go-json-0.10.3/benchmarks/testdata/code.json.gz 0000664 0000000 0000000 00000353160 14635552766 0025203 0 ustar 00root root 0000000 0000000 ]o#9r_X߂&rCm-YRZҌ}߯ؒ-V7~fл(i~,U"/*Ͽ/l /_~y.f/?;m^jja!{E~~.i'2_l)/SŌB ){i|}9}V|1zrYtVNqo6<܈6l{W&L7Oښ쳾Uڬ:|﵍l}a)#e,#G >
;x+ʒo
Mֵz]oCv Pɩv*-)URG.< N9ȭrClbּ?.46`(aB'F1'>_-)Nz`Nm@溜"_ƶHŕ)> Z*
BC &ӂdD-\If8"K'Lq3:KDX+I8Bqj8(sRa,cH')B Q`hiNK 1oO~J_B}6(`dd¸B:ˇh1@P¤:>EA_g#Ø竼ʶ`mWC'
dK5b(lsH1a^Hvxc40b} V4!(Lam%BwTj@R3 K7^f&vw0nQ'8*`Rn' tg=BSʏO|cOpTf몜lc5C6LQialf8npO Jԥ
ʳY 9F[,,Z{#{^Ygٞ6|ϴ5B)N'ΰę1i=bzn}(phX|!'A$}[.d\oQi
h0߃!b$ɍPgdDi !6 -:N
,mQıҝ`e{x7Adt& sO5@:i$7t0ѼbB({c: jmT6L5{"4TD!\<w:iAE%HVi"+4iJX9C9߆vbz A1%>>{@t>NAQ)lRPO9J ̌14Gv ~>Wu6;uFf"@134WJ@PzD:#1G(%[̠OXºUS(CF7(DHdZ?eLKAZRNiy@z
*A|}ư˪T#-r,x^:rob-GUš¢ D#Xzǒ0`M0
n\*pG lf!8 -[ҭ
4r$wdu]d),Pvl) %-x"\m--c+>HNicdN9ƜGGJj]VOIꁆf٬%1kO>cuuo6'6kOT>@r8Na߰*|%N[⫟cf%FB,܍Fv7м-_p)Nyeez祎Jg9Γ;YCi/bNM\`qFߟEאf Hxz oN0N83K9BSU =*vsS-~0k]z|ȡ0ވ->(9KL54gxV-*5="Zf
FMhZsV^k^!Nztz~=
*sGÁ9wl?*ԶI=
UʕA^:&+\Q^UAP62Bщ3Y|FSLc:F`04`nyw9&<[#`rU"+$,tcqo'k0M34V-Gi-k!Rqo^]
DsD-mGe҂D*t%aD<-\gį<'Ə"fjcPʼn !
F\eFjEyn\eIALJ0В+z2>B넛{|Hjh*f@WB9mj^ctC喡ԣ[%UJCxx|muB/"\ho^L
;Q*˦)tOǛlZȪD{$yW4q|x=J-DMh