Skip to content

Commit

Permalink
metrics: Fix --templateMetricsHints
Browse files Browse the repository at this point in the history
Also improve non-string comparisons.

Fixes #7048
  • Loading branch information
bep committed Mar 12, 2020
1 parent 18cb21f commit 5eadc4c
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 10 deletions.
42 changes: 41 additions & 1 deletion common/types/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@

package types

import "github.com/spf13/cast"
import (
"html/template"

"github.com/spf13/cast"
)

// ToStringSlicePreserveString converts v to a string slice.
// If v is a string, it will be wrapped in a string slice.
Expand All @@ -26,3 +30,39 @@ func ToStringSlicePreserveString(v interface{}) []string {
}
return cast.ToStringSlice(v)
}

// TypeToString converts v to a string if it's a valid string type.
// Note that this will not try to convert numeric values etc.,
// use ToString for that.
func TypeToString(v interface{}) (string, bool) {
switch s := v.(type) {
case string:
return s, true
case template.HTML:
return string(s), true
case template.CSS:
return string(s), true
case template.HTMLAttr:
return string(s), true
case template.JS:
return string(s), true
case template.JSStr:
return string(s), true
case template.URL:
return string(s), true
case template.Srcset:
return string(s), true
}

return "", false
}

// ToString converts v to a string.
func ToString(v interface{}) string {
if s, ok := TypeToString(v); ok {
return s
}

return cast.ToString(v)

}
42 changes: 33 additions & 9 deletions metrics/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@
package metrics

import (
"reflect"

"github.com/gohugoio/hugo/helpers"

"github.com/gohugoio/hugo/common/types"

"fmt"
"io"
"math"
Expand All @@ -25,8 +31,6 @@ import (
"time"

"github.com/gohugoio/hugo/compare"

"github.com/gohugoio/hugo/common/hreflect"
)

// The Provider interface defines an interface for measuring metrics.
Expand All @@ -51,15 +55,17 @@ type diff struct {
simSum int
}

var counter = 0

func (d *diff) add(v interface{}) *diff {
if !hreflect.IsTruthful(v) {
if types.IsNil(d.baseline) {
d.baseline = v
d.count = 1
d.simSum = 100 // If we get only one it is very cache friendly.
return d
}

d.simSum += howSimilar(v, d.baseline)
adder := howSimilar(v, d.baseline)
d.simSum += adder
d.count++

return d
Expand Down Expand Up @@ -113,6 +119,7 @@ func (s *Store) TrackValue(key string, value interface{}) {
}

d.add(value)

s.diffmu.Unlock()
}

Expand All @@ -135,6 +142,7 @@ func (s *Store) WriteMetrics(w io.Writer) {
var max time.Duration

diff, found := s.diffs[k]

cacheFactor := 0
if found {
cacheFactor = int(math.Floor(float64(diff.simSum) / float64(diff.count)))
Expand Down Expand Up @@ -196,11 +204,19 @@ func (b bySum) Less(i, j int) bool { return b[i].sum > b[j].sum }
// howSimilar is a naive diff implementation that returns
// a number between 0-100 indicating how similar a and b are.
func howSimilar(a, b interface{}) int {
// TODO(bep) object equality fast path, but remember that
// we can get anytning in here.
t1, t2 := reflect.TypeOf(a), reflect.TypeOf(b)
if t1 != t2 {
return 0
}

as, ok1 := a.(string)
bs, ok2 := b.(string)
if t1.Comparable() && t2.Comparable() {
if a == b {
return 100
}
}

as, ok1 := types.TypeToString(a)
bs, ok2 := types.TypeToString(b)

if ok1 && ok2 {
return howSimilarStrings(as, bs)
Expand All @@ -222,13 +238,21 @@ func howSimilar(a, b interface{}) int {
return 90
}

h1, h2 := helpers.HashString(a), helpers.HashString(b)
if h1 == h2 {
return 100
}
return 0

}

// howSimilar is a naive diff implementation that returns
// a number between 0-100 indicating how similar a and b are.
// 100 is when all words in a also exists in b.
func howSimilarStrings(a, b string) int {
if a == b {
return 100
}

// Give some weight to the word positions.
const partitionSize = 4
Expand Down
11 changes: 11 additions & 0 deletions metrics/metrics_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
package metrics

import (
"html/template"
"strings"
"testing"

Expand All @@ -39,13 +40,23 @@ func TestSimilarPercentage(t *testing.T) {
c.Assert(howSimilar("The Hugo", "The Hugo Rules"), qt.Equals, 66)
c.Assert(howSimilar("Totally different", "Not Same"), qt.Equals, 0)
c.Assert(howSimilar(sentence, sentenceReversed), qt.Equals, 14)
c.Assert(howSimilar(template.HTML("Hugo Rules"), template.HTML("Hugo Rules")), qt.Equals, 100)
c.Assert(howSimilar(map[string]interface{}{"a": 32, "b": 33}, map[string]interface{}{"a": 32, "b": 33}), qt.Equals, 100)
c.Assert(howSimilar(map[string]interface{}{"a": 32, "b": 33}, map[string]interface{}{"a": 32, "b": 34}), qt.Equals, 0)

}

type testStruct struct {
Name string
}

func TestSimilarPercentageNonString(t *testing.T) {
c := qt.New(t)
c.Assert(howSimilar(page.NopPage, page.NopPage), qt.Equals, 100)
c.Assert(howSimilar(page.Pages{}, page.Pages{}), qt.Equals, 90)
c.Assert(howSimilar(testStruct{Name: "A"}, testStruct{Name: "B"}), qt.Equals, 0)
c.Assert(howSimilar(testStruct{Name: "A"}, testStruct{Name: "A"}), qt.Equals, 100)

}

func BenchmarkHowSimilar(b *testing.B) {
Expand Down

0 comments on commit 5eadc4c

Please sign in to comment.