mirror of
https://github.com/kovidgoyal/kitty
synced 2026-07-19 15:04:50 +02:00
Micro-optimization: store strong hash as a uint64 instead of a byte slice
This commit is contained in:
@@ -9,7 +9,6 @@
|
||||
package rsync
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"hash"
|
||||
@@ -123,25 +122,25 @@ func (self *Operation) Unserialize(data []byte) (n int, err error) {
|
||||
// Signature hash item generated from target.
|
||||
type BlockHash struct {
|
||||
Index uint64
|
||||
StrongHash []byte
|
||||
WeakHash uint32
|
||||
StrongHash uint64
|
||||
}
|
||||
|
||||
func (self BlockHash) Serialize() []byte {
|
||||
ans := make([]byte, 12+len(self.StrongHash))
|
||||
ans := make([]byte, 20)
|
||||
bin.PutUint64(ans, self.Index)
|
||||
bin.PutUint32(ans[8:], self.WeakHash)
|
||||
copy(ans[12:], self.StrongHash)
|
||||
bin.PutUint64(ans[12:], self.StrongHash)
|
||||
return ans
|
||||
}
|
||||
|
||||
func (self *BlockHash) Unserialize(data []byte, hash_size int) (err error) {
|
||||
if len(data) < 12+hash_size {
|
||||
return fmt.Errorf("record too small to be a BlockHash: %d < %d", len(data), 12+hash_size)
|
||||
func (self *BlockHash) Unserialize(data []byte) (err error) {
|
||||
if len(data) < 20 {
|
||||
return fmt.Errorf("record too small to be a BlockHash: %d < %d", len(data), 20)
|
||||
}
|
||||
self.Index = bin.Uint64(data)
|
||||
self.WeakHash = bin.Uint32(data[8:])
|
||||
self.StrongHash = data[12 : 12+hash_size]
|
||||
self.StrongHash = bin.Uint64(data[12:])
|
||||
return
|
||||
}
|
||||
|
||||
@@ -156,12 +155,12 @@ type rsync struct {
|
||||
BlockSize int
|
||||
|
||||
// This must be non-nil before using any functions
|
||||
hasher hash.Hash
|
||||
hasher_constructor func() hash.Hash
|
||||
hasher hash.Hash64
|
||||
hasher_constructor func() hash.Hash64
|
||||
buffer []byte
|
||||
}
|
||||
|
||||
func (r *rsync) SetHasher(c func() hash.Hash) {
|
||||
func (r *rsync) SetHasher(c func() hash.Hash64) {
|
||||
r.hasher_constructor = c
|
||||
r.hasher = c()
|
||||
}
|
||||
@@ -358,8 +357,7 @@ type diff struct {
|
||||
// A single β hash may correlate with many unique hashes.
|
||||
hash_lookup map[uint32][]BlockHash
|
||||
source io.Reader
|
||||
hasher hash.Hash
|
||||
hash_buf []byte
|
||||
hasher hash.Hash64
|
||||
|
||||
window, data struct{ pos, sz int }
|
||||
block_size int
|
||||
@@ -379,10 +377,10 @@ func (self *diff) Next() (op *Operation, err error) {
|
||||
return self.ready_ops.pop_front(), nil
|
||||
}
|
||||
|
||||
func (self *diff) hash(b []byte) []byte {
|
||||
func (self *diff) hash(b []byte) uint64 {
|
||||
self.hasher.Reset()
|
||||
self.hasher.Write(b)
|
||||
return self.hasher.Sum(self.hash_buf[:0])
|
||||
return self.hasher.Sum64()
|
||||
}
|
||||
|
||||
// Combine OpBlock into OpBlockRange. To do this store the previous
|
||||
@@ -531,7 +529,6 @@ func (r *rsync) CreateDiff(source io.Reader, signature []BlockHash) func() (*Ope
|
||||
block_size: r.BlockSize, buffer: make([]byte, 0, (r.BlockSize * 8)),
|
||||
hash_lookup: make(map[uint32][]BlockHash, len(signature)),
|
||||
source: source, hasher: r.hasher_constructor(),
|
||||
hash_buf: make([]byte, 0, r.hasher.Size()),
|
||||
}
|
||||
for _, h := range signature {
|
||||
key := h.WeakHash
|
||||
@@ -556,10 +553,10 @@ func (r *rsync) CreateDelta(source io.Reader, signature []BlockHash, ops Operati
|
||||
}
|
||||
|
||||
// Use a more unique way to identify a set of bytes.
|
||||
func (r *rsync) hash(v []byte) []byte {
|
||||
func (r *rsync) hash(v []byte) uint64 {
|
||||
r.hasher.Reset()
|
||||
r.hasher.Write(v)
|
||||
return r.hasher.Sum(nil)
|
||||
return r.hasher.Sum64()
|
||||
}
|
||||
|
||||
func (r *rsync) HashSize() int { return r.hasher.Size() }
|
||||
@@ -567,12 +564,9 @@ func (r *rsync) HashBlockSize() int { return r.hasher.BlockSize() }
|
||||
func (r *rsync) HasHasher() bool { return r.hasher != nil }
|
||||
|
||||
// Searches for a given strong hash among all strong hashes in this bucket.
|
||||
func find_hash(hh []BlockHash, hv []byte) (uint64, bool) {
|
||||
if len(hv) == 0 {
|
||||
return 0, false
|
||||
}
|
||||
func find_hash(hh []BlockHash, hv uint64) (uint64, bool) {
|
||||
for _, block := range hh {
|
||||
if bytes.Equal(block.StrongHash, hv) {
|
||||
if block.StrongHash == hv {
|
||||
return block.Index, true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ func (self *Api) read_signature_header(data []byte) (consumed int, err error) {
|
||||
switch strong_hash := StrongHashType(bin.Uint16(data[4:])); strong_hash {
|
||||
case XXH3:
|
||||
self.Strong_hash_type = strong_hash
|
||||
self.rsync.SetHasher(func() hash.Hash { return xxh3.New() })
|
||||
self.rsync.SetHasher(func() hash.Hash64 { return xxh3.New() })
|
||||
default:
|
||||
return consumed, fmt.Errorf("Invalid strong_hash in signature header: %d", strong_hash)
|
||||
}
|
||||
@@ -84,11 +84,10 @@ func (self *Api) read_signature_header(data []byte) (consumed int, err error) {
|
||||
}
|
||||
|
||||
func (self *Api) read_signature_blocks(data []byte) (consumed int) {
|
||||
hash_size := self.rsync.HashSize()
|
||||
block_hash_size := hash_size + 12
|
||||
block_hash_size := self.rsync.HashSize() + 12
|
||||
for ; len(data) >= block_hash_size; data = data[block_hash_size:] {
|
||||
bl := BlockHash{}
|
||||
bl.Unserialize(data[:block_hash_size], hash_size)
|
||||
bl.Unserialize(data[:block_hash_size])
|
||||
self.signature = append(self.signature, bl)
|
||||
consumed += block_hash_size
|
||||
}
|
||||
@@ -241,7 +240,7 @@ func NewPatcher(expected_input_size int64) (ans *Patcher) {
|
||||
}
|
||||
ans = &Patcher{}
|
||||
ans.rsync.BlockSize = utils.Min(bs, MaxBlockSize)
|
||||
ans.rsync.SetHasher(func() hash.Hash { return xxh3.New() })
|
||||
ans.rsync.SetHasher(func() hash.Hash64 { return xxh3.New() })
|
||||
|
||||
if ans.rsync.HashBlockSize() > 0 && ans.rsync.HashBlockSize() < ans.rsync.BlockSize {
|
||||
ans.rsync.BlockSize = (ans.rsync.BlockSize / ans.rsync.HashBlockSize()) * ans.rsync.HashBlockSize()
|
||||
|
||||
Reference in New Issue
Block a user