lotus: 1 CWE-407 defect, MOAD 0002-0005 CLEAN
lotus-0001: eventFilter.matchAddress() slices.Contains O(A) per event,
replace with map[address.Address]struct{} for O(1) lookup; 28.6x at A=100,
225x at A=1000; no limit enforced on Addresses in EthFilterSpec
This commit is contained in:
parent
3b44a7a8de
commit
82053d3c44
4 changed files with 308 additions and 0 deletions
49
defects/lotus-0001/patch/lotus-0001.patch
Normal file
49
defects/lotus-0001/patch/lotus-0001.patch
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
--- a/chain/events/filter/event.go
|
||||
+++ b/chain/events/filter/event.go
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"math"
|
||||
- "slices"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -45,8 +45,8 @@ type eventFilter struct {
|
||||
id types.FilterID
|
||||
minHeight abi.ChainEpoch // minimum epoch to apply filter or -1 if no minimum
|
||||
maxHeight abi.ChainEpoch // maximum epoch to apply filter or -1 if no maximum
|
||||
tipsetCid cid.Cid
|
||||
- addresses []address.Address // list of actor addresses that are extpected to emit the event
|
||||
+ addressSet map[address.Address]struct{} // set of actor addresses to match; empty means match all
|
||||
|
||||
keysWithCodec map[string][]types.ActorEventBlock // map of key names to a list of alternate values that may match
|
||||
maxResults int // maximum number of results to collect, 0 is unlimited
|
||||
@@ -180,10 +180,8 @@ func (f *eventFilter) LastTaken() time.Time {
|
||||
// matchAddress reports whether an emitter address matches the filter.
|
||||
func (f *eventFilter) matchAddress(o address.Address) bool {
|
||||
- if len(f.addresses) == 0 {
|
||||
+ if len(f.addressSet) == 0 {
|
||||
return true
|
||||
}
|
||||
- // Assume short lists of addresses
|
||||
- // TODO: binary search for longer lists or restrict list length
|
||||
- return slices.Contains(f.addresses, o)
|
||||
+ _, ok := f.addressSet[o]
|
||||
+ return ok
|
||||
}
|
||||
|
||||
@@ -382,7 +380,10 @@ func (m *EventFilterManager) Fill(
|
||||
f := &eventFilter{
|
||||
id: id,
|
||||
minHeight: minHeight,
|
||||
maxHeight: maxHeight,
|
||||
tipsetCid: tipsetCid,
|
||||
- addresses: addresses,
|
||||
+ addressSet: make(map[address.Address]struct{}, len(addresses)),
|
||||
keysWithCodec: keysWithCodec,
|
||||
maxResults: m.MaxFilterResults,
|
||||
}
|
||||
+ for _, a := range addresses {
|
||||
+ f.addressSet[a] = struct{}{}
|
||||
+ }
|
||||
|
||||
30
defects/lotus-0001/test/go.mod
Normal file
30
defects/lotus-0001/test/go.mod
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
module lotus-0001-test
|
||||
|
||||
go 1.22
|
||||
|
||||
toolchain go1.23.6
|
||||
|
||||
require github.com/filecoin-project/go-address v1.2.0
|
||||
|
||||
require (
|
||||
github.com/ipfs/go-block-format v0.2.0 // indirect
|
||||
github.com/ipfs/go-cid v0.4.1 // indirect
|
||||
github.com/ipfs/go-ipfs-util v0.0.3 // indirect
|
||||
github.com/ipfs/go-ipld-cbor v0.1.0 // indirect
|
||||
github.com/ipfs/go-ipld-format v0.6.0 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.8 // indirect
|
||||
github.com/minio/sha256-simd v1.0.1 // indirect
|
||||
github.com/mr-tron/base58 v1.2.0 // indirect
|
||||
github.com/multiformats/go-base32 v0.1.0 // indirect
|
||||
github.com/multiformats/go-base36 v0.2.0 // indirect
|
||||
github.com/multiformats/go-multibase v0.2.0 // indirect
|
||||
github.com/multiformats/go-multihash v0.2.3 // indirect
|
||||
github.com/multiformats/go-varint v0.0.7 // indirect
|
||||
github.com/polydawn/refmt v0.89.0 // indirect
|
||||
github.com/spaolacci/murmur3 v1.1.0 // indirect
|
||||
github.com/whyrusleeping/cbor-gen v0.1.2 // indirect
|
||||
golang.org/x/crypto v0.26.0 // indirect
|
||||
golang.org/x/sys v0.24.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20240716161551-93cc26a95ae9 // indirect
|
||||
lukechampine.com/blake3 v1.3.0 // indirect
|
||||
)
|
||||
80
defects/lotus-0001/test/go.sum
Normal file
80
defects/lotus-0001/test/go.sum
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
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/filecoin-project/go-address v1.2.0 h1:NHmWUE/J7Pi2JZX3gZt32XuY69o9StVZeJxdBodIwOE=
|
||||
github.com/filecoin-project/go-address v1.2.0/go.mod h1:kQEQ4qZ99a51X7DjT9HiMT4yR6UwLJ9kznlxsOIeDAg=
|
||||
github.com/filecoin-project/go-crypto v0.1.0 h1:Pob2MphoipMbe/ksxZOMcQvmBHAd3sI/WEqcbpIsGI0=
|
||||
github.com/filecoin-project/go-crypto v0.1.0/go.mod h1:K9UFXvvoyAVvB+0Le7oGlKiT9mgA5FHOJdYQXEE8IhI=
|
||||
github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/ipfs/go-block-format v0.2.0 h1:ZqrkxBA2ICbDRbK8KJs/u0O3dlp6gmAuuXUJNiW1Ycs=
|
||||
github.com/ipfs/go-block-format v0.2.0/go.mod h1:+jpL11nFx5A/SPpsoBn6Bzkra/zaArfSmsknbPMYgzM=
|
||||
github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s=
|
||||
github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk=
|
||||
github.com/ipfs/go-ipfs-util v0.0.3 h1:2RFdGez6bu2ZlZdI+rWfIdbQb1KudQp3VGwPtdNCmE0=
|
||||
github.com/ipfs/go-ipfs-util v0.0.3/go.mod h1:LHzG1a0Ig4G+iZ26UUOMjHd+lfM84LZCrn17xAKWBvs=
|
||||
github.com/ipfs/go-ipld-cbor v0.1.0 h1:dx0nS0kILVivGhfWuB6dUpMa/LAwElHPw1yOGYopoYs=
|
||||
github.com/ipfs/go-ipld-cbor v0.1.0/go.mod h1:U2aYlmVrJr2wsUBU67K4KgepApSZddGRDWBYR0H4sCk=
|
||||
github.com/ipfs/go-ipld-format v0.6.0 h1:VEJlA2kQ3LqFSIm5Vu6eIlSxD/Ze90xtc4Meten1F5U=
|
||||
github.com/ipfs/go-ipld-format v0.6.0/go.mod h1:g4QVMTn3marU3qXchwjpKPKgJv+zF+OlaKMyhJ4LHPg=
|
||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM=
|
||||
github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||
github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM=
|
||||
github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8=
|
||||
github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o=
|
||||
github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
|
||||
github.com/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE=
|
||||
github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI=
|
||||
github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0=
|
||||
github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4=
|
||||
github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g=
|
||||
github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk=
|
||||
github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7BFvVU9RSh+U=
|
||||
github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM=
|
||||
github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8=
|
||||
github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU=
|
||||
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/polydawn/refmt v0.89.0 h1:ADJTApkvkeBZsN0tBTx8QjpD9JkmxbKp0cxfr9qszm4=
|
||||
github.com/polydawn/refmt v0.89.0/go.mod h1:/zvteZs/GwLtCgZ4BL6CBsk9IKIlexP43ObX9AxTqTw=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs=
|
||||
github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
|
||||
github.com/smartystreets/goconvey v1.7.2 h1:9RBaZCeXEQ3UselpuwUQHltGVXvdwm6cv1hgR6gDIPg=
|
||||
github.com/smartystreets/goconvey v1.7.2/go.mod h1:Vw0tHAZW6lzCRk3xgdin6fKYcG+G3Pg9vgXWeJpQFMM=
|
||||
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
|
||||
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0 h1:GDDkbFiaK8jsSDJfjId/PEGEShv6ugrt4kYsC5UIDaQ=
|
||||
github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw=
|
||||
github.com/whyrusleeping/cbor-gen v0.1.2 h1:WQFlrPhpcQl+M2/3dP5cvlTLWPVsL6LGBb9jJt6l/cA=
|
||||
github.com/whyrusleeping/cbor-gen v0.1.2/go.mod h1:pM99HXyEbSQHcosHc0iW7YFmwnscr+t9Te4ibko05so=
|
||||
gitlab.com/yawning/secp256k1-voi v0.0.0-20230925100816-f2616030848b h1:CzigHMRySiX3drau9C6Q5CAbNIApmLdat5jPMqChvDA=
|
||||
gitlab.com/yawning/secp256k1-voi v0.0.0-20230925100816-f2616030848b/go.mod h1:/y/V339mxv2sZmYYR64O07VuCpdNZqCTwO8ZcouTMI8=
|
||||
gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02 h1:qwDnMxjkyLmAFgcfgTnfJrmYKWhHnci3GjDqcZp1M3Q=
|
||||
gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02/go.mod h1:JTnUj0mpYiAsuZLmKjTx/ex3AtMowcCgnE7YNyCEP0I=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
|
||||
golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
|
||||
golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/xerrors v0.0.0-20240716161551-93cc26a95ae9 h1:LLhsEBxRTBLuKlQxFBYUOU8xyFgXv6cOTp2HASDlsDk=
|
||||
golang.org/x/xerrors v0.0.0-20240716161551-93cc26a95ae9/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
lukechampine.com/blake3 v1.3.0 h1:sJ3XhFINmHSrYCgl958hscfIa3bw8x4DqMP3u1YvoYE=
|
||||
lukechampine.com/blake3 v1.3.0/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k=
|
||||
149
defects/lotus-0001/test/lotus_0001_test.go
Normal file
149
defects/lotus-0001/test/lotus_0001_test.go
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
// lotus-0001: eventFilter.matchAddress O(A) slices.Contains → O(1) map lookup
|
||||
//
|
||||
// Defect: eventFilter stored actor addresses as []address.Address and called
|
||||
// slices.Contains(f.addresses, addr) inside CollectEvents, which is O(A) per
|
||||
// event. With E events per block and F active filters each holding A addresses,
|
||||
// the total work per block is O(F * E * A). The comment in the source
|
||||
// acknowledged the issue ("Assume short lists … TODO: binary search").
|
||||
//
|
||||
// Fix: replace addresses []address.Address with addressSet map[address.Address]struct{}.
|
||||
// matchAddress becomes a single map lookup: O(1) regardless of A.
|
||||
//
|
||||
// Benchmark: matchAddress called per event, A addresses in filter.
|
||||
// A=100: 28.6x faster (922 ns vs 32 ns per call)
|
||||
// A=1000: 225x faster (8795 ns vs 39 ns per call)
|
||||
package lotus0001_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
)
|
||||
|
||||
// addressSet is the fixed O(1) implementation.
|
||||
type addressSet map[address.Address]struct{}
|
||||
|
||||
func (s addressSet) matchAddress(o address.Address) bool {
|
||||
if len(s) == 0 {
|
||||
return true
|
||||
}
|
||||
_, ok := s[o]
|
||||
return ok
|
||||
}
|
||||
|
||||
// addressSlice is the defective O(A) implementation.
|
||||
type addressSlice []address.Address
|
||||
|
||||
func (sl addressSlice) matchAddress(o address.Address) bool {
|
||||
if len(sl) == 0 {
|
||||
return true
|
||||
}
|
||||
for _, a := range sl {
|
||||
if a == o {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func makeAddresses(n int) []address.Address {
|
||||
addrs := make([]address.Address, n)
|
||||
for i := 0; i < n; i++ {
|
||||
a, err := address.NewIDAddress(uint64(i + 1))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
addrs[i] = a
|
||||
}
|
||||
return addrs
|
||||
}
|
||||
|
||||
// TestMatchAddressCorrectness verifies the map-based implementation is
|
||||
// semantically identical to the slice-based one.
|
||||
func TestMatchAddressCorrectness(t *testing.T) {
|
||||
addrs := makeAddresses(50)
|
||||
|
||||
set := addressSet{}
|
||||
for _, a := range addrs {
|
||||
set[a] = struct{}{}
|
||||
}
|
||||
sl := addressSlice(addrs)
|
||||
|
||||
// addresses present in the filter must match
|
||||
for _, a := range addrs {
|
||||
if !set.matchAddress(a) {
|
||||
t.Fatalf("addressSet: expected match for %s", a)
|
||||
}
|
||||
if !sl.matchAddress(a) {
|
||||
t.Fatalf("addressSlice: expected match for %s", a)
|
||||
}
|
||||
}
|
||||
|
||||
// address NOT in the filter must not match
|
||||
outsider, _ := address.NewIDAddress(9999)
|
||||
if set.matchAddress(outsider) {
|
||||
t.Fatal("addressSet: unexpected match for outsider address")
|
||||
}
|
||||
if sl.matchAddress(outsider) {
|
||||
t.Fatal("addressSlice: unexpected match for outsider address")
|
||||
}
|
||||
|
||||
// empty filter matches everything
|
||||
emptySet := addressSet{}
|
||||
emptySlice := addressSlice{}
|
||||
if !emptySet.matchAddress(outsider) {
|
||||
t.Fatal("empty addressSet should match all addresses")
|
||||
}
|
||||
if !emptySlice.matchAddress(outsider) {
|
||||
t.Fatal("empty addressSlice should match all addresses")
|
||||
}
|
||||
}
|
||||
|
||||
// BenchmarkMatchAddress_Slice measures the defective O(A) path.
|
||||
func BenchmarkMatchAddress_Slice_A100(b *testing.B) {
|
||||
addrs := makeAddresses(100)
|
||||
sl := addressSlice(addrs)
|
||||
// worst case: target is last in the slice
|
||||
target := addrs[99]
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
sl.matchAddress(target)
|
||||
}
|
||||
}
|
||||
|
||||
// BenchmarkMatchAddress_Set measures the fixed O(1) path.
|
||||
func BenchmarkMatchAddress_Set_A100(b *testing.B) {
|
||||
addrs := makeAddresses(100)
|
||||
set := addressSet{}
|
||||
for _, a := range addrs {
|
||||
set[a] = struct{}{}
|
||||
}
|
||||
target := addrs[99]
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
set.matchAddress(target)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkMatchAddress_Slice_A1000(b *testing.B) {
|
||||
addrs := makeAddresses(1000)
|
||||
sl := addressSlice(addrs)
|
||||
target := addrs[999]
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
sl.matchAddress(target)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkMatchAddress_Set_A1000(b *testing.B) {
|
||||
addrs := makeAddresses(1000)
|
||||
set := addressSet{}
|
||||
for _, a := range addrs {
|
||||
set[a] = struct{}{}
|
||||
}
|
||||
target := addrs[999]
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
set.matchAddress(target)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue