From 2babd6404e072c4429511a061e8d7e5818679a37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Pedersen?= Date: Tue, 30 Jul 2024 10:26:10 +0200 Subject: [PATCH] identity: Use xxHash in hashstructure (note) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ``` name old time/op new time/op delta HashString/n28-10 133ns ± 9% 107ns ±10% -19.58% (p=0.029 n=4+4) HashString/n112-10 243ns ± 5% 121ns ± 4% -50.08% (p=0.029 n=4+4) HashString/n448-10 698ns ± 3% 174ns ± 5% -75.02% (p=0.029 n=4+4) HashString/n1792-10 2.58µs ± 4% 0.38µs ± 4% -85.11% (p=0.029 n=4+4) HashString/n7168-10 10.0µs ± 3% 1.3µs ± 4% -86.91% (p=0.029 n=4+4) name old alloc/op new alloc/op delta HashString/n28-10 80.0B ± 0% 72.0B ± 0% -10.00% (p=0.029 n=4+4) HashString/n112-10 160B ± 0% 152B ± 0% -5.00% (p=0.029 n=4+4) HashString/n448-10 496B ± 0% 488B ± 0% -1.61% (p=0.029 n=4+4) HashString/n1792-10 1.84kB ± 0% 1.83kB ± 0% -0.43% (p=0.029 n=4+4) HashString/n7168-10 8.24kB ± 0% 8.23kB ± 0% -0.06% (p=0.029 n=4+4) name old allocs/op new allocs/op delta HashString/n28-10 4.00 ± 0% 3.00 ± 0% -25.00% (p=0.029 n=4+4) HashString/n112-10 4.00 ± 0% 3.00 ± 0% -25.00% (p=0.029 n=4+4) HashString/n448-10 4.00 ± 0% 3.00 ± 0% -25.00% (p=0.029 n=4+4) HashString/n1792-10 4.00 ± 0% 3.00 ± 0% -25.00% (p=0.029 n=4+4) HashString/n7168-10 4.00 ± 0% 3.00 ± 0% -25.00% (p=0.029 n=4+4) ``` --- config/namespace_test.go | 2 +- hugolib/image_test.go | 4 ++-- identity/identityhash.go | 24 ++++++++++++++++++- identity/identityhash_test.go | 6 ++--- resources/internal/key_test.go | 2 +- .../resource_factories/create/remote_test.go | 12 +++++----- .../resource_transformers/js/options_test.go | 2 +- resources/resources_integration_test.go | 6 ++--- 8 files changed, 40 insertions(+), 18 deletions(-) diff --git a/config/namespace_test.go b/config/namespace_test.go index 3bbb28259..5eacdeac7 100644 --- a/config/namespace_test.go +++ b/config/namespace_test.go @@ -43,7 +43,7 @@ func TestNamespace(t *testing.T) { c.Assert(err, qt.IsNil) c.Assert(ns, qt.Not(qt.IsNil)) c.Assert(ns.SourceStructure, qt.DeepEquals, map[string]interface{}{"foo": "bar"}) - c.Assert(ns.SourceHash, qt.Equals, "5334326627423288605") + c.Assert(ns.SourceHash, qt.Equals, "1450430416588600409") c.Assert(ns.Config, qt.DeepEquals, &tstNsExt{Foo: "bar"}) c.Assert(ns.Signature(), qt.DeepEquals, []*tstNsExt(nil)) } diff --git a/hugolib/image_test.go b/hugolib/image_test.go index d58008512..637956b3b 100644 --- a/hugolib/image_test.go +++ b/hugolib/image_test.go @@ -82,12 +82,12 @@ SUNSET2: {{ $resized2.RelPermalink }}/{{ $resized2.Width }}/Lat: {{ $resized2.Ex // Check the file cache b.AssertImage(200, 200, "resources/_gen/images/bundle/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_200x200_resize_q75_box.jpg") - b.AssertFileContent("resources/_gen/images/bundle/sunset_9750822043026343402.json", + b.AssertFileContent("resources/_gen/images/bundle/sunset_2020904703097093419.json", "FocalLengthIn35mmFormat|uint16", "PENTAX") b.AssertImage(123, 234, "resources/_gen/images/images/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_123x234_resize_q75_box.jpg") - b.AssertFileContent("resources/_gen/images/images/sunset_9750822043026343402.json", + b.AssertFileContent("resources/_gen/images/images/sunset_2020904703097093419.json", "FocalLengthIn35mmFormat|uint16", "PENTAX") b.AssertNoDuplicateWrites() diff --git a/identity/identityhash.go b/identity/identityhash.go index 70371e567..7d3b83a0d 100644 --- a/identity/identityhash.go +++ b/identity/identityhash.go @@ -15,7 +15,9 @@ package identity import ( "strconv" + "sync" + "github.com/cespare/xxhash/v2" "github.com/mitchellh/hashstructure/v2" ) @@ -28,6 +30,23 @@ func HashString(vs ...any) string { return strconv.FormatUint(hash, 10) } +var hashOptsPool = sync.Pool{ + New: func() any { + return &hashstructure.HashOptions{ + Hasher: xxhash.New(), + } + }, +} + +func getHashOpts() *hashstructure.HashOptions { + return hashOptsPool.Get().(*hashstructure.HashOptions) +} + +func putHashOpts(opts *hashstructure.HashOptions) { + opts.Hasher.Reset() + hashOptsPool.Put(opts) +} + // HashUint64 returns a hash from the given elements. // It will panic if the hash cannot be calculated. // Note that this hash should be used primarily for identity, not for change detection as @@ -44,7 +63,10 @@ func HashUint64(vs ...any) uint64 { o = elements } - hash, err := hashstructure.Hash(o, hashstructure.FormatV2, nil) + hashOpts := getHashOpts() + defer putHashOpts(hashOpts) + + hash, err := hashstructure.Hash(o, hashstructure.FormatV2, hashOpts) if err != nil { panic(err) } diff --git a/identity/identityhash_test.go b/identity/identityhash_test.go index 52debe293..fee38c8fe 100644 --- a/identity/identityhash_test.go +++ b/identity/identityhash_test.go @@ -25,12 +25,12 @@ import ( func TestHashString(t *testing.T) { c := qt.New(t) - c.Assert(HashString("a", "b"), qt.Equals, "2712570657419664240") - c.Assert(HashString("ab"), qt.Equals, "590647783936702392") + c.Assert(HashString("a", "b"), qt.Equals, "3176555414984061461") + c.Assert(HashString("ab"), qt.Equals, "7347350983217793633") var vals []any = []any{"a", "b", tstKeyer{"c"}} - c.Assert(HashString(vals...), qt.Equals, "12599484872364427450") + c.Assert(HashString(vals...), qt.Equals, "4438730547989914315") c.Assert(vals[2], qt.Equals, tstKeyer{"c"}) } diff --git a/resources/internal/key_test.go b/resources/internal/key_test.go index b3f54eebd..fcad7d754 100644 --- a/resources/internal/key_test.go +++ b/resources/internal/key_test.go @@ -32,5 +32,5 @@ func TestResourceTransformationKey(t *testing.T) { key := NewResourceTransformationKey("testing", testStruct{Name: "test", V1: int64(10), V2: int32(20), V3: 30, V4: uint64(40)}) c := qt.New(t) - c.Assert(key.Value(), qt.Equals, "testing_5850874845946291698") + c.Assert(key.Value(), qt.Equals, "testing_4231238781487357822") } diff --git a/resources/resource_factories/create/remote_test.go b/resources/resource_factories/create/remote_test.go index 5284c4d19..293845107 100644 --- a/resources/resource_factories/create/remote_test.go +++ b/resources/resource_factories/create/remote_test.go @@ -127,10 +127,10 @@ func TestRemoteResourceKeys(t *testing.T) { c.Assert(got2, qt.Equals, expect2) } - check("foo", nil, "10276615683545312752", "10276615683545312752") - check("foo", map[string]any{"bar": "baz"}, "9898282343037894676", "9898282343037894676") - check("foo", map[string]any{"key": "1234", "bar": "baz"}, "14904296279238663669", "9898282343037894676") - check("foo", map[string]any{"key": "12345", "bar": "baz"}, "12191037851845371770", "9898282343037894676") - check("asdf", map[string]any{"key": "1234", "bar": "asdf"}, "14904296279238663669", "3005610248808565917") - check("asdf", map[string]any{"key": "12345", "bar": "asdf"}, "12191037851845371770", "3005610248808565917") + check("foo", nil, "7763396052142361238", "7763396052142361238") + check("foo", map[string]any{"bar": "baz"}, "5783339285578751849", "5783339285578751849") + check("foo", map[string]any{"key": "1234", "bar": "baz"}, "15578353952571222948", "5783339285578751849") + check("foo", map[string]any{"key": "12345", "bar": "baz"}, "14335752410685132726", "5783339285578751849") + check("asdf", map[string]any{"key": "1234", "bar": "asdf"}, "15578353952571222948", "15615023578599429261") + check("asdf", map[string]any{"key": "12345", "bar": "asdf"}, "14335752410685132726", "15615023578599429261") } diff --git a/resources/resource_transformers/js/options_test.go b/resources/resource_transformers/js/options_test.go index d2821c552..53aa9b6bb 100644 --- a/resources/resource_transformers/js/options_test.go +++ b/resources/resource_transformers/js/options_test.go @@ -44,7 +44,7 @@ func TestOptionKey(t *testing.T) { key := (&buildTransformation{optsm: opts}).Key() - c.Assert(key.Value(), qt.Equals, "jsbuild_9458638411414195026") + c.Assert(key.Value(), qt.Equals, "jsbuild_1533819657654811600") } func TestToBuildOptions(t *testing.T) { diff --git a/resources/resources_integration_test.go b/resources/resources_integration_test.go index df489c9e5..9c511332f 100644 --- a/resources/resources_integration_test.go +++ b/resources/resources_integration_test.go @@ -159,9 +159,9 @@ resize 2|RelPermalink: {{ $image.RelPermalink }}|MediaType: {{ $image.MediaType b := hugolib.Test(t, files) b.AssertFileContent("public/index.html", - "jpg|RelPermalink: /images/pixel_hu8aa3346827e49d756ff4e630147c42b5_70_filter_14347832029652749901.jpg|MediaType: image/jpeg|Width: 1|Height: 1|", - "resize 1|RelPermalink: /images/pixel_hu8aa3346827e49d756ff4e630147c42b5_70_filter_14038289290831899195.jpg|MediaType: image/jpeg|Width: 20|Height: 30|", - "resize 2|RelPermalink: /images/pixel_hu8aa3346827e49d756ff4e630147c42b5_70_filter_14038289290831899195.jpg|MediaType: image/jpeg|Width: 20|Height: 30|", + "jpg|RelPermalink: /images/pixel_hu8aa3346827e49d756ff4e630147c42b5_70_filter_1397118720664523257.jpg|MediaType: image/jpeg|Width: 1|Height: 1|", + "resize 1|RelPermalink: /images/pixel_hu8aa3346827e49d756ff4e630147c42b5_70_filter_3796633496882814163.jpg|MediaType: image/jpeg|Width: 20|Height: 30|", + "resize 2|RelPermalink: /images/pixel_hu8aa3346827e49d756ff4e630147c42b5_70_filter_3796633496882814163.jpg|MediaType: image/jpeg|Width: 20|Height: 30|", ) }