Skip to content

Conversation

@bep
Copy link
Member

@bep bep commented Oct 27, 2025

                                        │ master.bench │    fix-reflectmethodcache.bench     │
                                        │    sec/op    │    sec/op     vs base               │
WhereSliceOfStructPointersWithMethod-10   592.2µ ± ∞ ¹   390.1µ ± ∞ ¹  -34.14% (p=0.029 n=4)
¹ need >= 6 samples for confidence interval at level 0.95

                                        │  master.bench  │     fix-reflectmethodcache.bench     │
                                        │      B/op      │     B/op       vs base               │
WhereSliceOfStructPointersWithMethod-10   205.14Ki ± ∞ ¹   64.52Ki ± ∞ ¹  -68.55% (p=0.029 n=4)
¹ need >= 6 samples for confidence interval at level 0.95

                                        │ master.bench │    fix-reflectmethodcache.bench     │
                                        │  allocs/op   │  allocs/op    vs base               │
WhereSliceOfStructPointersWithMethod-10   9.003k ± ∞ ¹   4.503k ± ∞ ¹  -49.98% (p=0.029 n=4)
…others

We already cached the method index on the struct, but caching the resolved `reflect.Method` itself saves us from having to do another lookup on each call, which is escpeciall import in the hot path used by collections.Where and otherrs:

```bash
                                        │ master.bench │    fix-reflectmethodcache.bench     │
                                        │    sec/op    │    sec/op     vs base               │
WhereSliceOfStructPointersWithMethod-10   592.2µ ± ∞ ¹   390.1µ ± ∞ ¹  -34.14% (p=0.029 n=4)
¹ need >= 6 samples for confidence interval at level 0.95

                                        │  master.bench  │     fix-reflectmethodcache.bench     │
                                        │      B/op      │     B/op       vs base               │
WhereSliceOfStructPointersWithMethod-10   205.14Ki ± ∞ ¹   64.52Ki ± ∞ ¹  -68.55% (p=0.029 n=4)
¹ need >= 6 samples for confidence interval at level 0.95

                                        │ master.bench │    fix-reflectmethodcache.bench     │
                                        │  allocs/op   │  allocs/op    vs base               │
WhereSliceOfStructPointersWithMethod-10   9.003k ± ∞ ¹   4.503k ± ∞ ¹  -49.98% (p=0.029 n=4)
````
@bep bep force-pushed the fix/reflectmethodcache branch from 7c4cbfd to a554c38 Compare October 27, 2025 12:43
@bep bep requested a review from Copilot October 27, 2025 14:20
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR optimizes reflection-based method lookups in the collections package by introducing a new caching mechanism. The change yields significant performance improvements: ~34% reduction in execution time, ~69% reduction in memory allocations, and ~50% reduction in allocation count.

  • Introduced GetMethodByNameForType function that caches reflect.Method directly instead of just the method index
  • Split the method cache into two separate caches: methodIndexCache and methodCache to handle different use cases
  • Refactored evaluateSubElem to use the new cached method lookup, eliminating redundant method lookups

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
common/hreflect/helpers.go Added GetMethodByNameForType and IndirectElem functions, split method cache into two separate caches
common/hreflect/helpers_test.go Added benchmark test for the new GetMethodByNameForType function
tpl/collections/where.go Refactored to use GetMethodByNameForType instead of GetMethodIndexByName + Method(index) pattern
langs/i18n/i18n.go Simplified nil checking by using the new IndirectElem helper function

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@bep bep merged commit e9bda21 into gohugoio:master Oct 27, 2025
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

1 participant