Replace the MD5 hashing of images with xxHash

Note that we only use this for change detection.

The previous implementation invoked `MD5FromReaderFast` that created a MD5 has from 8 64 bytes chunks in the file, which is obviously very fast. The new implementation creates the hash from the entire file and ... seems to be even more effective:

```
name          old time/op    new time/op    delta
HashImage-10    9.45µs ±21%   10.89µs ± 1%     ~     (p=0.343 n=4+4)

name          old alloc/op   new alloc/op   delta
HashImage-10      144B ± 0%        8B ± 0%  -94.44%  (p=0.029 n=4+4)

name          old allocs/op  new allocs/op  delta
HashImage-10      4.00 ± 0%      1.00 ± 0%  -75.00%  (p=0.029 n=4+4)
```
This commit is contained in:
Bjørn Erik Pedersen 2024-07-30 12:52:54 +02:00
parent 8b5d796989
commit d5eda13cb2
7 changed files with 180 additions and 29 deletions

View file

@ -26,6 +26,7 @@ import (
"github.com/gohugoio/hugo/identity"
"github.com/gohugoio/hugo/resources/internal"
"github.com/gohugoio/hugo/common/hashing"
"github.com/gohugoio/hugo/common/herrors"
"github.com/gohugoio/hugo/common/paths"
@ -307,7 +308,7 @@ type fileInfo interface {
}
type hashProvider interface {
hash() string
hash() uint64
}
var _ resource.StaleInfo = (*StaleValue[any])(nil)
@ -403,7 +404,7 @@ func (l *genericResource) size() int64 {
return l.h.size
}
func (l *genericResource) hash() string {
func (l *genericResource) hash() uint64 {
if err := l.h.init(l); err != nil {
panic(err)
}
@ -628,7 +629,7 @@ type targetPather interface {
}
type resourceHash struct {
value string
value uint64
size int64
initOnce sync.Once
}
@ -636,7 +637,7 @@ type resourceHash struct {
func (r *resourceHash) init(l hugio.ReadSeekCloserProvider) error {
var initErr error
r.initOnce.Do(func() {
var hash string
var hash uint64
var size int64
f, err := l.ReadSeekCloser()
if err != nil {
@ -656,6 +657,6 @@ func (r *resourceHash) init(l hugio.ReadSeekCloserProvider) error {
return initErr
}
func hashImage(r io.ReadSeeker) (string, int64, error) {
return helpers.MD5FromReaderFast(r)
func hashImage(r io.ReadSeeker) (uint64, int64, error) {
return hashing.XXHashFromReader(r)
}