perf: eth: gas estimate set applyTsMessages false (#10546)

* have gas estimate call callInternal with applyTsMessages = false and other calls with applyTsMessages=true for gas caclulation optimization

* set applyTsMessages = true in CallWithGas call in shed

* update test with new callwithgas api optimization for eth call

* Update chain/stmgr/call.go

Co-authored-by: Łukasz Magiera <magik6k@users.noreply.github.com>

* env flag LOTUS_SKIP_APPLY_TS_MESSAGE_CALL_WITH_GAS must be 1 in order to have applyTsMessages change

* env flag LOTUS_SKIP_APPLY_TS_MESSAGE_CALL_WITH_GAS must be 1 in order to have applyTsMessages change

* make sure that even if we arent apply ts messages we grab ts messages from the particular user who is requesting gas estimation

---------

Co-authored-by: Jiaying Wang <42981373+jennijuju@users.noreply.github.com>
Co-authored-by: Łukasz Magiera <magik6k@users.noreply.github.com>
Co-authored-by: Ubuntu <ubuntu@ip-10-0-4-29.us-east-2.compute.internal>
This commit is contained in:
Mikers 2023-03-23 12:27:01 -10:00 committed by GitHub
parent 4efc29aa64
commit 41fce94db4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 39 additions and 12 deletions

View File

@ -52,8 +52,8 @@ func (sm *StateManager) Call(ctx context.Context, msg *types.Message, ts *types.
} }
// CallWithGas calculates the state for a given tipset, and then applies the given message on top of that state. // CallWithGas calculates the state for a given tipset, and then applies the given message on top of that state.
func (sm *StateManager) CallWithGas(ctx context.Context, msg *types.Message, priorMsgs []types.ChainMsg, ts *types.TipSet) (*api.InvocResult, error) { func (sm *StateManager) CallWithGas(ctx context.Context, msg *types.Message, priorMsgs []types.ChainMsg, ts *types.TipSet, applyTsMessages bool) (*api.InvocResult, error) {
return sm.callInternal(ctx, msg, priorMsgs, ts, cid.Undef, sm.GetNetworkVersion, true, true) return sm.callInternal(ctx, msg, priorMsgs, ts, cid.Undef, sm.GetNetworkVersion, true, applyTsMessages)
} }
// CallAtStateAndVersion allows you to specify a message to execute on the given stateCid and network version. // CallAtStateAndVersion allows you to specify a message to execute on the given stateCid and network version.
@ -117,12 +117,22 @@ func (sm *StateManager) callInternal(ctx context.Context, msg *types.Message, pr
if stateCid == cid.Undef { if stateCid == cid.Undef {
stateCid = ts.ParentState() stateCid = ts.ParentState()
} }
tsMsgs, err := sm.cs.MessagesForTipset(ctx, ts)
if err != nil {
return nil, xerrors.Errorf("failed to lookup messages for parent tipset: %w", err)
}
if applyTsMessages { if applyTsMessages {
tsMsgs, err := sm.cs.MessagesForTipset(ctx, ts)
if err != nil {
return nil, xerrors.Errorf("failed to lookup messages for parent tipset: %w", err)
}
priorMsgs = append(tsMsgs, priorMsgs...) priorMsgs = append(tsMsgs, priorMsgs...)
} else {
var filteredTsMsgs []types.ChainMsg
for _, tsMsg := range tsMsgs {
//TODO we should technically be normalizing the filecoin address of from when we compare here
if tsMsg.VMMessage().From == msg.VMMessage().From {
filteredTsMsgs = append(filteredTsMsgs, tsMsg)
}
}
priorMsgs = append(filteredTsMsgs, priorMsgs...)
} }
// Technically, the tipset we're passing in here should be ts+1, but that may not exist. // Technically, the tipset we're passing in here should be ts+1, but that may not exist.

View File

@ -341,7 +341,7 @@ func testForkRefuseCall(t *testing.T, nullsBefore, nullsAfter int) {
currentHeight := ts.TipSet.TipSet().Height() currentHeight := ts.TipSet.TipSet().Height()
// CallWithGas calls on top of the given tipset. // CallWithGas calls on top of the given tipset.
ret, err := sm.CallWithGas(ctx, m, nil, ts.TipSet.TipSet()) ret, err := sm.CallWithGas(ctx, m, nil, ts.TipSet.TipSet(), true)
if parentHeight <= testForkHeight && currentHeight >= testForkHeight { if parentHeight <= testForkHeight && currentHeight >= testForkHeight {
// If I had a fork, or I _will_ have a fork, it should fail. // If I had a fork, or I _will_ have a fork, it should fail.
require.Equal(t, ErrExpensiveFork, err) require.Equal(t, ErrExpensiveFork, err)
@ -362,7 +362,7 @@ func testForkRefuseCall(t *testing.T, nullsBefore, nullsAfter int) {
// Calls without a tipset should walk back to the last non-fork tipset. // Calls without a tipset should walk back to the last non-fork tipset.
// We _verify_ that the migration wasn't run multiple times at the end of the // We _verify_ that the migration wasn't run multiple times at the end of the
// test. // test.
ret, err = sm.CallWithGas(ctx, m, nil, nil) ret, err = sm.CallWithGas(ctx, m, nil, nil, true)
require.NoError(t, err) require.NoError(t, err)
require.True(t, ret.MsgRct.ExitCode.IsSuccess()) require.True(t, ret.MsgRct.ExitCode.IsSuccess())

View File

@ -241,7 +241,7 @@ var replayOfflineCmd = &cli.Command{
} }
tw := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', tabwriter.AlignRight) tw := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', tabwriter.AlignRight)
res, err := sm.CallWithGas(ctx, msg, []types.ChainMsg{}, executionTs) res, err := sm.CallWithGas(ctx, msg, []types.ChainMsg{}, executionTs, true)
if err != nil { if err != nil {
return err return err
} }

View File

@ -6,6 +6,7 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"os"
"sort" "sort"
"strconv" "strconv"
"sync" "sync"
@ -888,9 +889,14 @@ func (a *EthModule) applyMessage(ctx context.Context, msg *types.Message, tsk ty
return nil, xerrors.Errorf("cannot get tipset: %w", err) return nil, xerrors.Errorf("cannot get tipset: %w", err)
} }
applyTsMessages := true
if os.Getenv("LOTUS_SKIP_APPLY_TS_MESSAGE_CALL_WITH_GAS") == "1" {
applyTsMessages = false
}
// Try calling until we find a height with no migration. // Try calling until we find a height with no migration.
for { for {
res, err = a.StateManager.CallWithGas(ctx, msg, []types.ChainMsg{}, ts) res, err = a.StateManager.CallWithGas(ctx, msg, []types.ChainMsg{}, ts, applyTsMessages)
if err != stmgr.ErrExpensiveFork { if err != stmgr.ErrExpensiveFork {
break break
} }
@ -959,10 +965,15 @@ func gasSearch(
high := msg.GasLimit high := msg.GasLimit
low := msg.GasLimit low := msg.GasLimit
applyTsMessages := true
if os.Getenv("LOTUS_SKIP_APPLY_TS_MESSAGE_CALL_WITH_GAS") == "1" {
applyTsMessages = false
}
canSucceed := func(limit int64) (bool, error) { canSucceed := func(limit int64) (bool, error) {
msg.GasLimit = limit msg.GasLimit = limit
res, err := smgr.CallWithGas(ctx, &msg, priorMsgs, ts) res, err := smgr.CallWithGas(ctx, &msg, priorMsgs, ts, applyTsMessages)
if err != nil { if err != nil {
return false, xerrors.Errorf("CallWithGas failed: %w", err) return false, xerrors.Errorf("CallWithGas failed: %w", err)
} }

View File

@ -4,6 +4,7 @@ import (
"context" "context"
"math" "math"
"math/rand" "math/rand"
"os"
"sort" "sort"
lru "github.com/hashicorp/golang-lru/v2" lru "github.com/hashicorp/golang-lru/v2"
@ -276,10 +277,15 @@ func gasEstimateCallWithGas(
priorMsgs = append(priorMsgs, m) priorMsgs = append(priorMsgs, m)
} }
applyTsMessages := true
if os.Getenv("LOTUS_SKIP_APPLY_TS_MESSAGE_CALL_WITH_GAS") == "1" {
applyTsMessages = false
}
// Try calling until we find a height with no migration. // Try calling until we find a height with no migration.
var res *api.InvocResult var res *api.InvocResult
for { for {
res, err = smgr.CallWithGas(ctx, &msg, priorMsgs, ts) res, err = smgr.CallWithGas(ctx, &msg, priorMsgs, ts, applyTsMessages)
if err != stmgr.ErrExpensiveFork { if err != stmgr.ErrExpensiveFork {
break break
} }