forked from TrueCloudLab/restic
These are faster to construct but slower to access. The allocation rate is halved, the peak memory usage almost halved compared to standard map. Benchmark results on linux/amd64, -benchtime=3s -count=20: name old time/op new time/op delta PackerManager-8 178ms ± 0% 178ms ± 0% ~ (p=0.231 n=20+20) DecodeIndex-8 4.54s ± 0% 4.30s ± 0% -5.20% (p=0.000 n=18+17) DecodeIndexParallel-8 4.54s ± 0% 4.30s ± 0% -5.22% (p=0.000 n=19+18) IndexHasUnknown-8 44.4ns ± 5% 50.5ns ±11% +13.82% (p=0.000 n=19+17) IndexHasKnown-8 48.3ns ± 0% 51.5ns ±12% +6.68% (p=0.001 n=16+20) IndexAlloc-8 758ms ± 1% 616ms ± 1% -18.69% (p=0.000 n=19+19) IndexAllocParallel-8 234ms ± 3% 204ms ± 2% -12.60% (p=0.000 n=20+18) MasterIndexLookupSingleIndex-8 122ns ± 0% 145ns ± 9% +18.44% (p=0.000 n=14+20) MasterIndexLookupMultipleIndex-8 369ns ± 2% 429ns ± 8% +16.27% (p=0.000 n=20+20) MasterIndexLookupSingleIndexUnknown-8 68.4ns ± 5% 74.9ns ±13% +9.47% (p=0.000 n=20+20) MasterIndexLookupMultipleIndexUnknown-8 315ns ± 3% 369ns ±11% +17.14% (p=0.000 n=20+20) MasterIndexLookupParallel/known,indices=5-8 743ns ± 1% 816ns ± 2% +9.87% (p=0.000 n=17+17) MasterIndexLookupParallel/unknown,indices=5-8 238ns ± 1% 260ns ± 2% +9.14% (p=0.000 n=19+20) MasterIndexLookupParallel/known,indices=10-8 1.01µs ± 3% 1.11µs ± 2% +9.79% (p=0.000 n=19+20) MasterIndexLookupParallel/unknown,indices=10-8 222ns ± 0% 269ns ± 2% +20.83% (p=0.000 n=16+20) MasterIndexLookupParallel/known,indices=20-8 1.06µs ± 2% 1.19µs ± 2% +12.95% (p=0.000 n=19+18) MasterIndexLookupParallel/unknown,indices=20-8 413ns ± 1% 530ns ± 1% +28.19% (p=0.000 n=18+20) SaveAndEncrypt-8 30.2ms ± 1% 30.4ms ± 0% +0.71% (p=0.000 n=19+19) LoadTree-8 540µs ± 1% 576µs ± 1% +6.73% (p=0.000 n=20+20) LoadBlob-8 5.64ms ± 0% 5.64ms ± 0% ~ (p=0.883 n=18+17) LoadAndDecrypt-8 5.93ms ± 0% 5.95ms ± 1% ~ (p=0.247 n=20+19) LoadIndex-8 25.1ms ± 0% 24.5ms ± 1% -2.54% (p=0.000 n=18+17) name old speed new speed delta PackerManager-8 296MB/s ± 0% 296MB/s ± 0% ~ (p=0.229 n=20+20) SaveAndEncrypt-8 139MB/s ± 1% 138MB/s ± 0% -0.71% (p=0.000 n=19+19) LoadBlob-8 177MB/s ± 0% 177MB/s ± 0% ~ (p=0.890 n=18+17) LoadAndDecrypt-8 169MB/s ± 0% 168MB/s ± 1% ~ (p=0.227 n=20+19) name old alloc/op new alloc/op delta PackerManager-8 91.8kB ± 0% 91.8kB ± 0% ~ (p=0.772 n=12+19) IndexAlloc-8 786MB ± 0% 400MB ± 0% -49.04% (p=0.000 n=20+18) IndexAllocParallel-8 786MB ± 0% 401MB ± 0% -49.04% (p=0.000 n=19+15) SaveAndEncrypt-8 21.0MB ± 0% 21.0MB ± 0% +0.00% (p=0.000 n=19+19) name old allocs/op new allocs/op delta PackerManager-8 1.41k ± 0% 1.41k ± 0% ~ (all equal) IndexAlloc-8 977k ± 0% 907k ± 0% -7.18% (p=0.000 n=20+20) IndexAllocParallel-8 977k ± 0% 907k ± 0% -7.17% (p=0.000 n=19+15) SaveAndEncrypt-8 73.0 ± 0% 73.0 ± 0% ~ (all equal)
121 lines
2.2 KiB
Go
121 lines
2.2 KiB
Go
package restic
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/restic/restic/internal/errors"
|
|
)
|
|
|
|
// Blob is one part of a file or a tree.
|
|
type Blob struct {
|
|
Type BlobType
|
|
Length uint
|
|
ID ID
|
|
Offset uint
|
|
}
|
|
|
|
func (b Blob) String() string {
|
|
return fmt.Sprintf("<Blob (%v) %v, offset %v, length %v>",
|
|
b.Type, b.ID.Str(), b.Offset, b.Length)
|
|
}
|
|
|
|
// PackedBlob is a blob stored within a file.
|
|
type PackedBlob struct {
|
|
Blob
|
|
PackID ID
|
|
}
|
|
|
|
// BlobHandle identifies a blob of a given type.
|
|
type BlobHandle struct {
|
|
ID ID
|
|
Type BlobType
|
|
}
|
|
|
|
func (h BlobHandle) String() string {
|
|
return fmt.Sprintf("<%s/%s>", h.Type, h.ID.Str())
|
|
}
|
|
|
|
// BlobType specifies what a blob stored in a pack is.
|
|
type BlobType uint8
|
|
|
|
// These are the blob types that can be stored in a pack.
|
|
const (
|
|
InvalidBlob BlobType = iota
|
|
DataBlob
|
|
TreeBlob
|
|
NumBlobTypes // Number of types. Must be last in this enumeration.
|
|
)
|
|
|
|
func (t BlobType) String() string {
|
|
switch t {
|
|
case DataBlob:
|
|
return "data"
|
|
case TreeBlob:
|
|
return "tree"
|
|
case InvalidBlob:
|
|
return "invalid"
|
|
}
|
|
|
|
return fmt.Sprintf("<BlobType %d>", t)
|
|
}
|
|
|
|
// MarshalJSON encodes the BlobType into JSON.
|
|
func (t BlobType) MarshalJSON() ([]byte, error) {
|
|
switch t {
|
|
case DataBlob:
|
|
return []byte(`"data"`), nil
|
|
case TreeBlob:
|
|
return []byte(`"tree"`), nil
|
|
}
|
|
|
|
return nil, errors.New("unknown blob type")
|
|
}
|
|
|
|
// UnmarshalJSON decodes the BlobType from JSON.
|
|
func (t *BlobType) UnmarshalJSON(buf []byte) error {
|
|
switch string(buf) {
|
|
case `"data"`:
|
|
*t = DataBlob
|
|
case `"tree"`:
|
|
*t = TreeBlob
|
|
default:
|
|
return errors.New("unknown blob type")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// BlobHandles is an ordered list of BlobHandles that implements sort.Interface.
|
|
type BlobHandles []BlobHandle
|
|
|
|
func (h BlobHandles) Len() int {
|
|
return len(h)
|
|
}
|
|
|
|
func (h BlobHandles) Less(i, j int) bool {
|
|
for k, b := range h[i].ID {
|
|
if b == h[j].ID[k] {
|
|
continue
|
|
}
|
|
|
|
if b < h[j].ID[k] {
|
|
return true
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
return h[i].Type < h[j].Type
|
|
}
|
|
|
|
func (h BlobHandles) Swap(i, j int) {
|
|
h[i], h[j] = h[j], h[i]
|
|
}
|
|
|
|
func (h BlobHandles) String() string {
|
|
elements := make([]string, 0, len(h))
|
|
for _, e := range h {
|
|
elements = append(elements, e.String())
|
|
}
|
|
return fmt.Sprintf("%v", elements)
|
|
}
|