lang: Improve graph shape with speculative execution
Most of the time, we don't need to have a dynamic call sub graph, since the actual function call could be represented statically as it originally was before lambda functions were implemented. Simplifying the graph shape has important performance benefits in terms of both keep the graph smaller (memory, etc) and in avoiding the need to run transactions at runtime (speed) to reshape the graph. Co-authored-by: Samuel Gélineau <gelisam@gmail.com>
This commit is contained in:
@@ -508,6 +508,41 @@ func (obj *FuncSingleton) GraphFunc() (*pgraph.Graph, Func, error) {
|
||||
return obj.g, obj.f, nil
|
||||
}
|
||||
|
||||
// ValueEnv is a future potential argument to the Value() method on Expr.
|
||||
// XXX: Consider using this if we want to improve graph shape even more.
|
||||
type ValueEnv struct {
|
||||
Variables map[Expr]types.Value
|
||||
}
|
||||
|
||||
// EmptyValueEnv returns the zero, empty value for the value env, with all the
|
||||
// internal maps initialized appropriately.
|
||||
func EmptyValueEnv() *ValueEnv {
|
||||
return &ValueEnv{
|
||||
Variables: make(map[Expr]types.Value),
|
||||
}
|
||||
}
|
||||
|
||||
// Copy makes a copy of the ValueEnv struct. This ensures that if the internal
|
||||
// maps are changed, it doesn't affect other copies of the ValueEnv. It does
|
||||
// *not* copy or change the pointers contained within, since these are
|
||||
// references, and we need those to be consistently pointing to the same things
|
||||
// after copying.
|
||||
func (obj *ValueEnv) Copy() *ValueEnv {
|
||||
if obj == nil { // allow copying nil envs
|
||||
return EmptyValueEnv()
|
||||
}
|
||||
|
||||
variables := make(map[Expr]types.Value)
|
||||
|
||||
for k, v := range obj.Variables { // copy
|
||||
variables[k] = v // we don't copy the values!
|
||||
}
|
||||
|
||||
return &ValueEnv{
|
||||
Variables: variables,
|
||||
}
|
||||
}
|
||||
|
||||
// Arg represents a name identifier for a func or class argument declaration and
|
||||
// is sometimes accompanied by a type. This does not satisfy the Expr interface.
|
||||
type Arg struct {
|
||||
|
||||
@@ -44,6 +44,10 @@ import (
|
||||
// FuncSig is the simple signature that is used throughout our implementations.
|
||||
type FuncSig = func(context.Context, []types.Value) (types.Value, error)
|
||||
|
||||
// GraphSig is the simple signature that is used throughout our implementations.
|
||||
// TODO: Rename this?
|
||||
type GraphSig = func(Txn, []Func) (Func, error)
|
||||
|
||||
// Compile-time guarantee that *types.FuncValue accepts a func of type FuncSig.
|
||||
var _ = &types.FuncValue{V: FuncSig(nil)}
|
||||
|
||||
@@ -53,7 +57,8 @@ var _ = &types.FuncValue{V: FuncSig(nil)}
|
||||
type Info struct {
|
||||
Pure bool // is the function pure? (can it be memoized?)
|
||||
Memo bool // should the function be memoized? (false if too much output)
|
||||
Slow bool // is the function slow? (avoid speculative execution)
|
||||
Fast bool // is the function slow? (avoid speculative execution)
|
||||
Spec bool // can we speculatively execute it? (true for most)
|
||||
Sig *types.Type // the signature of the function, must be KindFunc
|
||||
Err error // is this a valid function, or was it created improperly?
|
||||
}
|
||||
@@ -116,6 +121,8 @@ type Func interface {
|
||||
// It must close the Output chan if it's done sending new values out. It
|
||||
// must send at least one value, or return an error. It may also return
|
||||
// an error at anytime if it can't continue.
|
||||
// XXX: Remove this from here, it should appear as StreamableFunc and
|
||||
// funcs should implement StreamableFunc or CallableFunc or maybe both.
|
||||
Stream(context.Context) error
|
||||
}
|
||||
|
||||
@@ -137,6 +144,7 @@ type Func interface {
|
||||
// the InferableFunc interface as well.
|
||||
type BuildableFunc interface {
|
||||
Func // implement everything in Func but add the additional requirements
|
||||
// XXX: Should this be CopyableFunc instead?
|
||||
|
||||
// Build takes the known or unified type signature for this function and
|
||||
// finalizes this structure so that it is now determined, and ready to
|
||||
@@ -273,7 +281,7 @@ type FuncData struct {
|
||||
// special functions that are useful in core.
|
||||
// TODO: This could be replaced if a func ever needs a SetScope method...
|
||||
type DataFunc interface {
|
||||
Func // implement everything in Func but add the additional requirements
|
||||
CopyableFunc // implement everything, but make it also have Copy
|
||||
|
||||
// SetData is used by the language to pass our function some code-level
|
||||
// context.
|
||||
|
||||
Reference in New Issue
Block a user