Combine: Optimize for all nil (#55)

The current implementation of Combine returns the input slice in the
returned multierr. This causes it to escape to the heap unconditionally.
Optimizing for the no-errors case, we can copy the slice in that case
and keep it on the stack.

```
name                                old time/op    new time/op    delta
Combine/inline_1-8                    17.7ns ± 0%     2.1ns ± 0%   -88.20%  (p=0.008 n=5+5)
Combine/inline_2-8                    21.0ns ± 0%     4.4ns ± 1%   -79.03%  (p=0.008 n=5+5)
Combine/inline_3_no_error-8           24.4ns ± 0%     5.1ns ± 1%   -79.22%  (p=0.016 n=4+5)
Combine/inline_3_one_error-8          24.8ns ± 0%     5.4ns ± 1%   -78.42%  (p=0.008 n=5+5)
Combine/inline_3_multiple_errors-8    44.3ns ± 0%    54.9ns ± 0%   +23.80%  (p=0.008 n=5+5)
Combine/slice_100_no_errors-8         72.9ns ± 0%    73.4ns ± 1%    +0.68%  (p=0.008 n=5+5)
Combine/slice_100_one_error-8         74.5ns ± 0%    74.8ns ± 0%      ~     (p=0.056 n=5+5)
Combine/slice_100_multi_error-8        193ns ± 0%     193ns ± 0%      ~     (p=0.127 n=5+5)

name                                old alloc/op   new alloc/op   delta
Combine/inline_1-8                     16.0B ± 0%      0.0B       -100.00%  (p=0.008 n=5+5)
Combine/inline_2-8                     32.0B ± 0%      0.0B       -100.00%  (p=0.008 n=5+5)
Combine/inline_3_no_error-8            48.0B ± 0%      0.0B       -100.00%  (p=0.008 n=5+5)
Combine/inline_3_one_error-8           48.0B ± 0%      0.0B       -100.00%  (p=0.008 n=5+5)
Combine/inline_3_multiple_errors-8     80.0B ± 0%     80.0B ± 0%      ~     (all equal)
Combine/slice_100_no_errors-8          0.00B          0.00B           ~     (all equal)
Combine/slice_100_one_error-8          0.00B          0.00B           ~     (all equal)
Combine/slice_100_multi_error-8        64.0B ± 0%     64.0B ± 0%      ~     (all equal)

name                                old allocs/op  new allocs/op  delta
Combine/inline_1-8                      1.00 ± 0%      0.00       -100.00%  (p=0.008 n=5+5)
Combine/inline_2-8                      1.00 ± 0%      0.00       -100.00%  (p=0.008 n=5+5)
Combine/inline_3_no_error-8             1.00 ± 0%      0.00       -100.00%  (p=0.008 n=5+5)
Combine/inline_3_one_error-8            1.00 ± 0%      0.00       -100.00%  (p=0.008 n=5+5)
Combine/inline_3_multiple_errors-8      2.00 ± 0%      2.00 ± 0%      ~     (all equal)
Combine/slice_100_no_errors-8           0.00           0.00           ~     (all equal)
Combine/slice_100_one_error-8           0.00           0.00           ~     (all equal)
Combine/slice_100_multi_error-8         2.00 ± 0%      2.00 ± 0%      ~     (all equal)
```

Co-authored-by: Abhinav Gupta <abg@uber.com>
3 files changed
tree: 70a5c0a8a5fa35bda72f85a474ff4a5102f8f49a
  1. .github/
  2. tools/
  3. .codecov.yml
  4. .gitignore
  5. appendinvoke_example_test.go
  6. benchmarks_test.go
  7. CHANGELOG.md
  8. error.go
  9. error_ext_test.go
  10. error_test.go
  11. example_test.go
  12. glide.yaml
  13. go.mod
  14. go.sum
  15. LICENSE.txt
  16. Makefile
  17. README.md
README.md

multierr GoDoc Build Status Coverage Status

multierr allows combining one or more Go errors together.

Installation

go get -u go.uber.org/multierr

Status

Stable: No breaking changes will be made before 2.0.


Released under the MIT License.