etcd-io / raft

Raft library for maintaining a replicated state machine
Apache License 2.0
666 stars 164 forks source link

Allow reuse of slices exposed through Ready #51

Open CaojiamingAlan opened 1 year ago

CaojiamingAlan commented 1 year ago

Solve https://github.com/etcd-io/raft/issues/15: Use pooled slice to reduce the total bytes allocated. Benchmark result:

 % benchdiff --old 177ef28a -r BenchmarkRawNode -c 5 .
test binaries already exist for '177ef28'; skipping build
checking out 'e5ac368'
building benchmark binaries for 'e5ac368' 1/1 -

  pkg=1/1 iter=5/5 go.etcd.io/raft/v3 |

name                    old time/op        new time/op        delta
RawNode/single-voter-8         922ns ± 3%         883ns ± 2%   -4.14%  (p=0.008 n=5+5)
RawNode/two-voters-8          1.33µs ± 1%        1.36µs ± 1%   +1.79%  (p=0.032 n=4+5)

name                    old firstIndex/op  new firstIndex/op  delta
RawNode/single-voter-8          1.00 ± 0%          1.00 ± 0%     ~     (all equal)
RawNode/two-voters-8            3.00 ± 0%          3.00 ± 0%     ~     (all equal)

name                    old lastIndex/op   new lastIndex/op   delta
RawNode/single-voter-8          2.00 ± 0%          2.00 ± 0%     ~     (all equal)
RawNode/two-voters-8            2.00 ± 0%          2.00 ± 0%     ~     (all equal)

name                    old ready/op       new ready/op       delta
RawNode/single-voter-8          2.00 ± 0%          2.00 ± 0%     ~     (all equal)
RawNode/two-voters-8            2.00 ± 0%          2.00 ± 0%     ~     (all equal)

name                    old term/op        new term/op        delta
RawNode/single-voter-8          0.00 ± 8%          0.00 ± 0%     ~     (p=0.444 n=5+5)
RawNode/two-voters-8            1.00 ± 0%          1.00 ± 0%     ~     (all equal)

name                    old alloc/op       new alloc/op       delta
RawNode/single-voter-8          551B ± 0%          410B ± 1%  -25.59%  (p=0.000 n=4+5)
RawNode/two-voters-8            843B ± 1%          702B ± 0%  -16.68%  (p=0.008 n=5+5)

name                    old allocs/op      new allocs/op      delta
RawNode/single-voter-8          4.00 ± 0%          4.00 ± 0%     ~     (all equal)
RawNode/two-voters-8            6.00 ± 0%          6.00 ± 0%     ~     (all equal)
CaojiamingAlan commented 1 year ago

@pavelkalinnikov Thank you for your comments! I've resolved them.

we still reallocate and copy the slice.

The trick is at when we put back the slice:

rn.raft.msgsAfterAppendPool.Put(rn.raft.msgsAfterAppend[:0])

This clears the slice but reserves the underlying array, which we can reuse so that we don't need to allocate a new one each iteration.