Skip to content

Commit

Permalink
feat: add InPlaceCompaction option
Browse files Browse the repository at this point in the history
The benchmarks now use in-place compaction to reduce allocations.

name                                       old time/op    new time/op    delta
Small/DifferReset/default-8                  2.15µs ± 2%    2.15µs ± 0%     ~     (p=0.239 n=10+10)
Small/Differ/default-8                       2.57µs ± 0%    2.57µs ± 1%     ~     (p=0.561 n=9+10)
Small/DifferReset/default-unordered-8        2.29µs ± 1%    2.31µs ± 1%   +0.63%  (p=0.001 n=9+10)
Small/Differ/default-unordered-8             2.94µs ± 1%    2.95µs ± 0%   +0.42%  (p=0.042 n=9+9)
Small/DifferReset/invertible-8               2.16µs ± 1%    2.18µs ± 1%   +0.80%  (p=0.001 n=8+10)
Small/Differ/invertible-8                    2.82µs ± 0%    2.82µs ± 1%     ~     (p=0.266 n=9+9)
Small/DifferReset/factorize-8                3.52µs ± 1%    3.53µs ± 0%     ~     (p=0.074 n=10+9)
Small/Differ/factorize-8                     4.10µs ± 1%    4.11µs ± 0%     ~     (p=0.483 n=9+10)
Small/DifferReset/rationalize-8              3.23µs ± 1%    2.29µs ± 0%  -29.13%  (p=0.000 n=9+9)
Small/Differ/rationalize-8                   3.80µs ± 1%    2.73µs ± 1%  -28.10%  (p=0.000 n=10+10)
Small/DifferReset/equivalent-8               2.13µs ± 0%    2.14µs ± 1%   +0.69%  (p=0.002 n=10+10)
Small/Differ/equivalent-8                    2.57µs ± 1%    2.57µs ± 1%     ~     (p=0.927 n=10+10)
Small/DifferReset/equivalent-unordered-8     2.30µs ± 0%    2.32µs ± 1%   +0.79%  (p=0.000 n=9+10)
Small/Differ/equivalent-unordered-8          2.74µs ± 0%    2.76µs ± 1%   +0.77%  (p=0.000 n=9+10)
Small/DifferReset/factor+ratio-8             4.64µs ± 1%    3.67µs ± 1%  -21.04%  (p=0.000 n=10+10)
Small/Differ/factor+ratio-8                  5.37µs ± 1%    4.26µs ± 1%  -20.55%  (p=0.000 n=10+10)
Small/DifferReset/all-8                      4.75µs ± 1%    3.77µs ± 0%  -20.60%  (p=0.000 n=9+9)
Small/Differ/all-8                           5.73µs ± 1%    4.59µs ± 0%  -19.79%  (p=0.000 n=10+10)
Small/DifferReset/all-unordered-8            4.95µs ± 1%    3.99µs ± 1%  -19.47%  (p=0.000 n=10+10)
Small/Differ/all-unordered-8                 5.92µs ± 0%    4.82µs ± 0%  -18.70%  (p=0.000 n=9+9)
Medium/DifferReset/default-8                 6.24µs ± 1%    6.23µs ± 0%     ~     (p=0.715 n=9+9)
Medium/Differ/default-8                      7.31µs ± 1%    7.30µs ± 1%     ~     (p=0.356 n=9+10)
Medium/DifferReset/default-unordered-8       6.81µs ± 1%    6.81µs ± 1%     ~     (p=0.953 n=10+9)
Medium/Differ/default-unordered-8            8.55µs ± 0%    8.52µs ± 1%   -0.42%  (p=0.008 n=10+9)
Medium/DifferReset/invertible-8              6.33µs ± 1%    6.32µs ± 1%     ~     (p=0.140 n=9+10)
Medium/Differ/invertible-8                   8.11µs ± 1%    8.09µs ± 0%     ~     (p=0.366 n=9+10)
Medium/DifferReset/factorize-8               11.3µs ± 0%    11.3µs ± 1%     ~     (p=1.000 n=9+10)
Medium/Differ/factorize-8                    13.0µs ± 0%    13.0µs ± 1%     ~     (p=0.496 n=8+9)
Medium/DifferReset/rationalize-8             15.3µs ± 1%     6.9µs ± 1%  -54.80%  (p=0.000 n=9+10)
Medium/Differ/rationalize-8                  17.3µs ± 1%     7.7µs ± 1%  -55.63%  (p=0.000 n=10+10)
Medium/DifferReset/equivalent-8              10.1µs ± 1%    10.0µs ± 1%   -0.41%  (p=0.043 n=10+9)
Medium/Differ/equivalent-8                   11.1µs ± 1%    11.1µs ± 1%     ~     (p=0.796 n=10+10)
Medium/DifferReset/equivalent-unordered-8    11.0µs ± 1%    11.0µs ± 1%     ~     (p=0.912 n=10+10)
Medium/Differ/equivalent-unordered-8         12.1µs ± 0%    12.1µs ± 0%     ~     (p=0.066 n=9+9)
Medium/DifferReset/factor+ratio-8            20.7µs ± 1%    11.8µs ± 0%  -43.04%  (p=0.000 n=10+9)
Medium/Differ/factor+ratio-8                 23.3µs ± 0%    13.1µs ± 0%  -43.71%  (p=0.000 n=9+9)
Medium/DifferReset/all-8                     25.1µs ± 0%    16.1µs ± 1%  -35.75%  (p=0.000 n=9+10)
Medium/Differ/all-8                          27.8µs ± 0%    17.9µs ± 1%  -35.77%  (p=0.000 n=9+9)
Medium/DifferReset/all-unordered-8           27.2µs ± 1%    17.7µs ± 1%  -35.21%  (p=0.000 n=10+9)
Medium/Differ/all-unordered-8                30.1µs ± 1%    19.5µs ± 0%  -35.44%  (p=0.000 n=9+10)

name                                       old alloc/op   new alloc/op   delta
Small/DifferReset/default-8                    216B ± 0%      216B ± 0%     ~     (all equal)
Small/Differ/default-8                       1.19kB ± 0%    1.19kB ± 0%     ~     (all equal)
Small/DifferReset/default-unordered-8          312B ± 0%      312B ± 0%     ~     (all equal)
Small/Differ/default-unordered-8             1.99kB ± 0%    1.99kB ± 0%     ~     (all equal)
Small/DifferReset/invertible-8                 216B ± 0%      216B ± 0%     ~     (all equal)
Small/Differ/invertible-8                    1.90kB ± 0%    1.90kB ± 0%     ~     (all equal)
Small/DifferReset/factorize-8                  400B ± 0%      400B ± 0%     ~     (all equal)
Small/Differ/factorize-8                     1.78kB ± 0%    1.78kB ± 0%     ~     (all equal)
Small/DifferReset/rationalize-8                360B ± 0%      224B ± 0%  -37.78%  (p=0.000 n=10+10)
Small/Differ/rationalize-8                   1.48kB ± 0%    1.20kB ± 0%  -18.92%  (p=0.000 n=10+10)
Small/DifferReset/equivalent-8                 216B ± 0%      216B ± 0%     ~     (all equal)
Small/Differ/equivalent-8                    1.19kB ± 0%    1.19kB ± 0%     ~     (all equal)
Small/DifferReset/equivalent-unordered-8       216B ± 0%      216B ± 0%     ~     (all equal)
Small/Differ/equivalent-unordered-8          1.19kB ± 0%    1.19kB ± 0%     ~     (all equal)
Small/DifferReset/factor+ratio-8               544B ± 0%      408B ± 0%  -25.00%  (p=0.000 n=10+10)
Small/Differ/factor+ratio-8                  2.06kB ± 0%    1.78kB ± 0%  -13.57%  (p=0.000 n=10+10)
Small/DifferReset/all-8                        544B ± 0%      408B ± 0%  -25.00%  (p=0.000 n=10+10)
Small/Differ/all-8                           2.77kB ± 0%    2.49kB ± 0%  -10.12%  (p=0.000 n=10+10)
Small/DifferReset/all-unordered-8              656B ± 0%      520B ± 0%  -20.73%  (p=0.000 n=10+10)
Small/Differ/all-unordered-8                 2.88kB ± 0%    2.60kB ± 0%   -9.72%  (p=0.000 n=10+10)
Medium/DifferReset/default-8                   624B ± 0%      624B ± 0%     ~     (all equal)
Medium/Differ/default-8                      3.71kB ± 0%    3.71kB ± 0%     ~     (all equal)
Medium/DifferReset/default-unordered-8         848B ± 0%      848B ± 0%     ~     (all equal)
Medium/Differ/default-unordered-8            7.01kB ± 0%    7.01kB ± 0%     ~     (all equal)
Medium/DifferReset/invertible-8                624B ± 0%      624B ± 0%     ~     (all equal)
Medium/Differ/invertible-8                   6.78kB ± 0%    6.78kB ± 0%     ~     (all equal)
Medium/DifferReset/factorize-8               1.41kB ± 0%    1.41kB ± 0%     ~     (p=0.470 n=10+10)
Medium/Differ/factorize-8                    5.60kB ± 0%    5.60kB ± 0%     ~     (p=0.736 n=10+10)
Medium/DifferReset/rationalize-8             1.14kB ± 0%    0.67kB ± 0%  -40.85%  (p=0.000 n=10+10)
Medium/Differ/rationalize-8                  5.12kB ± 0%    2.35kB ± 0%  -54.06%  (p=0.000 n=10+10)
Medium/DifferReset/equivalent-8              1.39kB ± 0%    1.39kB ± 0%     ~     (all equal)
Medium/Differ/equivalent-8                   4.48kB ± 0%    4.48kB ± 0%     ~     (all equal)
Medium/DifferReset/equivalent-unordered-8    1.49kB ± 0%    1.49kB ± 0%     ~     (all equal)
Medium/Differ/equivalent-unordered-8         4.58kB ± 0%    4.58kB ± 0%     ~     (all equal)
Medium/DifferReset/factor+ratio-8            1.92kB ± 0%    1.45kB ± 0%  -24.20%  (p=0.000 n=10+10)
Medium/Differ/factor+ratio-8                 7.01kB ± 0%    4.24kB ± 0%  -39.51%  (p=0.000 n=10+10)
Medium/DifferReset/all-8                     2.73kB ± 0%    2.22kB ± 0%  -18.73%  (p=0.000 n=10+10)
Medium/Differ/all-8                          7.82kB ± 0%    6.41kB ± 0%  -18.00%  (p=0.000 n=10+10)
Medium/DifferReset/all-unordered-8           2.88kB ± 0%    2.36kB ± 0%  -17.80%  (p=0.000 n=7+10)
Medium/Differ/all-unordered-8                7.96kB ± 0%    6.55kB ± 0%  -17.68%  (p=0.000 n=6+10)

name                                       old allocs/op  new allocs/op  delta
Small/DifferReset/default-8                    9.00 ± 0%      9.00 ± 0%     ~     (all equal)
Small/Differ/default-8                         13.0 ± 0%      13.0 ± 0%     ~     (all equal)
Small/DifferReset/default-unordered-8          13.0 ± 0%      13.0 ± 0%     ~     (all equal)
Small/Differ/default-unordered-8               18.0 ± 0%      18.0 ± 0%     ~     (all equal)
Small/DifferReset/invertible-8                 9.00 ± 0%      9.00 ± 0%     ~     (all equal)
Small/Differ/invertible-8                      14.0 ± 0%      14.0 ± 0%     ~     (all equal)
Small/DifferReset/factorize-8                  21.0 ± 0%      21.0 ± 0%     ~     (all equal)
Small/Differ/factorize-8                       27.0 ± 0%      27.0 ± 0%     ~     (all equal)
Small/DifferReset/rationalize-8                10.0 ± 0%      10.0 ± 0%     ~     (all equal)
Small/Differ/rationalize-8                     14.0 ± 0%      14.0 ± 0%     ~     (all equal)
Small/DifferReset/equivalent-8                 9.00 ± 0%      9.00 ± 0%     ~     (all equal)
Small/Differ/equivalent-8                      13.0 ± 0%      13.0 ± 0%     ~     (all equal)
Small/DifferReset/equivalent-unordered-8       9.00 ± 0%      9.00 ± 0%     ~     (all equal)
Small/Differ/equivalent-unordered-8            13.0 ± 0%      13.0 ± 0%     ~     (all equal)
Small/DifferReset/factor+ratio-8               22.0 ± 0%      22.0 ± 0%     ~     (all equal)
Small/Differ/factor+ratio-8                    28.0 ± 0%      28.0 ± 0%     ~     (all equal)
Small/DifferReset/all-8                        22.0 ± 0%      22.0 ± 0%     ~     (all equal)
Small/Differ/all-8                             29.0 ± 0%      29.0 ± 0%     ~     (all equal)
Small/DifferReset/all-unordered-8              25.0 ± 0%      25.0 ± 0%     ~     (all equal)
Small/Differ/all-unordered-8                   32.0 ± 0%      32.0 ± 0%     ~     (all equal)
Medium/DifferReset/default-8                   18.0 ± 0%      18.0 ± 0%     ~     (all equal)
Medium/Differ/default-8                        24.0 ± 0%      24.0 ± 0%     ~     (all equal)
Medium/DifferReset/default-unordered-8         26.0 ± 0%      26.0 ± 0%     ~     (all equal)
Medium/Differ/default-unordered-8              33.0 ± 0%      33.0 ± 0%     ~     (all equal)
Medium/DifferReset/invertible-8                18.0 ± 0%      18.0 ± 0%     ~     (all equal)
Medium/Differ/invertible-8                     25.0 ± 0%      25.0 ± 0%     ~     (all equal)
Medium/DifferReset/factorize-8                 55.0 ± 0%      55.0 ± 0%     ~     (all equal)
Medium/Differ/factorize-8                      64.0 ± 0%      64.0 ± 0%     ~     (all equal)
Medium/DifferReset/rationalize-8               19.0 ± 0%      22.0 ± 0%  +15.79%  (p=0.000 n=10+10)
Medium/Differ/rationalize-8                    25.0 ± 0%      27.0 ± 0%   +8.00%  (p=0.000 n=10+10)
Medium/DifferReset/equivalent-8                26.0 ± 0%      26.0 ± 0%     ~     (all equal)
Medium/Differ/equivalent-8                     32.0 ± 0%      32.0 ± 0%     ~     (all equal)
Medium/DifferReset/equivalent-unordered-8      30.0 ± 0%      30.0 ± 0%     ~     (all equal)
Medium/Differ/equivalent-unordered-8           36.0 ± 0%      36.0 ± 0%     ~     (all equal)
Medium/DifferReset/factor+ratio-8              56.0 ± 0%      59.0 ± 0%   +5.36%  (p=0.000 n=10+10)
Medium/Differ/factor+ratio-8                   65.0 ± 0%      67.0 ± 0%   +3.08%  (p=0.000 n=10+10)
Medium/DifferReset/all-8                       68.0 ± 0%      67.0 ± 0%   -1.47%  (p=0.000 n=10+10)
Medium/Differ/all-8                            77.0 ± 0%      76.0 ± 0%   -1.30%  (p=0.000 n=10+10)
Medium/DifferReset/all-unordered-8             75.0 ± 0%      74.0 ± 0%   -1.33%  (p=0.000 n=10+10)
Medium/Differ/all-unordered-8                  84.0 ± 0%      83.0 ± 0%   -1.19%  (p=0.000 n=10+10)
  • Loading branch information
wI2L committed Jun 3, 2023
1 parent 7130e0c commit 5497a04
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 72 deletions.
128 changes: 68 additions & 60 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,12 @@ Reducing the size of a JSON Patch is usually beneficial when it needs to be sent

When the `Rationalize()` option is enabled, the package pre-process the JSON input given to the `CompareJSON*` functions. If your inputs are already compact JSON documents, you **should** also use the `SkipCompact()` option to instruct the package to skip the compaction step, resulting in a *nice and free* performance improvement.

##### In-place compaction

By default, the package will not modify the JSON documents given to the `CompareJSON` and `CompareJSONOpts` functions. Instead, a copy of the `target` byte slice argument is created and then compacted to remove insignificant spaces.

To avoid an extra allocation, you can use the `InPlaceCompaction()` option to allow the package to *take ownership* of the `target` byte slice and modify it directly. **Note that you should not update it concurrently with a call to the `CompareJSON*` functions.**

#### Invertible patch

Using the functional option `Invertible()`, it is possible to instruct the diff generator to precede each `remove` and `replace` operation with a `test` operation. Such patches can be inverted to return a patched document to its original form.
Expand Down Expand Up @@ -367,7 +373,9 @@ By default, the package uses the `json.Marshal` and `json.Unmarshal` functions f

The prototype of the function argument accepted by these options is the same as the official `json.Marshal` and `json.Unmarshal` functions.

For example, the `UnmarshalFunc` option can be used to set up a custom JSON [`Decoder`](https://pkg.go.dev/encoding/json#Decoder) with the [`UserNumber`](https://pkg.go.dev/encoding/json#Decoder.UseNumber) flag enabled, to decode JSON numbers as [`json.Number`](https://pkg.go.dev/encoding/json#Decoder.UseNumber) instead of float64:
##### Custom decoder

In the following example, the `UnmarshalFunc` option is used to set up a custom JSON [`Decoder`](https://pkg.go.dev/encoding/json#Decoder) with the [`UserNumber`](https://pkg.go.dev/encoding/json#Decoder.UseNumber) flag enabled, to decode JSON numbers as [`json.Number`](https://pkg.go.dev/encoding/json#Decoder.UseNumber) instead of `float64`:

```go
patch, err := jsondiff.CompareJSONOpts(
Expand Down Expand Up @@ -405,46 +413,46 @@ Go : go version go1.20.4 darwin/amd64

<details><summary>Output</summary><br><pre>
name time/op
Small/DifferReset/default-8 2.13µs ± 1%
Small/Differ/default-8 2.56µs ± 1%
Small/DifferReset/default-unordered-8 2.29µs ± 1%
Small/Differ/default-unordered-8 2.93µs ± 1%
Small/DifferReset/invertible-8 2.16µs ± 0%
Small/Differ/invertible-8 2.81µs ± 1%
Small/DifferReset/factorize-8 3.52µs ± 0%
Small/Differ/factorize-8 4.09µs ± 1%
Small/DifferReset/rationalize-8 3.23µs ± 1%
Small/Differ/rationalize-8 3.82µs ± 3%
Small/DifferReset/equivalent-8 2.12µs ± 1%
Small/Differ/equivalent-8 2.56µs ± 1%
Small/DifferReset/equivalent-unordered-8 2.31µs ± 1%
Small/Differ/equivalent-unordered-8 2.74µs ± 1%
Small/DifferReset/factor+ratio-8 4.64µs ± 1%
Small/Differ/factor+ratio-8 5.35µs ± 1%
Small/DifferReset/all-8 4.74µs ± 0%
Small/Differ/all-8 5.73µs ± 1%
Small/DifferReset/all-unordered-8 4.94µs ± 0%
Small/Differ/all-unordered-8 5.91µs ± 1%
Medium/DifferReset/default-8 6.20µs ± 0%
Medium/Differ/default-8 7.27µs ± 0%
Medium/DifferReset/default-unordered-8 6.79µs ± 1%
Small/DifferReset/default-8 2.15µs ± 0%
Small/Differ/default-8 2.57µs ± 1%
Small/DifferReset/default-unordered-8 2.31µs ± 1%
Small/Differ/default-unordered-8 2.95µs ± 0%
Small/DifferReset/invertible-8 2.18µs ± 1%
Small/Differ/invertible-8 2.82µs ± 1%
Small/DifferReset/factorize-8 3.53µs ± 0%
Small/Differ/factorize-8 4.11µs ± 0%
Small/DifferReset/rationalize-8 2.29µs ± 0%
Small/Differ/rationalize-8 2.73µs ± 1%
Small/DifferReset/equivalent-8 2.14µs ± 1%
Small/Differ/equivalent-8 2.57µs ± 1%
Small/DifferReset/equivalent-unordered-8 2.32µs ± 1%
Small/Differ/equivalent-unordered-8 2.76µs ± 1%
Small/DifferReset/factor+ratio-8 3.67µs ± 1%
Small/Differ/factor+ratio-8 4.26µs ± 1%
Small/DifferReset/all-8 3.77µs ± 0%
Small/Differ/all-8 4.59µs ± 0%
Small/DifferReset/all-unordered-8 3.99µs ± 1%
Small/Differ/all-unordered-8 4.82µs ± 0%
Medium/DifferReset/default-8 6.23µs ± 0%
Medium/Differ/default-8 7.30µs ± 1%
Medium/DifferReset/default-unordered-8 6.81µs ± 1%
Medium/Differ/default-unordered-8 8.52µs ± 1%
Medium/DifferReset/invertible-8 6.32µs ± 0%
Medium/Differ/invertible-8 8.09µs ± 1%
Medium/DifferReset/invertible-8 6.32µs ± 1%
Medium/Differ/invertible-8 8.09µs ± 0%
Medium/DifferReset/factorize-8 11.3µs ± 1%
Medium/Differ/factorize-8 13.0µs ± 1%
Medium/DifferReset/rationalize-8 15.3µs ± 1%
Medium/Differ/rationalize-8 17.2µs ± 0%
Medium/DifferReset/equivalent-8 10.0µs ± 0%
Medium/DifferReset/rationalize-8 6.91µs ± 1%
Medium/Differ/rationalize-8 7.66µs ± 1%
Medium/DifferReset/equivalent-8 10.0µs ± 1%
Medium/Differ/equivalent-8 11.1µs ± 1%
Medium/DifferReset/equivalent-unordered-8 11.0µs ± 1%
Medium/Differ/equivalent-unordered-8 12.1µs ± 1%
Medium/DifferReset/factor+ratio-8 20.6µs ± 1%
Medium/Differ/factor+ratio-8 23.3µs ± 1%
Medium/DifferReset/all-8 24.9µs ± 0%
Medium/Differ/all-8 27.8µs ± 1%
Medium/DifferReset/all-unordered-8 27.3µs ± 1%
Medium/Differ/all-unordered-8 30.2µs ± 1%
Medium/Differ/equivalent-unordered-8 12.1µs ± 0%
Medium/DifferReset/factor+ratio-8 11.8µs ± 0%
Medium/Differ/factor+ratio-8 13.1µs ± 0%
Medium/DifferReset/all-8 16.1µs ± 1%
Medium/Differ/all-8 17.9µs ± 1%
Medium/DifferReset/all-unordered-8 17.7µs ± 1%
Medium/Differ/all-unordered-8 19.5µs ± 0%
<br>name alloc/op
Small/DifferReset/default-8 216B ± 0%
Small/Differ/default-8 1.19kB ± 0%
Expand All @@ -454,18 +462,18 @@ Small/DifferReset/invertible-8 216B ± 0%
Small/Differ/invertible-8 1.90kB ± 0%
Small/DifferReset/factorize-8 400B ± 0%
Small/Differ/factorize-8 1.78kB ± 0%
Small/DifferReset/rationalize-8 360B ± 0%
Small/Differ/rationalize-8 1.48kB ± 0%
Small/DifferReset/rationalize-8 224B ± 0%
Small/Differ/rationalize-8 1.20kB ± 0%
Small/DifferReset/equivalent-8 216B ± 0%
Small/Differ/equivalent-8 1.19kB ± 0%
Small/DifferReset/equivalent-unordered-8 216B ± 0%
Small/Differ/equivalent-unordered-8 1.19kB ± 0%
Small/DifferReset/factor+ratio-8 544B ± 0%
Small/Differ/factor+ratio-8 2.06kB ± 0%
Small/DifferReset/all-8 544B ± 0%
Small/Differ/all-8 2.77kB ± 0%
Small/DifferReset/all-unordered-8 656B ± 0%
Small/Differ/all-unordered-8 2.88kB ± 0%
Small/DifferReset/factor+ratio-8 408B ± 0%
Small/Differ/factor+ratio-8 1.78kB ± 0%
Small/DifferReset/all-8 408B ± 0%
Small/Differ/all-8 2.49kB ± 0%
Small/DifferReset/all-unordered-8 520B ± 0%
Small/Differ/all-unordered-8 2.60kB ± 0%
Medium/DifferReset/default-8 624B ± 0%
Medium/Differ/default-8 3.71kB ± 0%
Medium/DifferReset/default-unordered-8 848B ± 0%
Expand All @@ -474,18 +482,18 @@ Medium/DifferReset/invertible-8 624B ± 0%
Medium/Differ/invertible-8 6.78kB ± 0%
Medium/DifferReset/factorize-8 1.41kB ± 0%
Medium/Differ/factorize-8 5.60kB ± 0%
Medium/DifferReset/rationalize-8 1.14kB ± 0%
Medium/Differ/rationalize-8 5.12kB ± 0%
Medium/DifferReset/rationalize-8 672B ± 0%
Medium/Differ/rationalize-8 2.35kB ± 0%
Medium/DifferReset/equivalent-8 1.39kB ± 0%
Medium/Differ/equivalent-8 4.48kB ± 0%
Medium/DifferReset/equivalent-unordered-8 1.49kB ± 0%
Medium/Differ/equivalent-unordered-8 4.58kB ± 0%
Medium/DifferReset/factor+ratio-8 1.92kB ± 0%
Medium/Differ/factor+ratio-8 7.01kB ± 0%
Medium/DifferReset/all-8 2.73kB ± 0%
Medium/Differ/all-8 7.82kB ± 0%
Medium/DifferReset/all-unordered-8 2.88kB ± 0%
Medium/Differ/all-unordered-8 7.96kB ± 0%
Medium/DifferReset/factor+ratio-8 1.45kB ± 0%
Medium/Differ/factor+ratio-8 4.24kB ± 0%
Medium/DifferReset/all-8 2.22kB ± 0%
Medium/Differ/all-8 6.41kB ± 0%
Medium/DifferReset/all-unordered-8 2.36kB ± 0%
Medium/Differ/all-unordered-8 6.55kB ± 0%
<br>name allocs/op
Small/DifferReset/default-8 9.00 ± 0%
Small/Differ/default-8 13.0 ± 0%
Expand Down Expand Up @@ -515,18 +523,18 @@ Medium/DifferReset/invertible-8 18.0 ± 0%
Medium/Differ/invertible-8 25.0 ± 0%
Medium/DifferReset/factorize-8 55.0 ± 0%
Medium/Differ/factorize-8 64.0 ± 0%
Medium/DifferReset/rationalize-8 19.0 ± 0%
Medium/Differ/rationalize-8 25.0 ± 0%
Medium/DifferReset/rationalize-8 22.0 ± 0%
Medium/Differ/rationalize-8 27.0 ± 0%
Medium/DifferReset/equivalent-8 26.0 ± 0%
Medium/Differ/equivalent-8 32.0 ± 0%
Medium/DifferReset/equivalent-unordered-8 30.0 ± 0%
Medium/Differ/equivalent-unordered-8 36.0 ± 0%
Medium/DifferReset/factor+ratio-8 56.0 ± 0%
Medium/Differ/factor+ratio-8 65.0 ± 0%
Medium/DifferReset/all-8 68.0 ± 0%
Medium/Differ/all-8 77.0 ± 0%
Medium/DifferReset/all-unordered-8 75.0 ± 0%
Medium/Differ/all-unordered-8 84.0 ± 0%
Medium/DifferReset/factor+ratio-8 59.0 ± 0%
Medium/Differ/factor+ratio-8 67.0 ± 0%
Medium/DifferReset/all-8 67.0 ± 0%
Medium/Differ/all-8 76.0 ± 0%
Medium/DifferReset/all-unordered-8 74.0 ± 0%
Medium/Differ/all-unordered-8 83.0 ± 0%
</pre></details>

## Credits
Expand Down
23 changes: 19 additions & 4 deletions bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,11 @@ func subBenchmarks(b *testing.B, src, tgt, tgtUnordered []byte) {
if err := json.Unmarshal(bb.afterBytes, &after); err != nil {
b.Fatal(err)
}
b.ResetTimer()

b.Run("DifferReset/"+bb.name, func(b *testing.B) {
d := Differ{targetBytes: bb.afterBytes}
d := Differ{
targetBytes: compactBytes(bb.afterBytes),
isCompact: true,
}
for _, opt := range bb.opts {
opt(&d)
}
Expand All @@ -69,11 +70,18 @@ func subBenchmarks(b *testing.B, src, tgt, tgtUnordered []byte) {
d.Compare(before, after)
d.Reset()
}

})
b.Run("Differ/"+bb.name, func(b *testing.B) {
targetBytes := compactBytes(bb.afterBytes)
b.ReportAllocs()
b.ResetTimer()

for i := 0; i < b.N; i++ {
d := Differ{targetBytes: bb.afterBytes}
d := Differ{
targetBytes: targetBytes,
isCompact: true,
}
for _, opt := range bb.opts {
opt(&d)
}
Expand Down Expand Up @@ -106,3 +114,10 @@ func subBenchmarks(b *testing.B, src, tgt, tgtUnordered []byte) {
})
}
}

func compactBytes(src []byte) []byte {
b := make([]byte, 0, len(src))
copy(b, src)
b = _compact(b, b)
return b
}
15 changes: 7 additions & 8 deletions differ.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,17 +75,16 @@ func (d *Differ) Compare(src, tgt interface{}) {
d.prepare(d.ptr, src, tgt)
d.ptr.reset()
}
var doc string

if d.opts.rationalize {
if d.compactInPlace {
d.targetBytes = compactInPlace(d.targetBytes)
} else {
d.targetBytes = compact(d.targetBytes)
if !d.isCompact {
if d.compactInPlace {
d.targetBytes = compactInPlace(d.targetBytes)
} else {
d.targetBytes = compact(d.targetBytes)
}
}
doc = b2s(d.targetBytes)
}
d.diff(d.ptr, src, tgt, doc)
d.diff(d.ptr, src, tgt, b2s(d.targetBytes))
}

func (d *Differ) isIgnored(ptr pointer) bool {
Expand Down
15 changes: 15 additions & 0 deletions json_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package jsondiff

import (
"encoding/json"
"os"
"testing"
)

Expand Down Expand Up @@ -141,3 +142,17 @@ func Test_findIndex(t *testing.T) {
}
}
}

func Test__compact(t *testing.T) {
small, err := os.ReadFile("testdata/benchs/small/source.json")
if err != nil {
t.Fatal(err)
}
b := _compact(small, small)

const want = `{"pine":true,"silence":{"feathers":"could","lion":false,"provide":["lake",1886677335,"research",false],"ate":"nearest"},"already":true,"it":false}`

if string(b) != want {
t.Errorf("got %q, want %q", b, want)
}
}
10 changes: 10 additions & 0 deletions option.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,16 @@ func SkipCompact() Option {
}
}

// InPlaceCompaction instructs to compact the input JSON
// documents in place; it does not allocate to create
// a copy, but modify the original byte slice.
// This option has no effect if used alongside SkipCompact.
func InPlaceCompaction() Option {
return func(o *Differ) {
o.compactInPlace = true
}
}

// Ignores defines the list of values that are ignored
// by the diff generation, represented as a list of JSON
// Pointer strings (RFC 6901).
Expand Down

0 comments on commit 5497a04

Please sign in to comment.