github.com/xxRanger/go-ethereum@v1.8.23/swarm/storage/localstore/retrieval_index_test.go (about)

     1  // Copyright 2018 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package localstore
    18  
    19  import (
    20  	"strconv"
    21  	"testing"
    22  
    23  	"github.com/ethereum/go-ethereum/swarm/storage"
    24  )
    25  
    26  // BenchmarkRetrievalIndexes uploads a number of chunks in order to measure
    27  // total time of updating their retrieval indexes by setting them
    28  // to synced state and requesting them.
    29  //
    30  // This benchmark takes significant amount of time.
    31  //
    32  // Measurements on MacBook Pro (Retina, 15-inch, Mid 2014) show
    33  // that two separated indexes perform better.
    34  //
    35  // # go test -benchmem -run=none github.com/ethereum/go-ethereum/swarm/storage/localstore -bench BenchmarkRetrievalIndexes -v
    36  // goos: darwin
    37  // goarch: amd64
    38  // pkg: github.com/ethereum/go-ethereum/swarm/storage/localstore
    39  // BenchmarkRetrievalIndexes/1000-8         	      20       75556686 ns/op      19033493 B/op       84500 allocs/op
    40  // BenchmarkRetrievalIndexes/10000-8        	       1     1079084922 ns/op     382792064 B/op     1429644 allocs/op
    41  // BenchmarkRetrievalIndexes/100000-8       	       1    16891305737 ns/op    2629165304 B/op    12465019 allocs/op
    42  // PASS
    43  func BenchmarkRetrievalIndexes(b *testing.B) {
    44  	for _, count := range []int{
    45  		1000,
    46  		10000,
    47  		100000,
    48  	} {
    49  		b.Run(strconv.Itoa(count)+"-split", func(b *testing.B) {
    50  			for n := 0; n < b.N; n++ {
    51  				benchmarkRetrievalIndexes(b, nil, count)
    52  			}
    53  		})
    54  	}
    55  }
    56  
    57  // benchmarkRetrievalIndexes is used in BenchmarkRetrievalIndexes
    58  // to do benchmarks with a specific number of chunks and different
    59  // database options.
    60  func benchmarkRetrievalIndexes(b *testing.B, o *Options, count int) {
    61  	b.StopTimer()
    62  	db, cleanupFunc := newTestDB(b, o)
    63  	defer cleanupFunc()
    64  	uploader := db.NewPutter(ModePutUpload)
    65  	syncer := db.NewSetter(ModeSetSync)
    66  	requester := db.NewGetter(ModeGetRequest)
    67  	addrs := make([]storage.Address, count)
    68  	for i := 0; i < count; i++ {
    69  		chunk := generateFakeRandomChunk()
    70  		err := uploader.Put(chunk)
    71  		if err != nil {
    72  			b.Fatal(err)
    73  		}
    74  		addrs[i] = chunk.Address()
    75  	}
    76  	// set update gc test hook to signal when
    77  	// update gc goroutine is done by sending to
    78  	// testHookUpdateGCChan channel, which is
    79  	// used to wait for gc index updates to be
    80  	// included in the benchmark time
    81  	testHookUpdateGCChan := make(chan struct{})
    82  	defer setTestHookUpdateGC(func() {
    83  		testHookUpdateGCChan <- struct{}{}
    84  	})()
    85  	b.StartTimer()
    86  
    87  	for i := 0; i < count; i++ {
    88  		err := syncer.Set(addrs[i])
    89  		if err != nil {
    90  			b.Fatal(err)
    91  		}
    92  
    93  		_, err = requester.Get(addrs[i])
    94  		if err != nil {
    95  			b.Fatal(err)
    96  		}
    97  		// wait for update gc goroutine to be done
    98  		<-testHookUpdateGCChan
    99  	}
   100  }
   101  
   102  // BenchmarkUpload compares uploading speed for different
   103  // retrieval indexes and various number of chunks.
   104  //
   105  // Measurements on MacBook Pro (Retina, 15-inch, Mid 2014).
   106  //
   107  // go test -benchmem -run=none github.com/ethereum/go-ethereum/swarm/storage/localstore -bench BenchmarkUpload -v
   108  // goos: darwin
   109  // goarch: amd64
   110  // pkg: github.com/ethereum/go-ethereum/swarm/storage/localstore
   111  // BenchmarkUpload/1000-8         	      20       59437463 ns/op     25205193 B/op    23208 allocs/op
   112  // BenchmarkUpload/10000-8        	       2      580646362 ns/op    216532932 B/op	  248090 allocs/op
   113  // BenchmarkUpload/100000-8       	       1    22373390892 ns/op   2323055312 B/op	 3995903 allocs/op
   114  // PASS
   115  func BenchmarkUpload(b *testing.B) {
   116  	for _, count := range []int{
   117  		1000,
   118  		10000,
   119  		100000,
   120  	} {
   121  		b.Run(strconv.Itoa(count), func(b *testing.B) {
   122  			for n := 0; n < b.N; n++ {
   123  				benchmarkUpload(b, nil, count)
   124  			}
   125  		})
   126  	}
   127  }
   128  
   129  // benchmarkUpload is used in BenchmarkUpload
   130  // to do benchmarks with a specific number of chunks and different
   131  // database options.
   132  func benchmarkUpload(b *testing.B, o *Options, count int) {
   133  	b.StopTimer()
   134  	db, cleanupFunc := newTestDB(b, o)
   135  	defer cleanupFunc()
   136  	uploader := db.NewPutter(ModePutUpload)
   137  	chunks := make([]storage.Chunk, count)
   138  	for i := 0; i < count; i++ {
   139  		chunk := generateFakeRandomChunk()
   140  		chunks[i] = chunk
   141  	}
   142  	b.StartTimer()
   143  
   144  	for i := 0; i < count; i++ {
   145  		err := uploader.Put(chunks[i])
   146  		if err != nil {
   147  			b.Fatal(err)
   148  		}
   149  	}
   150  }