mirror of
https://github.com/gohugoio/hugo.git
synced 2026-08-24 15:28:54 +00:00
common/hreflect: Speed up IsTrutfulValue
By caching the calculation of whether a type implements `IsZero`: ``` IsTruthFulVAlue-10 467.95n ± ∞ ¹ 79.13n ± ∞ ¹ -83.09% (p=0.029 n=4) ```
This commit is contained in:
@@ -86,6 +86,18 @@ func IsSlice(v any) bool {
|
||||
|
||||
var zeroType = reflect.TypeOf((*types.Zeroer)(nil)).Elem()
|
||||
|
||||
var isZeroCache sync.Map
|
||||
|
||||
func implementsIsZero(tp reflect.Type) bool {
|
||||
v, ok := isZeroCache.Load(tp)
|
||||
if ok {
|
||||
return v.(bool)
|
||||
}
|
||||
implements := tp.Implements(zeroType)
|
||||
isZeroCache.Store(tp, implements)
|
||||
return implements
|
||||
}
|
||||
|
||||
// IsTruthfulValue returns whether the given value has a meaningful truth value.
|
||||
// This is based on template.IsTrue in Go's stdlib, but also considers
|
||||
// IsZero and any interface value will be unwrapped before it's considered
|
||||
@@ -105,7 +117,7 @@ func IsTruthfulValue(val reflect.Value) (truth bool) {
|
||||
return
|
||||
}
|
||||
|
||||
if val.Type().Implements(zeroType) {
|
||||
if implementsIsZero(val.Type()) {
|
||||
return !val.Interface().(types.Zeroer).IsZero()
|
||||
}
|
||||
|
||||
|
||||
@@ -106,14 +106,26 @@ func BenchmarkIsContextType(b *testing.B) {
|
||||
})
|
||||
}
|
||||
|
||||
func BenchmarkIsTruthFul(b *testing.B) {
|
||||
v := reflect.ValueOf("Hugo")
|
||||
func BenchmarkIsTruthFulValue(b *testing.B) {
|
||||
var (
|
||||
stringHugo = reflect.ValueOf("Hugo")
|
||||
stringEmpty = reflect.ValueOf("")
|
||||
zero = reflect.ValueOf(time.Time{})
|
||||
timeNow = reflect.ValueOf(time.Now())
|
||||
boolTrue = reflect.ValueOf(true)
|
||||
boolFalse = reflect.ValueOf(false)
|
||||
nilPointer = reflect.ValueOf((*zeroStruct)(nil))
|
||||
)
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
if !IsTruthfulValue(v) {
|
||||
b.Fatal("not truthful")
|
||||
}
|
||||
IsTruthfulValue(stringHugo)
|
||||
IsTruthfulValue(stringEmpty)
|
||||
IsTruthfulValue(zero)
|
||||
IsTruthfulValue(timeNow)
|
||||
IsTruthfulValue(boolTrue)
|
||||
IsTruthfulValue(boolFalse)
|
||||
IsTruthfulValue(nilPointer)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user