gofrs / uuid

A UUID package for Go
MIT License
1.57k stars 110 forks source link

improve performance and reduce allocations of UUID methods #96

Closed charlievieth closed 1 year ago

charlievieth commented 2 years ago

This commit improves the performance and reduces the number of allocs of most UUID methods and adds a new UUID.Parse() method for parsing string encoded UUIDs.

Parsing string encoded UUIDs is now 2x faster and no longer allocates. The NullUUID MarshalJSON() and UnmarshalJSON() methods have also been improved and no longer call out to json.Unmarshal. The UUID.Format method has been improved for common cases.

Benchmark results:

goos: linux
goarch: amd64
pkg: github.com/gofrs/uuid
cpu: Intel(R) Core(TM) i9-9900K CPU @ 3.60GHz

name                        old time/op    new time/op    delta
UnmarshalText/canonical-16    47.7ns ± 0%    22.3ns ± 0%   -53.26%  (p=0.000 n=8+10)
UnmarshalText/urn-16          47.8ns ± 1%    22.3ns ± 0%   -53.32%  (p=0.000 n=10+10)
UnmarshalText/braced-16       47.8ns ± 1%    22.3ns ± 0%   -53.34%  (p=0.000 n=9+9)
ParseV4-16                    86.5ns ±10%    22.6ns ± 0%   -73.85%  (p=0.000 n=9+8)
NullMarshalJSON/Valid-16       308ns ±21%      72ns ±12%   -76.71%  (p=0.000 n=10+10)
NullMarshalJSON/Invalid-16    41.8ns ± 2%     1.4ns ± 0%   -96.59%  (p=0.000 n=10+8)
Format/s-16                    151ns ± 3%     143ns ± 7%    -5.18%  (p=0.003 n=10+10)
Format/S-16                    305ns ± 2%     161ns ± 2%   -47.38%  (p=0.000 n=10+9)
Format/q-16                    217ns ±12%     144ns ± 6%   -33.52%  (p=0.000 n=10+10)
Format/x-16                    170ns ±13%     123ns ± 1%   -27.95%  (p=0.000 n=10+10)
Format/X-16                    324ns ±11%     148ns ± 1%   -54.15%  (p=0.000 n=10+10)
Format/v-16                    156ns ± 4%     142ns ± 5%    -8.68%  (p=0.000 n=10+10)
Format/+v-16                   155ns ± 3%     142ns ± 6%    -8.67%  (p=0.000 n=10+10)
Format/#v-16                   894ns ± 1%     847ns ± 1%    -5.22%  (p=0.000 n=10+9)
String-16                     70.1ns ±36%    70.4ns ±29%      ~     (p=0.971 n=10+10)
FromBytes-16                  1.81ns ± 0%    1.81ns ± 0%    -0.15%  (p=0.010 n=8+9)
FromString/canonical-16       94.3ns ±20%    23.3ns ± 1%   -75.25%  (p=0.000 n=10+10)
FromString/urn-16             93.7ns ±11%    23.8ns ± 1%   -74.66%  (p=0.000 n=10+8)
FromString/braced-16          87.1ns ± 5%    23.5ns ± 1%   -73.03%  (p=0.000 n=9+10)
MarshalBinary-16              0.20ns ± 3%    0.20ns ± 1%      ~     (p=0.922 n=10+9)
MarshalText-16                 115ns ±25%      22ns ± 1%   -80.66%  (p=0.000 n=10+10)

name                        old alloc/op   new alloc/op   delta
UnmarshalText/canonical-16     0.00B          0.00B           ~     (all equal)
UnmarshalText/urn-16           0.00B          0.00B           ~     (all equal)
UnmarshalText/braced-16        0.00B          0.00B           ~     (all equal)
ParseV4-16                     48.0B ± 0%      0.0B       -100.00%  (p=0.000 n=10+10)
NullMarshalJSON/Valid-16        160B ± 0%       48B ± 0%   -70.00%  (p=0.000 n=10+10)
NullMarshalJSON/Invalid-16     8.00B ± 0%     0.00B       -100.00%  (p=0.000 n=10+10)
Format/s-16                    48.0B ± 0%     48.0B ± 0%      ~     (all equal)
Format/S-16                    96.0B ± 0%     48.0B ± 0%   -50.00%  (p=0.000 n=10+10)
Format/q-16                    96.0B ± 0%     48.0B ± 0%   -50.00%  (p=0.000 n=10+10)
Format/x-16                    64.0B ± 0%     32.0B ± 0%   -50.00%  (p=0.000 n=10+10)
Format/X-16                     112B ± 0%       32B ± 0%   -71.43%  (p=0.000 n=10+10)
Format/v-16                    48.0B ± 0%     48.0B ± 0%      ~     (all equal)
Format/+v-16                   48.0B ± 0%     48.0B ± 0%      ~     (all equal)
Format/#v-16                    128B ± 0%       16B ± 0%   -87.50%  (p=0.000 n=10+10)
String-16                      48.0B ± 0%     48.0B ± 0%      ~     (all equal)
FromBytes-16                   0.00B          0.00B           ~     (all equal)
FromString/canonical-16        48.0B ± 0%      0.0B       -100.00%  (p=0.000 n=10+10)
FromString/urn-16              48.0B ± 0%      0.0B       -100.00%  (p=0.000 n=10+10)
FromString/braced-16           48.0B ± 0%      0.0B       -100.00%  (p=0.000 n=10+10)
MarshalBinary-16               0.00B          0.00B           ~     (all equal)
MarshalText-16                 96.0B ± 0%      0.0B       -100.00%  (p=0.000 n=10+10)

name                        old allocs/op  new allocs/op  delta
UnmarshalText/canonical-16      0.00           0.00           ~     (all equal)
UnmarshalText/urn-16            0.00           0.00           ~     (all equal)
UnmarshalText/braced-16         0.00           0.00           ~     (all equal)
ParseV4-16                      1.00 ± 0%      0.00       -100.00%  (p=0.000 n=10+10)
NullMarshalJSON/Valid-16        4.00 ± 0%      1.00 ± 0%   -75.00%  (p=0.000 n=10+10)
NullMarshalJSON/Invalid-16      1.00 ± 0%      0.00       -100.00%  (p=0.000 n=10+10)
Format/s-16                     1.00 ± 0%      1.00 ± 0%      ~     (all equal)
Format/S-16                     2.00 ± 0%      1.00 ± 0%   -50.00%  (p=0.000 n=10+10)
Format/q-16                     2.00 ± 0%      1.00 ± 0%   -50.00%  (p=0.000 n=10+10)
Format/x-16                     2.00 ± 0%      1.00 ± 0%   -50.00%  (p=0.000 n=10+10)
Format/X-16                     3.00 ± 0%      1.00 ± 0%   -66.67%  (p=0.000 n=10+10)
Format/v-16                     1.00 ± 0%      1.00 ± 0%      ~     (all equal)
Format/+v-16                    1.00 ± 0%      1.00 ± 0%      ~     (all equal)
Format/#v-16                    2.00 ± 0%      1.00 ± 0%   -50.00%  (p=0.000 n=10+10)
String-16                       1.00 ± 0%      1.00 ± 0%      ~     (all equal)
FromBytes-16                    0.00           0.00           ~     (all equal)
FromString/canonical-16         1.00 ± 0%      0.00       -100.00%  (p=0.000 n=10+10)
FromString/urn-16               1.00 ± 0%      0.00       -100.00%  (p=0.000 n=10+10)
FromString/braced-16            1.00 ± 0%      0.00       -100.00%  (p=0.000 n=10+10)
MarshalBinary-16                0.00           0.00           ~     (all equal)
MarshalText-16                  2.00 ± 0%      0.00       -100.00%  (p=0.000 n=10+10)
codecov-commenter commented 2 years ago

Codecov Report

Base: 100.00% // Head: 100.00% // No change to project coverage :thumbsup:

Coverage data is based on head (2a97ddf) compared to base (e1079f3). Patch coverage: 100.00% of modified lines in pull request are covered.

Additional details and impacted files ```diff @@ Coverage Diff @@ ## master #96 +/- ## ========================================= Coverage 100.00% 100.00% ========================================= Files 4 4 Lines 411 448 +37 ========================================= + Hits 411 448 +37 ``` | [Impacted Files](https://codecov.io/gh/gofrs/uuid/pull/96?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=gofrs) | Coverage Δ | | |---|---|---| | [codec.go](https://codecov.io/gh/gofrs/uuid/pull/96/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=gofrs#diff-Y29kZWMuZ28=) | `100.00% <100.00%> (ø)` | | | [sql.go](https://codecov.io/gh/gofrs/uuid/pull/96/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=gofrs#diff-c3FsLmdv) | `100.00% <100.00%> (ø)` | | | [uuid.go](https://codecov.io/gh/gofrs/uuid/pull/96/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=gofrs#diff-dXVpZC5nbw==) | `100.00% <100.00%> (ø)` | | Help us with your feedback. Take ten seconds to tell us [how you rate us](https://about.codecov.io/nps?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=gofrs). Have a feature suggestion? [Share it here.](https://app.codecov.io/gh/feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=gofrs)

:umbrella: View full report at Codecov.
:loudspeaker: Do you have feedback about the report comment? Let us know in this issue.

charlievieth commented 2 years ago

@cameracker @theckman I see you've both recently contributed to and reviewed PRs for this repo. Are you the right people to ping for a review here?

theckman commented 2 years ago

Yep. I may have some time this coming weekend to go over this. Not sure about Cameron.

charlievieth commented 2 years ago

Thanks the for quick response and no hurries on the review, I just wanted to make sure someone was aware of this PR.

charlievieth commented 2 years ago

@theckman any chance you have time for a review and if not is there someone else I should ping? Thanks!

TerminalFi commented 2 years ago

Bump, this is a great improvement

charlievieth commented 1 year ago

@dylan-bourque if everything looks good, could I get another approval from @LeonanCarvalho or any other maintaner?

LeonanCarvalho commented 1 year ago

@dylan-bourque if everything looks good, could I get another approval from @LeonanCarvalho or any other maintaner?

I'm not a maintainer, I'm just an enthusiast, your changes to looks good to me

charlievieth commented 1 year ago

@cameracker (or anyone else with write access) could I get this reviewed/merged?

cameracker commented 1 year ago

@charlievieth I'll give it a look over today with the plan to merge. Thanks so much <3