Commit 311809b0 authored by Daniel Martí's avatar Daniel Martí

add the first read-only benchmarks

BenchmarkReadBlocks uses carv2.OpenReader with its Roots and Next method.
From six runs on a laptop with a i5-8350U and benchstat:

	name          time/op
	ReadBlocks-8    633µs ± 2%

	name          speed
	ReadBlocks-8  824MB/s ± 2%

	name          alloc/op
	ReadBlocks-8   1.32MB ± 0%

	name          allocs/op
	ReadBlocks-8    13.5k ± 0%

OpenReadOnlyV1 uses blockstore.OpenReadOnly with its Get method.
The method is used on all blocks in a shuffled order,
to ensure that the index is working as intended.
The input file lacks an index, so we also generate that.

	name              time/op
	OpenReadOnlyV1-8    899µs ± 1%

	name              speed
	OpenReadOnlyV1-8  534MB/s ± 1%

	name              alloc/op
	OpenReadOnlyV1-8   1.52MB ± 0%

	name              allocs/op
	OpenReadOnlyV1-8    27.2k ± 0%

Both benchmarks use the "sample" v1/v2 CAR files, which weigh about half
a megabyte. It seems like a good size; a significantly larger CAR file
would make each benchmark iteration take tens or hundreds of
milliseconds, making it much slower to obtain many benchmark results,
since we want at least thousands of iterations to avoid noise.
parent d393a837
package car_test
import (
"io"
"os"
"testing"
carv2 "github.com/ipld/go-car/v2"
)
// Open a reader, get the roots, and iterate over all blocks.
// Essentially looking at the contents of any CARv1 or CARv2 file.
// Note that this also uses ReadVersion underneath.
func BenchmarkReadBlocks(b *testing.B) {
path := "testdata/sample-wrapped-v2.car"
info, err := os.Stat(path)
if err != nil {
b.Fatal(err)
}
b.SetBytes(info.Size())
b.ReportAllocs()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
cr, err := carv2.OpenReader(path)
if err != nil {
b.Fatal(err)
}
_, err = cr.Roots()
if err != nil {
b.Fatal(err)
}
for {
_, err := cr.Next()
if err == io.EOF {
break
}
if err != nil {
b.Fatal(err)
}
}
cr.Close()
}
})
}
package blockstore_test
import (
"io"
mathrand "math/rand"
"os"
"testing"
"github.com/ipfs/go-cid"
carv2 "github.com/ipld/go-car/v2"
"github.com/ipld/go-car/v2/blockstore"
)
// Open a read-only blockstore,
// and retrieve all blocks in a shuffled order.
// Note that this benchmark includes generating an index,
// since the input file is a CARv1.
func BenchmarkOpenReadOnlyV1(b *testing.B) {
path := "../testdata/sample-v1.car"
info, err := os.Stat(path)
if err != nil {
b.Fatal(err)
}
b.SetBytes(info.Size())
b.ReportAllocs()
var shuffledCIDs []cid.Cid
cr, err := carv2.OpenReader(path)
if err != nil {
b.Fatal(err)
}
for {
block, err := cr.Next()
if err == io.EOF {
break
}
if err != nil {
b.Fatal(err)
}
shuffledCIDs = append(shuffledCIDs, block.Cid())
}
cr.Close()
// The shuffling needs to be deterministic,
// for the sake of stable benchmark results.
// Any source number works as long as it's fixed.
rnd := mathrand.New(mathrand.NewSource(123456))
rnd.Shuffle(len(shuffledCIDs), func(i, j int) {
shuffledCIDs[i], shuffledCIDs[j] = shuffledCIDs[j], shuffledCIDs[i]
})
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
bs, err := blockstore.OpenReadOnly(path)
if err != nil {
b.Fatal(err)
}
for _, c := range shuffledCIDs {
_, err := bs.Get(c)
if err != nil {
b.Fatal(err)
}
}
bs.Close()
}
})
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment