Skip to content

Commit

Permalink
perf(logic): reduce read params in ask query
Browse files Browse the repository at this point in the history
amimart committed Jul 24, 2024

Verified

This commit was signed with the committer’s verified signature.
amimart Arnaud Mimart
1 parent c6e6bf6 commit 92e6d05
Showing 10 changed files with 81 additions and 79 deletions.
34 changes: 17 additions & 17 deletions x/logic/keeper/features/bech32_address_2.feature
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@ Feature: bech32_address/2
Then the answer we get is:
""" yaml
height: 42
gas_used: 6032
gas_used: 3876
answer:
has_more: false
variables: ["Address"]
@@ -39,7 +39,7 @@ Feature: bech32_address/2
Then the answer we get is:
""" yaml
height: 42
gas_used: 6032
gas_used: 3876
answer:
has_more: false
variables: ["Hrp", "Address"]
@@ -63,7 +63,7 @@ Feature: bech32_address/2
Then the answer we get is:
""" yaml
height: 42
gas_used: 6032
gas_used: 3876
answer:
has_more: false
variables: ["Address"]
@@ -84,7 +84,7 @@ Feature: bech32_address/2
Then the answer we get is:
""" yaml
height: 42
gas_used: 6032
gas_used: 3876
answer:
has_more: false
variables: ["Bech32"]
@@ -109,7 +109,7 @@ Feature: bech32_address/2
Then the answer we get is:
""" yaml
height: 42
gas_used: 6032
gas_used: 3876
answer:
has_more: false
results:
@@ -130,7 +130,7 @@ Feature: bech32_address/2
Then the answer we get is:
""" yaml
height: 42
gas_used: 6032
gas_used: 3876
answer:
has_more: false
results:
@@ -146,7 +146,7 @@ Feature: bech32_address/2
Then the answer we get is:
""" yaml
height: 42
gas_used: 6032
gas_used: 3876
answer:
has_more: false
results:
@@ -163,7 +163,7 @@ Feature: bech32_address/2
Then the answer we get is:
""" yaml
height: 42
gas_used: 6032
gas_used: 3876
answer:
has_more: false
variables: ["Hrp"]
@@ -186,7 +186,7 @@ Feature: bech32_address/2
Then the answer we get is:
""" yaml
height: 42
gas_used: 6032
gas_used: 3876
answer:
has_more: false
variables: ["Address"]
@@ -207,7 +207,7 @@ Feature: bech32_address/2
Then the answer we get is:
""" yaml
height: 42
gas_used: 6032
gas_used: 3876
answer:
has_more: false
variables: ["X"]
@@ -227,7 +227,7 @@ Feature: bech32_address/2
Then the answer we get is:
""" yaml
height: 42
gas_used: 6032
gas_used: 3876
answer:
has_more: false
variables: ["Bech32"]
@@ -247,7 +247,7 @@ Feature: bech32_address/2
Then the answer we get is:
""" yaml
height: 42
gas_used: 6032
gas_used: 3876
answer:
has_more: false
variables: ["Bech32"]
@@ -267,7 +267,7 @@ Feature: bech32_address/2
Then the answer we get is:
""" yaml
height: 42
gas_used: 6032
gas_used: 3876
answer:
has_more: false
variables: ["Bech32"]
@@ -287,7 +287,7 @@ Feature: bech32_address/2
Then the answer we get is:
""" yaml
height: 42
gas_used: 6032
gas_used: 3876
answer:
has_more: false
variables: ["Bech32"]
@@ -307,7 +307,7 @@ Feature: bech32_address/2
Then the answer we get is:
""" yaml
height: 42
gas_used: 6032
gas_used: 3876
answer:
has_more: false
variables: ["Bech32"]
@@ -327,7 +327,7 @@ Feature: bech32_address/2
Then the answer we get is:
""" yaml
height: 42
gas_used: 6032
gas_used: 3876
answer:
has_more: false
variables: ["Address", "Bech32"]
@@ -347,7 +347,7 @@ Feature: bech32_address/2
Then the answer we get is:
""" yaml
height: 42
gas_used: 6032
gas_used: 3876
answer:
has_more: false
variables: ["Hrp", "Bech32"]
4 changes: 2 additions & 2 deletions x/logic/keeper/features/block_height_1.feature
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@ Feature: block_height/1
Then the answer we get is:
""" yaml
height: 100
gas_used: 6032
gas_used: 3876
answer:
has_more: false
variables: ["Height"]
@@ -43,7 +43,7 @@ Feature: block_height/1
Then the answer we get is:
""" yaml
height: 101
gas_used: 6033
gas_used: 3877
answer:
has_more: false
variables: ["Height"]
4 changes: 2 additions & 2 deletions x/logic/keeper/features/block_time_1.feature
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@ Feature: block_time/1
Then the answer we get is:
""" yaml
height: 42
gas_used: 6032
gas_used: 3876
answer:
has_more: false
variables: ["Time"]
@@ -44,7 +44,7 @@ Feature: block_time/1
Then the answer we get is:
""" yaml
height: 42
gas_used: 6033
gas_used: 3877
answer:
has_more: false
variables: ["Time"]
6 changes: 3 additions & 3 deletions x/logic/keeper/features/consult_1.feature
Original file line number Diff line number Diff line change
@@ -34,7 +34,7 @@ Feature: consult/1
Then the answer we get is:
""" yaml
height: 42
gas_used: 6034
gas_used: 3878
answer:
has_more: false
variables: ["Who"]
@@ -90,7 +90,7 @@ Feature: consult/1
Then the answer we get is:
""" yaml
height: 42
gas_used: 6033
gas_used: 3877
answer:
has_more: false
variables: ["X"]
@@ -144,7 +144,7 @@ Feature: consult/1
Then the answer we get is:
""" yaml
height: 42
gas_used: 6033
gas_used: 3877
answer:
has_more: false
variables: ["File"]
10 changes: 5 additions & 5 deletions x/logic/keeper/features/current_output_1.feature
Original file line number Diff line number Diff line change
@@ -28,7 +28,7 @@ Feature: current_output/1
Then the answer we get is:
""" yaml
height: 42
gas_used: 6150
gas_used: 3976
answer:
has_more: false
variables:
@@ -66,7 +66,7 @@ Feature: current_output/1
Then the answer we get is:
""" yaml
height: 42
gas_used: 6190
gas_used: 4010
answer:
has_more: false
variables:
@@ -104,7 +104,7 @@ Feature: current_output/1
Then the answer we get is:
""" yaml
height: 42
gas_used: 6150
gas_used: 3976
answer:
has_more: false
variables:
@@ -145,7 +145,7 @@ Feature: current_output/1
Then the answer we get is:
""" yaml
height: 42
gas_used: 6164
gas_used: 3990
answer:
has_more: false
variables:
@@ -176,7 +176,7 @@ Feature: current_output/1
Then the answer we get is:
""" yaml
height: 42
gas_used: 6417
gas_used: 4261
answer:
has_more: false
variables:
2 changes: 1 addition & 1 deletion x/logic/keeper/features/open_3.feature
Original file line number Diff line number Diff line change
@@ -31,7 +31,7 @@ Feature: open/3
Then the answer we get is:
""" yaml
height: 42
gas_used: 6033
gas_used: 3877
answer:
has_more: false
variables:
22 changes: 11 additions & 11 deletions x/logic/keeper/features/open_4.feature
Original file line number Diff line number Diff line change
@@ -43,7 +43,7 @@ Feature: open/4
Then the answer we get is:
""" yaml
height: 42
gas_used: 6038
gas_used: 3882
answer:
has_more: false
variables: ["URI"]
@@ -86,7 +86,7 @@ Feature: open/4
Then the answer we get is:
""" yaml
height: 42
gas_used: 6034
gas_used: 3878
answer:
has_more: false
variables: ["Chars"]
@@ -127,7 +127,7 @@ Feature: open/4
Then the answer we get is:
""" yaml
height: 42
gas_used: 6034
gas_used: 3878
answer:
has_more: false
variables: ["Chars"]
@@ -149,7 +149,7 @@ Feature: open/4
Then the answer we get is:
""" yaml
height: 42
gas_used: 6032
gas_used: 3876
answer:
has_more: false
variables: ["Stream"]
@@ -170,7 +170,7 @@ Feature: open/4
Then the answer we get is:
""" yaml
height: 42
gas_used: 6032
gas_used: 3876
answer:
has_more: false
variables: ["Stream"]
@@ -191,7 +191,7 @@ Feature: open/4
Then the answer we get is:
""" yaml
height: 42
gas_used: 6032
gas_used: 3876
answer:
has_more: false
variables: ["Stream"]
@@ -212,7 +212,7 @@ Feature: open/4
Then the answer we get is:
""" yaml
height: 42
gas_used: 6032
gas_used: 3876
answer:
has_more: false
variables: ["Stream"]
@@ -232,7 +232,7 @@ Feature: open/4
Then the answer we get is:
""" yaml
height: 42
gas_used: 6032
gas_used: 3876
answer:
has_more: false
variables: ["Stream"]
@@ -251,7 +251,7 @@ Feature: open/4
Then the answer we get is:
""" yaml
height: 42
gas_used: 6032
gas_used: 3876
answer:
has_more: false
variables: ["Stream"]
@@ -270,7 +270,7 @@ Feature: open/4
Then the answer we get is:
""" yaml
height: 42
gas_used: 6032
gas_used: 3876
answer:
has_more: false
variables: ["Resource", "Stream"]
@@ -289,7 +289,7 @@ Feature: open/4
Then the answer we get is:
""" yaml
height: 42
gas_used: 6032
gas_used: 3876
answer:
has_more: false
variables: ["Mode", "Stream"]
23 changes: 20 additions & 3 deletions x/logic/keeper/grpc_query_ask.go
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@ package keeper

import (
goctx "context"

"math"

errorsmod "cosmossdk.io/errors"
sdkmath "cosmossdk.io/math"
@@ -37,18 +37,35 @@ func (k Keeper) Ask(ctx goctx.Context, req *types.QueryServiceAskRequest) (respo
}
}()

limits := k.limits(ctx)
if err := checkLimits(req, limits); err != nil {
params := k.GetParams(sdkCtx)
if err := checkLimits(req, params.Limits); err != nil {
return nil, err
}

return k.execute(
sdkCtx,
params,
req.Program,
req.Query,
util.DerefOrDefault(req.Limit, defaultSolutionsLimit))
}

func checkLimits(request *types.QueryServiceAskRequest, limits types.Limits) error {
size := sdkmath.NewUint(uint64(len(request.GetQuery())))
maxSize := util.DerefOrDefault(limits.MaxSize, sdkmath.NewUint(math.MaxInt64))
if size.GT(maxSize) {
return errorsmod.Wrapf(types.LimitExceeded, "query: %d > MaxSize: %d", size.Uint64(), maxSize.Uint64())
}

resultCount := util.DerefOrDefault(request.Limit, defaultSolutionsLimit)
maxResultCount := util.DerefOrDefault(limits.MaxResultCount, sdkmath.NewUint(math.MaxInt64))
if resultCount.GT(maxResultCount) {
return errorsmod.Wrapf(types.LimitExceeded, "query: %d > MaxResultCount: %d", resultCount.Uint64(), maxResultCount.Uint64())
}

return nil
}

// withSafeGasMeter returns a new context with a gas meter that has the given limit.
// The gas meter is go-router-safe.
func withSafeGasMeter(sdkCtx sdk.Context) sdk.Context {
29 changes: 16 additions & 13 deletions x/logic/keeper/grpc_query_ask_test.go
Original file line number Diff line number Diff line change
@@ -37,6 +37,7 @@ func TestGRPCAsk(t *testing.T) {
query string
limit int
maxResultCount int
maxSize int
predicateBlacklist []string
maxGas uint64
predicateCosts map[string]uint64
@@ -117,13 +118,13 @@ func TestGRPCAsk(t *testing.T) {
query: "father(bob, X).",
limit: 2,
maxResultCount: 1,
expectedAnswer: &types.Answer{
HasMore: true,
Variables: []string{"X"},
Results: []types.Result{{Substitutions: []types.Substitution{{
Variable: "X", Expression: "alice",
}}}},
},
expectedError: "query: 2 > MaxResultCount: 1: limit exceeded",
},
{
program: "father(bob, alice). father(bob, john).",
query: "father(bob, X).",
maxSize: 5,
expectedError: "query: 15 > MaxSize: 5: limit exceeded",
},
{
query: "block_height(X).",
@@ -141,16 +142,16 @@ func TestGRPCAsk(t *testing.T) {
},
{
query: "bank_balances(X, Y).",
maxGas: 3500,
expectedError: "out of gas: logic <panic: {ValuePerByte}> (5243/3500): limit exceeded",
maxGas: 3000,
expectedError: "out of gas: logic <panic: {ValuePerByte}> (3093/3000): limit exceeded",
},
{
query: "block_height(X).",
maxGas: 3500,
maxGas: 3000,
predicateCosts: map[string]uint64{
"block_height/1": 10000,
},
expectedError: "out of gas: logic <block_height/1> (13467/3500): limit exceeded",
expectedError: "out of gas: logic <block_height/1> (11167/3000): limit exceeded",
},
{
program: "father(bob, 'élodie').",
@@ -283,8 +284,8 @@ foo(a3) :- throw(error(resource_error(foo))).
foo(a4).
`,
query: `foo(X).`,
limit: 5,
maxResultCount: 3,
limit: 3,
maxResultCount: 5,
expectedAnswer: &types.Answer{
Variables: []string{"X"},
Results: []types.Result{
@@ -346,8 +347,10 @@ foo(a4).
},
)
maxResultCount := sdkmath.NewUint(uint64(lo.If(tc.maxResultCount == 0, 1).Else(tc.maxResultCount)))
maxSize := sdkmath.NewUint(uint64(lo.If(tc.maxSize == 0, 5000).Else(tc.maxSize)))
params := types.DefaultParams()
params.Limits.MaxResultCount = &maxResultCount
params.Limits.MaxSize = &maxSize
if tc.predicateBlacklist != nil {
params.Interpreter.PredicatesFilter.Blacklist = tc.predicateBlacklist
}
26 changes: 4 additions & 22 deletions x/logic/keeper/interpreter.go
Original file line number Diff line number Diff line change
@@ -4,7 +4,6 @@ import (
"context"
"fmt"
"io"
"math"
"strings"

"github.com/ichiban/prolog"
@@ -37,11 +36,6 @@ type writerStringer interface {
fmt.Stringer
}

func (k Keeper) limits(ctx context.Context) types.Limits {
params := k.GetParams(sdk.UnwrapSDKContext(ctx))
return params.GetLimits()
}

func (k Keeper) enhanceContext(ctx context.Context) context.Context {
sdkCtx := sdk.UnwrapSDKContext(ctx)
sdkCtx = sdkCtx.WithValue(types.AuthKeeperContextKey, k.authKeeper)
@@ -50,21 +44,20 @@ func (k Keeper) enhanceContext(ctx context.Context) context.Context {
}

func (k Keeper) execute(
ctx context.Context, program, query string, solutionsLimit sdkmath.Uint,
ctx context.Context, params types.Params, program, query string, solutionsLimit sdkmath.Uint,
) (*types.QueryServiceAskResponse, error) {
ctx = k.enhanceContext(ctx)
sdkCtx := sdk.UnwrapSDKContext(ctx)
limits := k.limits(sdkCtx)

i, userOutput, err := k.newInterpreter(ctx)
i, userOutput, err := k.newInterpreter(ctx, params)
if err != nil {
return nil, errorsmod.Wrapf(types.Internal, "error creating interpreter: %v", err.Error())
}
if err := i.ExecContext(ctx, program); err != nil {
return nil, errorsmod.Wrapf(types.InvalidArgument, "error compiling query: %v", err.Error())
}

answer, err := k.queryInterpreter(ctx, i, query, sdkmath.MinUint(solutionsLimit, *limits.MaxResultCount))
answer, err := k.queryInterpreter(ctx, i, query, solutionsLimit)
if err != nil {
return nil, err
}
@@ -85,9 +78,8 @@ func (k Keeper) queryInterpreter(
}

// newInterpreter creates a new interpreter properly configured.
func (k Keeper) newInterpreter(ctx context.Context) (*prolog.Interpreter, fmt.Stringer, error) {
func (k Keeper) newInterpreter(ctx context.Context, params types.Params) (*prolog.Interpreter, fmt.Stringer, error) {
sdkctx := sdk.UnwrapSDKContext(ctx)
params := k.GetParams(sdkctx)

interpreterParams := params.GetInterpreter()
gasPolicy := params.GetGasPolicy()
@@ -148,16 +140,6 @@ func (k Keeper) newInterpreter(ctx context.Context) (*prolog.Interpreter, fmt.St
return i, userOutputBuffer, err
}

func checkLimits(request *types.QueryServiceAskRequest, limits types.Limits) error {
size := sdkmath.NewUint(uint64(len(request.GetQuery())))
maxSize := util.DerefOrDefault(limits.MaxSize, sdkmath.NewUint(math.MaxInt64))
if size.GT(maxSize) {
return errorsmod.Wrapf(types.LimitExceeded, "query: %d > MaxSize: %d", size, maxSize)
}

return nil
}

func lookupCost(predicate string, defaultCost uint64, costs []types.PredicateCost) uint64 {
for _, c := range costs {
if prolog2.PredicateMatches(predicate)(c.Predicate) {

0 comments on commit 92e6d05

Please sign in to comment.