Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf: use GetByValue to avoid boxing to interface{} #7372

Merged
merged 1 commit into from
Feb 18, 2025

Conversation

anderseknert
Copy link
Member

And make shorthand types boxed types to avoid allocations at runtime.

Below stats show the difference running Regal lint with all rules disabled (to better highlight compilation costs). @srenatus will be pleased by this format, I'm sure.

goos: darwin
goarch: arm64
pkg: github.com/styrainc/regal/pkg/linter
cpu: Apple M4 Pro
                       │  main.txt   │              pr.txt               │
                       │   sec/op    │   sec/op     vs base              │
RegalNoEnabledRules-12   190.8m ± 2%   181.8m ± 2%  -4.72% (p=0.002 n=6)

                       │   main.txt   │               pr.txt               │
                       │     B/op     │     B/op      vs base              │
RegalNoEnabledRules-12   474.4Mi ± 0%   471.3Mi ± 0%  -0.65% (p=0.002 n=6)

                       │  main.txt   │              pr.txt               │
                       │  allocs/op  │  allocs/op   vs base              │
RegalNoEnabledRules-12   9.657M ± 0%   9.476M ± 0%  -1.88% (p=0.002 n=6)

And make shorthand types boxed types to avoid allocations at runtime.

Below stats show the difference running Regal lint with all rules disabled
(to better highlight compilation costs). @srenatus will be pleased by this
format, I'm sure.

```
goos: darwin
goarch: arm64
pkg: github.com/styrainc/regal/pkg/linter
cpu: Apple M4 Pro
                       │  main.txt   │              pr.txt               │
                       │   sec/op    │   sec/op     vs base              │
RegalNoEnabledRules-12   190.8m ± 2%   181.8m ± 2%  -4.72% (p=0.002 n=6)

                       │   main.txt   │               pr.txt               │
                       │     B/op     │     B/op      vs base              │
RegalNoEnabledRules-12   474.4Mi ± 0%   471.3Mi ± 0%  -0.65% (p=0.002 n=6)

                       │  main.txt   │              pr.txt               │
                       │  allocs/op  │  allocs/op   vs base              │
RegalNoEnabledRules-12   9.657M ± 0%   9.476M ± 0%  -1.88% (p=0.002 n=6)
```

Signed-off-by: Anders Eknert <[email protected]>
ref = append(ref, dynamicSuffix[i])
}
rule.Head.SetRef(ref)
rule.Head.SetRef(append(ref, dynamicSuffix...))
Copy link
Member Author

Choose a reason for hiding this comment

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

This is unrelated but suggested by a later version of golangci-lint, which was nice :)

@@ -131,7 +131,7 @@ func (w *compressResponseWriter) doCompressedResponse() error {
w.Header().Del(contentLengthHeader)
w.writeHeader()
// there's nothing to write
if w.buffer == nil || len(w.buffer) <= 0 {
if len(w.buffer) <= 0 {
Copy link
Member Author

Choose a reason for hiding this comment

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

Also golangci-lint

Copy link
Contributor

@johanfylling johanfylling left a comment

Choose a reason for hiding this comment

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

👍

tpe := types.Keys(rc.env.getRefRecExtent(node))
if exist := rc.env.Get(v); exist != nil {
if exist := rc.env.GetByValue(head.Value); exist != nil {
Copy link
Contributor

Choose a reason for hiding this comment

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

In a lot of places, we're pulling the value out of a term; enough to warrant a GetByRef()/GetByRefValue()?

Copy link
Member Author

Choose a reason for hiding this comment

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

You mean we should accept a *Term instead of a Value? I'm generally in favor of accepting the least common denominator, which in this case would be the value... and we'd still need GetByRef (which we did before as well, it was just internal).

@@ -518,7 +518,7 @@ func TestCheckInferenceRules(t *testing.T) {
{"ref_regression_array_key", ruleset2, "data.ref_regression_array_key.walker",
types.NewObject(
nil,
types.NewDynamicProperty(types.NewArray([]types.Type{types.NewArray(types.A, types.A), types.A}, nil),
types.NewDynamicProperty(types.NewArray([]types.Type{types.NewArray(types.NewAny(), types.A), types.A}, nil),
Copy link
Contributor

Choose a reason for hiding this comment

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

Why this change?

Copy link
Member Author

Choose a reason for hiding this comment

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

types.A now represents the boxed Type (interface) of Any rather than Any ([]Type), and in the case of types.NewArray, the latter was expected.

// Any represents a dynamic type.
type Any []Type

// A represents the superset of all types.
var A Type = NewAny()

@anderseknert anderseknert merged commit 772a29f into open-policy-agent:main Feb 18, 2025
28 checks passed
@anderseknert anderseknert deleted the typecheck-perf branch February 18, 2025 15:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants