Skip to content

Commit 00cd1e9

Browse files
authored
ruleguard: add profiling labels support (#338)
When ruleguard is compiled with `--tags pproflabels`, profiling will record per rules group labels, like `rules:groupname`. This makes it easies to find the rules that may need to be optimized or re-written in some other way. Build tags protection is used to avoid the overhead in the normal mode, when labels are not needed. ``` (pprof) tags rules: Total 2.3s 410.0ms (18.14%): dupArg 350.0ms (15.49%): offBy1 250.0ms (11.06%): badLock 160.0ms ( 7.08%): argOrder 140.0ms ( 6.19%): equalFold 120.0ms ( 5.31%): redundantSprint 110.0ms ( 4.87%): wrapperFunc 90.0ms ( 3.98%): ioutilDeprecated 80.0ms ( 3.54%): preferFprint 70.0ms ( 3.10%): assignOp 60.0ms ( 2.65%): badCall 60.0ms ( 2.65%): externalErrorReassign 60.0ms ( 2.65%): stringXbytes 50.0ms ( 2.21%): valSwap 40.0ms ( 1.77%): stringConcatSimplify 40.0ms ( 1.77%): yodaStyleExpr 20.0ms ( 0.88%): badSorting 20.0ms ( 0.88%): flagDeref 20.0ms ( 0.88%): httpNoBody 20.0ms ( 0.88%): preferStringWriter 20.0ms ( 0.88%): timeExprSimplify 10.0ms ( 0.44%): dynamicFmtString 10.0ms ( 0.44%): emptyStringTest 10.0ms ( 0.44%): preferWriteByte 10.0ms ( 0.44%): regexpMust 10.0ms ( 0.44%): returnAfterHttpError 10.0ms ( 0.44%): sloppyLen 10.0ms ( 0.44%): sprintfQuotedString ```
1 parent 3db0900 commit 00cd1e9

File tree

3 files changed

+55
-0
lines changed

3 files changed

+55
-0
lines changed

ruleguard/profiling/no_labels.go

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//go:build !pproflabels
2+
// +build !pproflabels
3+
4+
package profiling
5+
6+
import (
7+
"context"
8+
)
9+
10+
const LabelsEnabled = false
11+
12+
func EnterWithLabels(origContext context.Context, name string) {
13+
}
14+
15+
func Leave(origContext context.Context) {
16+
}

ruleguard/profiling/with_labels.go

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//go:build pproflabels
2+
// +build pproflabels
3+
4+
package profiling
5+
6+
import (
7+
"context"
8+
"runtime/pprof"
9+
)
10+
11+
const LabelsEnabled = true
12+
13+
func EnterWithLabels(origContext context.Context, name string) {
14+
labels := pprof.Labels("rules", name)
15+
ctx := pprof.WithLabels(origContext, labels)
16+
pprof.SetGoroutineLabels(ctx)
17+
}
18+
19+
func Leave(origContext context.Context) {
20+
pprof.SetGoroutineLabels(origContext)
21+
}

ruleguard/runner.go

+18
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package ruleguard
22

33
import (
44
"bytes"
5+
"context"
56
"fmt"
67
"go/ast"
78
"go/build"
@@ -13,13 +14,16 @@ import (
1314
"strings"
1415

1516
"github.com/quasilyte/go-ruleguard/ruleguard/goutil"
17+
"github.com/quasilyte/go-ruleguard/ruleguard/profiling"
1618
"github.com/quasilyte/gogrep"
1719
"github.com/quasilyte/gogrep/nodetag"
1820
)
1921

2022
type rulesRunner struct {
2123
state *engineState
2224

25+
bgContext context.Context
26+
2327
ctx *RunContext
2428
rules *goRuleSet
2529

@@ -60,6 +64,7 @@ func newRulesRunner(ctx *RunContext, buildContext *build.Context, state *engineS
6064
gogrepState := gogrep.NewMatcherState()
6165
gogrepState.Types = ctx.Types
6266
rr := &rulesRunner{
67+
bgContext: context.Background(),
6368
ctx: ctx,
6469
importer: importer,
6570
rules: rules,
@@ -209,12 +214,25 @@ func (rr *rulesRunner) runCommentRules(comment *ast.Comment) {
209214
}
210215

211216
func (rr *rulesRunner) runRules(n ast.Node) {
217+
// profiling.LabelsEnabled is constant, so labels-related
218+
// code should be a no-op inside normal build.
219+
// To enable labels, use "-tags pproflabels" build tag.
220+
212221
tag := nodetag.FromNode(n)
213222
for _, rule := range rr.rules.universal.rulesByTag[tag] {
223+
if profiling.LabelsEnabled {
224+
profiling.EnterWithLabels(rr.bgContext, rule.group.Name)
225+
}
226+
214227
matched := false
215228
rule.pat.MatchNode(&rr.gogrepState, n, func(m gogrep.MatchData) {
216229
matched = rr.handleMatch(rule, m)
217230
})
231+
232+
if profiling.LabelsEnabled {
233+
profiling.Leave(rr.bgContext)
234+
}
235+
218236
if matched {
219237
break
220238
}

0 commit comments

Comments
 (0)