mirror of
https://github.com/romychs/Ocean-240.2-Emulator.git
synced 2026-04-21 11:03:21 +03:00
151 lines
4.2 KiB
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)
|
|
}
|
|
})
|
|
|
|
}
|
|
}
|