Ocean-240.2-Emulator/gval/benchmarks_test.go

151 lines
4.2 KiB
Go

package gval
import (
"context"
"testing"
)
func BenchmarkGval(bench *testing.B) {
benchmarks := []evaluationTest{
{
// Serves as a "water test" to give an idea of the general overhead
name: "const",
expression: "1",
},
{
name: "single parameter",
expression: "requests_made",
parameter: map[string]interface{}{
"requests_made": 99.0,
},
},
{
name: "parameter",
expression: "requests_made > requests_succeeded",
parameter: map[string]interface{}{
"requests_made": 99.0,
"requests_succeeded": 90.0,
},
},
{
// The most common use case, a single variable, modified slightly, compared to a constant.
// This is the "expected" use case.
name: "common",
expression: "(requests_made * requests_succeeded / 100) >= 90",
parameter: map[string]interface{}{
"requests_made": 99.0,
"requests_succeeded": 90.0,
},
},
{
// All major possibilities in one expression.
name: "complex",
expression: `2 > 1 &&
"something" != "nothing" ||
date("2014-01-20") < date("Wed Jul 8 23:07:35 MDT 2015") &&
object["Variable name with spaces"] <= array[0] &&
modifierTest + 1000 / 2 > (80 * 100 % 2)`,
parameter: map[string]interface{}{
"object": map[string]interface{}{"Variable name with spaces": 10.},
"array": []interface{}{0.},
"modifierTest": 7.3,
},
},
{
// no variables, no modifiers
name: "literal",
expression: "(2) > (1)",
},
{
name: "modifier",
expression: "(2) + (2) == (4)",
},
{
// Benchmarks uncompiled parameter regex operators, which are the most expensive of the lot.
// Note that regex compilation times are unpredictable and wily things. The regex engine has a lot of edge cases
// and possible performance pitfalls. This test doesn't aim to be comprehensive against all possible regex scenarios,
// it is primarily concerned with tracking how much longer it takes to compile a regex at evaluation-time than during parse-time.
name: "regex",
expression: "(foo !~ bar) && (foo + bar =~ oba)",
parameter: map[string]interface{}{
"foo": "foo",
"bar": "bar",
"baz": "baz",
"oba": ".*oba.*",
},
},
{
// Benchmarks pre-compilable regex patterns. Meant to serve as a sanity check that constant strings used as regex patterns
// are actually being precompiled.
// Also demonstrates that (generally) compiling a regex at evaluation-time takes an order of magnitude more time than pre-compiling.
name: "constant regex",
expression: `(foo !~ "[bB]az") && (bar =~ "[bB]ar")`,
parameter: map[string]interface{}{
"foo": "foo",
"bar": "bar",
"baz": "baz",
"oba": ".*oba.*",
},
},
{
name: "accessors",
expression: "foo.Int",
parameter: fooFailureParameters,
},
{
name: "accessors method",
expression: "foo.Func()",
parameter: fooFailureParameters,
},
{
name: "accessors method parameter",
expression: `foo.FuncArgStr("bonk")`,
parameter: fooFailureParameters,
},
{
name: "nested accessors",
expression: `foo.Nested.Funk`,
parameter: fooFailureParameters,
},
{
name: "decimal arithmetic",
expression: "(requests_made * requests_succeeded / 100)",
extension: decimalArithmetic,
parameter: map[string]interface{}{
"requests_made": 99.0,
"requests_succeeded": 90.0,
},
},
{
name: "decimal logic",
expression: "(requests_made * requests_succeeded / 100) >= 90",
extension: decimalArithmetic,
parameter: map[string]interface{}{
"requests_made": 99.0,
"requests_succeeded": 90.0,
},
},
}
for _, benchmark := range benchmarks {
eval, err := Full().NewEvaluable(benchmark.expression)
if err != nil {
bench.Fatal(err)
}
_, err = eval(context.Background(), benchmark.parameter)
if err != nil {
bench.Fatal(err)
}
bench.Run(benchmark.name+"_evaluation", func(bench *testing.B) {
for i := 0; i < bench.N; i++ {
eval(context.Background(), benchmark.parameter)
}
})
bench.Run(benchmark.name+"_parsing", func(bench *testing.B) {
for i := 0; i < bench.N; i++ {
Full().NewEvaluable(benchmark.expression)
}
})
}
}