0

Обновлены завендоренные зависимости

This commit is contained in:
eleksir
2025-10-12 14:37:48 +03:00
parent 9baa9ec5a2
commit 14778f40f6
12 changed files with 230 additions and 438 deletions

16
go.mod
View File

@@ -1,15 +1,13 @@
module aleesa-misc-go module aleesa-misc-go
go 1.24.0 go 1.25.1
require github.com/go-redis/redis/v8 v8.11.5
require ( require (
github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/go-redis/redis/v8 v8.11.5
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/hjson/hjson-go v3.3.0+incompatible
golang.org/x/sys v0.35.0 // indirect
) )
require github.com/hjson/hjson-go v3.3.0+incompatible require (
github.com/cespare/xxhash/v2 v2.1.2 // indirect
tool aleesa-misc-go github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
)

8
go.sum
View File

@@ -1,5 +1,5 @@
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
@@ -16,8 +16,8 @@ github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 h1:DzZ89McO9/gWPsQXS/FVKAlG02ZjaQ6AlZRBimEYOd0= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 h1:DzZ89McO9/gWPsQXS/FVKAlG02ZjaQ6AlZRBimEYOd0=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM=
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=

View File

@@ -3,7 +3,8 @@
[![Go Reference](https://pkg.go.dev/badge/github.com/cespare/xxhash/v2.svg)](https://pkg.go.dev/github.com/cespare/xxhash/v2) [![Go Reference](https://pkg.go.dev/badge/github.com/cespare/xxhash/v2.svg)](https://pkg.go.dev/github.com/cespare/xxhash/v2)
[![Test](https://github.com/cespare/xxhash/actions/workflows/test.yml/badge.svg)](https://github.com/cespare/xxhash/actions/workflows/test.yml) [![Test](https://github.com/cespare/xxhash/actions/workflows/test.yml/badge.svg)](https://github.com/cespare/xxhash/actions/workflows/test.yml)
xxhash is a Go implementation of the 64-bit [xxHash] algorithm, XXH64. This is a xxhash is a Go implementation of the 64-bit
[xxHash](http://cyan4973.github.io/xxHash/) algorithm, XXH64. This is a
high-quality hashing algorithm that is much faster than anything in the Go high-quality hashing algorithm that is much faster than anything in the Go
standard library. standard library.
@@ -24,11 +25,8 @@ func (*Digest) WriteString(string) (int, error)
func (*Digest) Sum64() uint64 func (*Digest) Sum64() uint64
``` ```
The package is written with optimized pure Go and also contains even faster This implementation provides a fast pure-Go implementation and an even faster
assembly implementations for amd64 and arm64. If desired, the `purego` build tag assembly implementation for amd64.
opts into using the Go code even on those architectures.
[xxHash]: http://cyan4973.github.io/xxHash/
## Compatibility ## Compatibility
@@ -47,20 +45,19 @@ I recommend using the latest release of Go.
Here are some quick benchmarks comparing the pure-Go and assembly Here are some quick benchmarks comparing the pure-Go and assembly
implementations of Sum64. implementations of Sum64.
| input size | purego | asm | | input size | purego | asm |
| ---------- | --------- | --------- | | --- | --- | --- |
| 4 B | 1.3 GB/s | 1.2 GB/s | | 5 B | 979.66 MB/s | 1291.17 MB/s |
| 16 B | 2.9 GB/s | 3.5 GB/s | | 100 B | 7475.26 MB/s | 7973.40 MB/s |
| 100 B | 6.9 GB/s | 8.1 GB/s | | 4 KB | 17573.46 MB/s | 17602.65 MB/s |
| 4 KB | 11.7 GB/s | 16.7 GB/s | | 10 MB | 17131.46 MB/s | 17142.16 MB/s |
| 10 MB | 12.0 GB/s | 17.3 GB/s |
These numbers were generated on Ubuntu 20.04 with an Intel Xeon Platinum 8252C These numbers were generated on Ubuntu 18.04 with an Intel i7-8700K CPU using
CPU using the following commands under Go 1.19.2: the following commands under Go 1.11.2:
``` ```
benchstat <(go test -tags purego -benchtime 500ms -count 15 -bench 'Sum64$') $ go test -tags purego -benchtime 10s -bench '/xxhash,direct,bytes'
benchstat <(go test -benchtime 500ms -count 15 -bench 'Sum64$') $ go test -benchtime 10s -bench '/xxhash,direct,bytes'
``` ```
## Projects using this package ## Projects using this package
@@ -70,5 +67,3 @@ benchstat <(go test -benchtime 500ms -count 15 -bench 'Sum64$')
- [VictoriaMetrics](https://github.com/VictoriaMetrics/VictoriaMetrics) - [VictoriaMetrics](https://github.com/VictoriaMetrics/VictoriaMetrics)
- [FreeCache](https://github.com/coocood/freecache) - [FreeCache](https://github.com/coocood/freecache)
- [FastCache](https://github.com/VictoriaMetrics/fastcache) - [FastCache](https://github.com/VictoriaMetrics/fastcache)
- [Ristretto](https://github.com/dgraph-io/ristretto)
- [Badger](https://github.com/dgraph-io/badger)

View File

@@ -1,10 +0,0 @@
#!/bin/bash
set -eu -o pipefail
# Small convenience script for running the tests with various combinations of
# arch/tags. This assumes we're running on amd64 and have qemu available.
go test ./...
go test -tags purego ./...
GOARCH=arm64 go test
GOARCH=arm64 go test -tags purego

View File

@@ -16,16 +16,21 @@ const (
prime5 uint64 = 2870177450012600261 prime5 uint64 = 2870177450012600261
) )
// Store the primes in an array as well. // NOTE(caleb): I'm using both consts and vars of the primes. Using consts where
// // possible in the Go code is worth a small (but measurable) performance boost
// The consts are used when possible in Go code to avoid MOVs but we need a // by avoiding some MOVQs. Vars are needed for the asm and also are useful for
// contiguous array for the assembly code. // convenience in the Go code in a few places where we need to intentionally
var primes = [...]uint64{prime1, prime2, prime3, prime4, prime5} // avoid constant arithmetic (e.g., v1 := prime1 + prime2 fails because the
// result overflows a uint64).
var (
prime1v = prime1
prime2v = prime2
prime3v = prime3
prime4v = prime4
prime5v = prime5
)
// Digest implements hash.Hash64. // Digest implements hash.Hash64.
//
// Note that a zero-valued Digest is not ready to receive writes.
// Call Reset or create a Digest using New before calling other methods.
type Digest struct { type Digest struct {
v1 uint64 v1 uint64
v2 uint64 v2 uint64
@@ -36,31 +41,19 @@ type Digest struct {
n int // how much of mem is used n int // how much of mem is used
} }
// New creates a new Digest with a zero seed. // New creates a new Digest that computes the 64-bit xxHash algorithm.
func New() *Digest { func New() *Digest {
return NewWithSeed(0)
}
// NewWithSeed creates a new Digest with the given seed.
func NewWithSeed(seed uint64) *Digest {
var d Digest var d Digest
d.ResetWithSeed(seed) d.Reset()
return &d return &d
} }
// Reset clears the Digest's state so that it can be reused. // Reset clears the Digest's state so that it can be reused.
// It uses a seed value of zero.
func (d *Digest) Reset() { func (d *Digest) Reset() {
d.ResetWithSeed(0) d.v1 = prime1v + prime2
} d.v2 = prime2
d.v3 = 0
// ResetWithSeed clears the Digest's state so that it can be reused. d.v4 = -prime1v
// It uses the given seed to initialize the state.
func (d *Digest) ResetWithSeed(seed uint64) {
d.v1 = seed + prime1 + prime2
d.v2 = seed + prime2
d.v3 = seed
d.v4 = seed - prime1
d.total = 0 d.total = 0
d.n = 0 d.n = 0
} }
@@ -76,23 +69,21 @@ func (d *Digest) Write(b []byte) (n int, err error) {
n = len(b) n = len(b)
d.total += uint64(n) d.total += uint64(n)
memleft := d.mem[d.n&(len(d.mem)-1):]
if d.n+n < 32 { if d.n+n < 32 {
// This new data doesn't even fill the current block. // This new data doesn't even fill the current block.
copy(memleft, b) copy(d.mem[d.n:], b)
d.n += n d.n += n
return return
} }
if d.n > 0 { if d.n > 0 {
// Finish off the partial block. // Finish off the partial block.
c := copy(memleft, b) copy(d.mem[d.n:], b)
d.v1 = round(d.v1, u64(d.mem[0:8])) d.v1 = round(d.v1, u64(d.mem[0:8]))
d.v2 = round(d.v2, u64(d.mem[8:16])) d.v2 = round(d.v2, u64(d.mem[8:16]))
d.v3 = round(d.v3, u64(d.mem[16:24])) d.v3 = round(d.v3, u64(d.mem[16:24]))
d.v4 = round(d.v4, u64(d.mem[24:32])) d.v4 = round(d.v4, u64(d.mem[24:32]))
b = b[c:] b = b[32-d.n:]
d.n = 0 d.n = 0
} }
@@ -142,20 +133,21 @@ func (d *Digest) Sum64() uint64 {
h += d.total h += d.total
b := d.mem[:d.n&(len(d.mem)-1)] i, end := 0, d.n
for ; len(b) >= 8; b = b[8:] { for ; i+8 <= end; i += 8 {
k1 := round(0, u64(b[:8])) k1 := round(0, u64(d.mem[i:i+8]))
h ^= k1 h ^= k1
h = rol27(h)*prime1 + prime4 h = rol27(h)*prime1 + prime4
} }
if len(b) >= 4 { if i+4 <= end {
h ^= uint64(u32(b[:4])) * prime1 h ^= uint64(u32(d.mem[i:i+4])) * prime1
h = rol23(h)*prime2 + prime3 h = rol23(h)*prime2 + prime3
b = b[4:] i += 4
} }
for ; len(b) > 0; b = b[1:] { for i < end {
h ^= uint64(b[0]) * prime5 h ^= uint64(d.mem[i]) * prime5
h = rol11(h) * prime1 h = rol11(h) * prime1
i++
} }
h ^= h >> 33 h ^= h >> 33

View File

@@ -1,12 +1,10 @@
//go:build (amd64 || arm64) && !appengine && gc && !purego
// +build amd64 arm64
// +build !appengine // +build !appengine
// +build gc // +build gc
// +build !purego // +build !purego
package xxhash package xxhash
// Sum64 computes the 64-bit xxHash digest of b with a zero seed. // Sum64 computes the 64-bit xxHash digest of b.
// //
//go:noescape //go:noescape
func Sum64(b []byte) uint64 func Sum64(b []byte) uint64

View File

@@ -1,209 +1,215 @@
//go:build !appengine && gc && !purego
// +build !appengine // +build !appengine
// +build gc // +build gc
// +build !purego // +build !purego
#include "textflag.h" #include "textflag.h"
// Registers: // Register allocation:
#define h AX // AX h
#define d AX // SI pointer to advance through b
#define p SI // pointer to advance through b // DX n
#define n DX // BX loop end
#define end BX // loop end // R8 v1, k1
#define v1 R8 // R9 v2
#define v2 R9 // R10 v3
#define v3 R10 // R11 v4
#define v4 R11 // R12 tmp
#define x R12 // R13 prime1v
#define prime1 R13 // R14 prime2v
#define prime2 R14 // DI prime4v
#define prime4 DI
#define round(acc, x) \ // round reads from and advances the buffer pointer in SI.
IMULQ prime2, x \ // It assumes that R13 has prime1v and R14 has prime2v.
ADDQ x, acc \ #define round(r) \
ROLQ $31, acc \ MOVQ (SI), R12 \
IMULQ prime1, acc ADDQ $8, SI \
IMULQ R14, R12 \
ADDQ R12, r \
ROLQ $31, r \
IMULQ R13, r
// round0 performs the operation x = round(0, x). // mergeRound applies a merge round on the two registers acc and val.
#define round0(x) \ // It assumes that R13 has prime1v, R14 has prime2v, and DI has prime4v.
IMULQ prime2, x \ #define mergeRound(acc, val) \
ROLQ $31, x \ IMULQ R14, val \
IMULQ prime1, x ROLQ $31, val \
IMULQ R13, val \
// mergeRound applies a merge round on the two registers acc and x. XORQ val, acc \
// It assumes that prime1, prime2, and prime4 have been loaded. IMULQ R13, acc \
#define mergeRound(acc, x) \ ADDQ DI, acc
round0(x) \
XORQ x, acc \
IMULQ prime1, acc \
ADDQ prime4, acc
// blockLoop processes as many 32-byte blocks as possible,
// updating v1, v2, v3, and v4. It assumes that there is at least one block
// to process.
#define blockLoop() \
loop: \
MOVQ +0(p), x \
round(v1, x) \
MOVQ +8(p), x \
round(v2, x) \
MOVQ +16(p), x \
round(v3, x) \
MOVQ +24(p), x \
round(v4, x) \
ADDQ $32, p \
CMPQ p, end \
JLE loop
// func Sum64(b []byte) uint64 // func Sum64(b []byte) uint64
TEXT ·Sum64(SB), NOSPLIT|NOFRAME, $0-32 TEXT ·Sum64(SB), NOSPLIT, $0-32
// Load fixed primes. // Load fixed primes.
MOVQ ·primes+0(SB), prime1 MOVQ ·prime1v(SB), R13
MOVQ ·primes+8(SB), prime2 MOVQ ·prime2v(SB), R14
MOVQ ·primes+24(SB), prime4 MOVQ ·prime4v(SB), DI
// Load slice. // Load slice.
MOVQ b_base+0(FP), p MOVQ b_base+0(FP), SI
MOVQ b_len+8(FP), n MOVQ b_len+8(FP), DX
LEAQ (p)(n*1), end LEAQ (SI)(DX*1), BX
// The first loop limit will be len(b)-32. // The first loop limit will be len(b)-32.
SUBQ $32, end SUBQ $32, BX
// Check whether we have at least one block. // Check whether we have at least one block.
CMPQ n, $32 CMPQ DX, $32
JLT noBlocks JLT noBlocks
// Set up initial state (v1, v2, v3, v4). // Set up initial state (v1, v2, v3, v4).
MOVQ prime1, v1 MOVQ R13, R8
ADDQ prime2, v1 ADDQ R14, R8
MOVQ prime2, v2 MOVQ R14, R9
XORQ v3, v3 XORQ R10, R10
XORQ v4, v4 XORQ R11, R11
SUBQ prime1, v4 SUBQ R13, R11
blockLoop() // Loop until SI > BX.
blockLoop:
round(R8)
round(R9)
round(R10)
round(R11)
MOVQ v1, h CMPQ SI, BX
ROLQ $1, h JLE blockLoop
MOVQ v2, x
ROLQ $7, x
ADDQ x, h
MOVQ v3, x
ROLQ $12, x
ADDQ x, h
MOVQ v4, x
ROLQ $18, x
ADDQ x, h
mergeRound(h, v1) MOVQ R8, AX
mergeRound(h, v2) ROLQ $1, AX
mergeRound(h, v3) MOVQ R9, R12
mergeRound(h, v4) ROLQ $7, R12
ADDQ R12, AX
MOVQ R10, R12
ROLQ $12, R12
ADDQ R12, AX
MOVQ R11, R12
ROLQ $18, R12
ADDQ R12, AX
mergeRound(AX, R8)
mergeRound(AX, R9)
mergeRound(AX, R10)
mergeRound(AX, R11)
JMP afterBlocks JMP afterBlocks
noBlocks: noBlocks:
MOVQ ·primes+32(SB), h MOVQ ·prime5v(SB), AX
afterBlocks: afterBlocks:
ADDQ n, h ADDQ DX, AX
ADDQ $24, end // Right now BX has len(b)-32, and we want to loop until SI > len(b)-8.
CMPQ p, end ADDQ $24, BX
JG try4
loop8: CMPQ SI, BX
MOVQ (p), x JG fourByte
ADDQ $8, p
round0(x)
XORQ x, h
ROLQ $27, h
IMULQ prime1, h
ADDQ prime4, h
CMPQ p, end wordLoop:
JLE loop8 // Calculate k1.
MOVQ (SI), R8
ADDQ $8, SI
IMULQ R14, R8
ROLQ $31, R8
IMULQ R13, R8
try4: XORQ R8, AX
ADDQ $4, end ROLQ $27, AX
CMPQ p, end IMULQ R13, AX
JG try1 ADDQ DI, AX
MOVL (p), x CMPQ SI, BX
ADDQ $4, p JLE wordLoop
IMULQ prime1, x
XORQ x, h
ROLQ $23, h fourByte:
IMULQ prime2, h ADDQ $4, BX
ADDQ ·primes+16(SB), h CMPQ SI, BX
JG singles
try1: MOVL (SI), R8
ADDQ $4, end ADDQ $4, SI
CMPQ p, end IMULQ R13, R8
XORQ R8, AX
ROLQ $23, AX
IMULQ R14, AX
ADDQ ·prime3v(SB), AX
singles:
ADDQ $4, BX
CMPQ SI, BX
JGE finalize JGE finalize
loop1: singlesLoop:
MOVBQZX (p), x MOVBQZX (SI), R12
ADDQ $1, p ADDQ $1, SI
IMULQ ·primes+32(SB), x IMULQ ·prime5v(SB), R12
XORQ x, h XORQ R12, AX
ROLQ $11, h
IMULQ prime1, h
CMPQ p, end ROLQ $11, AX
JL loop1 IMULQ R13, AX
CMPQ SI, BX
JL singlesLoop
finalize: finalize:
MOVQ h, x MOVQ AX, R12
SHRQ $33, x SHRQ $33, R12
XORQ x, h XORQ R12, AX
IMULQ prime2, h IMULQ R14, AX
MOVQ h, x MOVQ AX, R12
SHRQ $29, x SHRQ $29, R12
XORQ x, h XORQ R12, AX
IMULQ ·primes+16(SB), h IMULQ ·prime3v(SB), AX
MOVQ h, x MOVQ AX, R12
SHRQ $32, x SHRQ $32, R12
XORQ x, h XORQ R12, AX
MOVQ h, ret+24(FP) MOVQ AX, ret+24(FP)
RET RET
// writeBlocks uses the same registers as above except that it uses AX to store
// the d pointer.
// func writeBlocks(d *Digest, b []byte) int // func writeBlocks(d *Digest, b []byte) int
TEXT ·writeBlocks(SB), NOSPLIT|NOFRAME, $0-40 TEXT ·writeBlocks(SB), NOSPLIT, $0-40
// Load fixed primes needed for round. // Load fixed primes needed for round.
MOVQ ·primes+0(SB), prime1 MOVQ ·prime1v(SB), R13
MOVQ ·primes+8(SB), prime2 MOVQ ·prime2v(SB), R14
// Load slice. // Load slice.
MOVQ b_base+8(FP), p MOVQ b_base+8(FP), SI
MOVQ b_len+16(FP), n MOVQ b_len+16(FP), DX
LEAQ (p)(n*1), end LEAQ (SI)(DX*1), BX
SUBQ $32, end SUBQ $32, BX
// Load vN from d. // Load vN from d.
MOVQ s+0(FP), d MOVQ d+0(FP), AX
MOVQ 0(d), v1 MOVQ 0(AX), R8 // v1
MOVQ 8(d), v2 MOVQ 8(AX), R9 // v2
MOVQ 16(d), v3 MOVQ 16(AX), R10 // v3
MOVQ 24(d), v4 MOVQ 24(AX), R11 // v4
// We don't need to check the loop condition here; this function is // We don't need to check the loop condition here; this function is
// always called with at least one block of data to process. // always called with at least one block of data to process.
blockLoop() blockLoop:
round(R8)
round(R9)
round(R10)
round(R11)
CMPQ SI, BX
JLE blockLoop
// Copy vN back to d. // Copy vN back to d.
MOVQ v1, 0(d) MOVQ R8, 0(AX)
MOVQ v2, 8(d) MOVQ R9, 8(AX)
MOVQ v3, 16(d) MOVQ R10, 16(AX)
MOVQ v4, 24(d) MOVQ R11, 24(AX)
// The number of bytes written is p minus the old base pointer. // The number of bytes written is SI minus the old base pointer.
SUBQ b_base+8(FP), p SUBQ b_base+8(FP), SI
MOVQ p, ret+32(FP) MOVQ SI, ret+32(FP)
RET RET

View File

@@ -1,183 +0,0 @@
//go:build !appengine && gc && !purego
// +build !appengine
// +build gc
// +build !purego
#include "textflag.h"
// Registers:
#define digest R1
#define h R2 // return value
#define p R3 // input pointer
#define n R4 // input length
#define nblocks R5 // n / 32
#define prime1 R7
#define prime2 R8
#define prime3 R9
#define prime4 R10
#define prime5 R11
#define v1 R12
#define v2 R13
#define v3 R14
#define v4 R15
#define x1 R20
#define x2 R21
#define x3 R22
#define x4 R23
#define round(acc, x) \
MADD prime2, acc, x, acc \
ROR $64-31, acc \
MUL prime1, acc
// round0 performs the operation x = round(0, x).
#define round0(x) \
MUL prime2, x \
ROR $64-31, x \
MUL prime1, x
#define mergeRound(acc, x) \
round0(x) \
EOR x, acc \
MADD acc, prime4, prime1, acc
// blockLoop processes as many 32-byte blocks as possible,
// updating v1, v2, v3, and v4. It assumes that n >= 32.
#define blockLoop() \
LSR $5, n, nblocks \
PCALIGN $16 \
loop: \
LDP.P 16(p), (x1, x2) \
LDP.P 16(p), (x3, x4) \
round(v1, x1) \
round(v2, x2) \
round(v3, x3) \
round(v4, x4) \
SUB $1, nblocks \
CBNZ nblocks, loop
// func Sum64(b []byte) uint64
TEXT ·Sum64(SB), NOSPLIT|NOFRAME, $0-32
LDP b_base+0(FP), (p, n)
LDP ·primes+0(SB), (prime1, prime2)
LDP ·primes+16(SB), (prime3, prime4)
MOVD ·primes+32(SB), prime5
CMP $32, n
CSEL LT, prime5, ZR, h // if n < 32 { h = prime5 } else { h = 0 }
BLT afterLoop
ADD prime1, prime2, v1
MOVD prime2, v2
MOVD $0, v3
NEG prime1, v4
blockLoop()
ROR $64-1, v1, x1
ROR $64-7, v2, x2
ADD x1, x2
ROR $64-12, v3, x3
ROR $64-18, v4, x4
ADD x3, x4
ADD x2, x4, h
mergeRound(h, v1)
mergeRound(h, v2)
mergeRound(h, v3)
mergeRound(h, v4)
afterLoop:
ADD n, h
TBZ $4, n, try8
LDP.P 16(p), (x1, x2)
round0(x1)
// NOTE: here and below, sequencing the EOR after the ROR (using a
// rotated register) is worth a small but measurable speedup for small
// inputs.
ROR $64-27, h
EOR x1 @> 64-27, h, h
MADD h, prime4, prime1, h
round0(x2)
ROR $64-27, h
EOR x2 @> 64-27, h, h
MADD h, prime4, prime1, h
try8:
TBZ $3, n, try4
MOVD.P 8(p), x1
round0(x1)
ROR $64-27, h
EOR x1 @> 64-27, h, h
MADD h, prime4, prime1, h
try4:
TBZ $2, n, try2
MOVWU.P 4(p), x2
MUL prime1, x2
ROR $64-23, h
EOR x2 @> 64-23, h, h
MADD h, prime3, prime2, h
try2:
TBZ $1, n, try1
MOVHU.P 2(p), x3
AND $255, x3, x1
LSR $8, x3, x2
MUL prime5, x1
ROR $64-11, h
EOR x1 @> 64-11, h, h
MUL prime1, h
MUL prime5, x2
ROR $64-11, h
EOR x2 @> 64-11, h, h
MUL prime1, h
try1:
TBZ $0, n, finalize
MOVBU (p), x4
MUL prime5, x4
ROR $64-11, h
EOR x4 @> 64-11, h, h
MUL prime1, h
finalize:
EOR h >> 33, h
MUL prime2, h
EOR h >> 29, h
MUL prime3, h
EOR h >> 32, h
MOVD h, ret+24(FP)
RET
// func writeBlocks(d *Digest, b []byte) int
TEXT ·writeBlocks(SB), NOSPLIT|NOFRAME, $0-40
LDP ·primes+0(SB), (prime1, prime2)
// Load state. Assume v[1-4] are stored contiguously.
MOVD d+0(FP), digest
LDP 0(digest), (v1, v2)
LDP 16(digest), (v3, v4)
LDP b_base+8(FP), (p, n)
blockLoop()
// Store updated state.
STP (v1, v2), 0(digest)
STP (v3, v4), 16(digest)
BIC $31, n
MOVD n, ret+32(FP)
RET

View File

@@ -1,9 +1,8 @@
//go:build (!amd64 && !arm64) || appengine || !gc || purego // +build !amd64 appengine !gc purego
// +build !amd64,!arm64 appengine !gc purego
package xxhash package xxhash
// Sum64 computes the 64-bit xxHash digest of b with a zero seed. // Sum64 computes the 64-bit xxHash digest of b.
func Sum64(b []byte) uint64 { func Sum64(b []byte) uint64 {
// A simpler version would be // A simpler version would be
// d := New() // d := New()
@@ -15,10 +14,10 @@ func Sum64(b []byte) uint64 {
var h uint64 var h uint64
if n >= 32 { if n >= 32 {
v1 := primes[0] + prime2 v1 := prime1v + prime2
v2 := prime2 v2 := prime2
v3 := uint64(0) v3 := uint64(0)
v4 := -primes[0] v4 := -prime1v
for len(b) >= 32 { for len(b) >= 32 {
v1 = round(v1, u64(b[0:8:len(b)])) v1 = round(v1, u64(b[0:8:len(b)]))
v2 = round(v2, u64(b[8:16:len(b)])) v2 = round(v2, u64(b[8:16:len(b)]))
@@ -37,18 +36,19 @@ func Sum64(b []byte) uint64 {
h += uint64(n) h += uint64(n)
for ; len(b) >= 8; b = b[8:] { i, end := 0, len(b)
k1 := round(0, u64(b[:8])) for ; i+8 <= end; i += 8 {
k1 := round(0, u64(b[i:i+8:len(b)]))
h ^= k1 h ^= k1
h = rol27(h)*prime1 + prime4 h = rol27(h)*prime1 + prime4
} }
if len(b) >= 4 { if i+4 <= end {
h ^= uint64(u32(b[:4])) * prime1 h ^= uint64(u32(b[i:i+4:len(b)])) * prime1
h = rol23(h)*prime2 + prime3 h = rol23(h)*prime2 + prime3
b = b[4:] i += 4
} }
for ; len(b) > 0; b = b[1:] { for ; i < end; i++ {
h ^= uint64(b[0]) * prime5 h ^= uint64(b[i]) * prime5
h = rol11(h) * prime1 h = rol11(h) * prime1
} }

View File

@@ -1,11 +1,10 @@
//go:build appengine
// +build appengine // +build appengine
// This file contains the safe implementations of otherwise unsafe-using code. // This file contains the safe implementations of otherwise unsafe-using code.
package xxhash package xxhash
// Sum64String computes the 64-bit xxHash digest of s with a zero seed. // Sum64String computes the 64-bit xxHash digest of s.
func Sum64String(s string) uint64 { func Sum64String(s string) uint64 {
return Sum64([]byte(s)) return Sum64([]byte(s))
} }

View File

@@ -1,4 +1,3 @@
//go:build !appengine
// +build !appengine // +build !appengine
// This file encapsulates usage of unsafe. // This file encapsulates usage of unsafe.
@@ -12,7 +11,7 @@ import (
// In the future it's possible that compiler optimizations will make these // In the future it's possible that compiler optimizations will make these
// XxxString functions unnecessary by realizing that calls such as // XxxString functions unnecessary by realizing that calls such as
// Sum64([]byte(s)) don't need to copy s. See https://go.dev/issue/2205. // Sum64([]byte(s)) don't need to copy s. See https://golang.org/issue/2205.
// If that happens, even if we keep these functions they can be replaced with // If that happens, even if we keep these functions they can be replaced with
// the trivial safe code. // the trivial safe code.
@@ -33,7 +32,7 @@ import (
// //
// See https://github.com/golang/go/issues/42739 for discussion. // See https://github.com/golang/go/issues/42739 for discussion.
// Sum64String computes the 64-bit xxHash digest of s with a zero seed. // Sum64String computes the 64-bit xxHash digest of s.
// It may be faster than Sum64([]byte(s)) by avoiding a copy. // It may be faster than Sum64([]byte(s)) by avoiding a copy.
func Sum64String(s string) uint64 { func Sum64String(s string) uint64 {
b := *(*[]byte)(unsafe.Pointer(&sliceHeader{s, len(s)})) b := *(*[]byte)(unsafe.Pointer(&sliceHeader{s, len(s)}))

4
vendor/modules.txt vendored
View File

@@ -1,4 +1,4 @@
# github.com/cespare/xxhash/v2 v2.3.0 # github.com/cespare/xxhash/v2 v2.1.2
## explicit; go 1.11 ## explicit; go 1.11
github.com/cespare/xxhash/v2 github.com/cespare/xxhash/v2
# github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f # github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f
@@ -17,5 +17,3 @@ github.com/go-redis/redis/v8/internal/util
# github.com/hjson/hjson-go v3.3.0+incompatible # github.com/hjson/hjson-go v3.3.0+incompatible
## explicit ## explicit
github.com/hjson/hjson-go github.com/hjson/hjson-go
# golang.org/x/sys v0.35.0
## explicit; go 1.23.0