Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion runtime/common/computationkind.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ const (
ComputationKindCreateArrayValue
ComputationKindTransferArrayValue
ComputationKindDestroyArrayValue
_
ComputationKindIterateArrayValue
Comment thread
SupunS marked this conversation as resolved.
_
_
_
Expand Down
7 changes: 4 additions & 3 deletions runtime/common/computationkind_string.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions runtime/interpreter/value.go
Original file line number Diff line number Diff line change
Expand Up @@ -2986,6 +2986,9 @@ func (v *ArrayValue) Reverse(
count := v.Count()
index := count - 1

// Meter computation for iterating the array.
interpreter.ReportComputation(common.ComputationKindIterateArrayValue, uint(v.Count()))
Comment thread
turbolent marked this conversation as resolved.
Outdated

return NewArrayValueWithIterator(
interpreter,
v.Type,
Expand Down Expand Up @@ -3017,6 +3020,9 @@ func (v *ArrayValue) Filter(
procedure FunctionValue,
) Value {

// Meter computation for iterating the array.
interpreter.ReportComputation(common.ComputationKindIterateArrayValue, uint(v.Count()))

elementTypeSlice := []sema.Type{v.semaType.ElementType(false)}
iterationInvocation := func(arrayElement Value) Invocation {
invocation := NewInvocation(
Expand Down Expand Up @@ -3091,6 +3097,9 @@ func (v *ArrayValue) Map(
transformFunctionType *sema.FunctionType,
) Value {

// Meter computation for iterating the array.
interpreter.ReportComputation(common.ComputationKindIterateArrayValue, uint(v.Count()))

elementTypeSlice := []sema.Type{v.semaType.ElementType(false)}
iterationInvocation := func(arrayElement Value) Invocation {
return NewInvocation(
Expand Down
3 changes: 3 additions & 0 deletions runtime/interpreter/value_string.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,9 @@ func stringFunctionJoin(invocation Invocation) Value {
panic(errors.NewUnreachableError())
}

// Meter computation for iterating the array.
inter.ReportComputation(common.ComputationKindIterateArrayValue, uint(stringArray.Count()))

// NewStringMemoryUsage already accounts for empty string.
common.UseMemory(inter, common.NewStringMemoryUsage(0))
var builder strings.Builder
Expand Down
115 changes: 115 additions & 0 deletions runtime/tests/interpreter/metering_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -397,3 +397,118 @@ func TestInterpretFunctionInvocationHandler(t *testing.T) {
occurrences,
)
}

func TestInterpretArrayFunctionsComputationMetering(t *testing.T) {

t.Parallel()

t.Run("reverse", func(t *testing.T) {
t.Parallel()

computationMeteredValues := make(map[common.ComputationKind]uint)
inter, err := parseCheckAndInterpretWithOptions(t, `
fun main() {
let x = [1, 2, 3]
let y = x.reverse()
}`,
ParseCheckAndInterpretOptions{
Config: &interpreter.Config{
OnMeterComputation: func(compKind common.ComputationKind, intensity uint) {
computationMeteredValues[compKind] += intensity
},
},
},
)
require.NoError(t, err)

_, err = inter.Invoke("main")
require.NoError(t, err)

assert.Equal(t, uint(3), computationMeteredValues[common.ComputationKindIterateArrayValue])
})

t.Run("map", func(t *testing.T) {
t.Parallel()

computationMeteredValues := make(map[common.ComputationKind]uint)
inter, err := parseCheckAndInterpretWithOptions(t, `
fun main() {
let x = [1, 2, 3, 4]
let trueForEven = fun (_ x: Int): Bool {
return x % 2 == 0
}
let y = x.map(trueForEven)
}`,
ParseCheckAndInterpretOptions{
Config: &interpreter.Config{
OnMeterComputation: func(compKind common.ComputationKind, intensity uint) {
computationMeteredValues[compKind] += intensity
},
},
},
)
require.NoError(t, err)

_, err = inter.Invoke("main")
require.NoError(t, err)

assert.Equal(t, uint(4), computationMeteredValues[common.ComputationKindIterateArrayValue])
})

t.Run("filter", func(t *testing.T) {
t.Parallel()

computationMeteredValues := make(map[common.ComputationKind]uint)
inter, err := parseCheckAndInterpretWithOptions(t, `
fun main() {
let x = [1, 2, 3, 4, 5]
let onlyEven = fun (_ x: Int): Bool {
return x % 2 == 0
}
let y = x.filter(onlyEven)
}`,
ParseCheckAndInterpretOptions{
Config: &interpreter.Config{
OnMeterComputation: func(compKind common.ComputationKind, intensity uint) {
computationMeteredValues[compKind] += intensity
},
},
},
)
require.NoError(t, err)

_, err = inter.Invoke("main")
require.NoError(t, err)

assert.Equal(t, uint(5), computationMeteredValues[common.ComputationKindIterateArrayValue])
})
}

func TestInterpretStdlibComputationMetering(t *testing.T) {

t.Parallel()

t.Run("string join", func(t *testing.T) {
t.Parallel()

computationMeteredValues := make(map[common.ComputationKind]uint)
inter, err := parseCheckAndInterpretWithOptions(t, `
fun main() {
let s = String.join(["one", "two", "three", "four"], separator: ", ")
}`,
ParseCheckAndInterpretOptions{
Config: &interpreter.Config{
OnMeterComputation: func(compKind common.ComputationKind, intensity uint) {
computationMeteredValues[compKind] += intensity
},
},
},
)
require.NoError(t, err)

_, err = inter.Invoke("main")
require.NoError(t, err)

assert.Equal(t, uint(4), computationMeteredValues[common.ComputationKindIterateArrayValue])
})
}