mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-01 07:35:40 +00:00
text: use a simpler hash
The hash calculation is a significant bottleneck in caching, replace it with a simpler "add; multiply by a prime" approach. LabelStatic/1000runes-RTL-arabic-32 89.75µ ± 2% 63.58µ ± 1% -29.16% (p=0.002 n=6) Signed-off-by: Egon Elbre <egonelbre@gmail.com>
This commit is contained in:
+19
-20
@@ -3,9 +3,8 @@
|
|||||||
package text
|
package text
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
|
||||||
"hash/maphash"
|
|
||||||
"image"
|
"image"
|
||||||
|
"sync/atomic"
|
||||||
|
|
||||||
giofont "gioui.org/font"
|
giofont "gioui.org/font"
|
||||||
"gioui.org/io/system"
|
"gioui.org/io/system"
|
||||||
@@ -88,32 +87,32 @@ type glyphValue[V any] struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type glyphLRU[V any] struct {
|
type glyphLRU[V any] struct {
|
||||||
seed maphash.Seed
|
seed uint64
|
||||||
cache lru[uint64, glyphValue[V]]
|
cache lru[uint64, glyphValue[V]]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var seed uint32
|
||||||
|
|
||||||
// hashGlyphs computes a hash key based on the ID and X offset of
|
// hashGlyphs computes a hash key based on the ID and X offset of
|
||||||
// every glyph in the slice.
|
// every glyph in the slice.
|
||||||
func (c *glyphLRU[V]) hashGlyphs(gs []Glyph) uint64 {
|
func (c *glyphLRU[V]) hashGlyphs(gs []Glyph) uint64 {
|
||||||
if c.seed == (maphash.Seed{}) {
|
if c.seed == 0 {
|
||||||
c.seed = maphash.MakeSeed()
|
c.seed = uint64(atomic.AddUint32(&seed, 3900798947))
|
||||||
}
|
}
|
||||||
var h maphash.Hash
|
if len(gs) == 0 {
|
||||||
h.SetSeed(c.seed)
|
return 0
|
||||||
var b [8]byte
|
|
||||||
firstX := fixed.Int26_6(0)
|
|
||||||
for i, g := range gs {
|
|
||||||
if i == 0 {
|
|
||||||
firstX = g.X
|
|
||||||
}
|
|
||||||
// Cache glyph X offsets relative to the first glyph.
|
|
||||||
binary.LittleEndian.PutUint32(b[:4], uint32(g.X-firstX))
|
|
||||||
h.Write(b[:4])
|
|
||||||
binary.LittleEndian.PutUint64(b[:], uint64(g.ID))
|
|
||||||
h.Write(b[:])
|
|
||||||
}
|
}
|
||||||
sum := h.Sum64()
|
|
||||||
return sum
|
h := c.seed
|
||||||
|
firstX := gs[0].X
|
||||||
|
for _, g := range gs {
|
||||||
|
h += uint64(g.X - firstX)
|
||||||
|
h *= 6585573582091643
|
||||||
|
h += uint64(g.ID)
|
||||||
|
h *= 3650802748644053
|
||||||
|
}
|
||||||
|
|
||||||
|
return h
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *glyphLRU[V]) Get(key uint64, gs []Glyph) (V, bool) {
|
func (c *glyphLRU[V]) Get(key uint64, gs []Glyph) (V, bool) {
|
||||||
|
|||||||
Reference in New Issue
Block a user