feat: improve std.reverse performance by 73.39%

Implements std.reverse in native Go, improving performance

benchmark                        old ns/op     new ns/op     delta
Benchmark_Builtin_reverse-16     869191619     231309458     -73.39%

part of #111
This commit is contained in:
Wes McNamee 2019-12-15 13:43:53 -08:00 committed by Stanisław Barzowski
parent 27b4c60bc7
commit 3b580145f4
13 changed files with 64 additions and 2 deletions

View File

@ -0,0 +1,5 @@
{
foo: [
std.reverse(std.range(0, 5000)) for i in std.range(0,100)
],
}

View File

@ -345,6 +345,23 @@ func builtinJoin(i *interpreter, trace traceElement, sep, arrv value) (value, er
}
}
func builtinReverse(i *interpreter, trace traceElement, arrv value) (value, error) {
arr, err := i.getArray(arrv, trace)
if err != nil {
return nil, err
}
lenArr := len(arr.elements) // lenx holds the original array length
reversed_array := make([]*cachedThunk, lenArr) // creates a slice that refer to a new array of length lenx
for i := 0; i < lenArr; i++ {
j := lenArr - (i + 1) // j initially holds (lenx - 1) and decreases to 0 while i initially holds 0 and increase to (lenx - 1)
reversed_array[i] = arr.elements[j]
}
return makeValueArray(reversed_array), nil
}
func builtinFilter(i *interpreter, trace traceElement, funcv, arrv value) (value, error) {
arr, err := i.getArray(arrv, trace)
if err != nil {
@ -1271,6 +1288,7 @@ var funcBuiltins = buildBuiltinMap([]builtin{
&binaryBuiltin{name: "makeArray", function: builtinMakeArray, parameters: ast.Identifiers{"sz", "func"}},
&binaryBuiltin{name: "flatMap", function: builtinFlatMap, parameters: ast.Identifiers{"func", "arr"}},
&binaryBuiltin{name: "join", function: builtinJoin, parameters: ast.Identifiers{"sep", "arr"}},
&unaryBuiltin{name: "reverse", function: builtinReverse, parameters: ast.Identifiers{"arr"}},
&binaryBuiltin{name: "filter", function: builtinFilter, parameters: ast.Identifiers{"func", "arr"}},
&binaryBuiltin{name: "range", function: builtinRange, parameters: ast.Identifiers{"from", "to"}},
&binaryBuiltin{name: "primitiveEquals", function: primitiveEquals, parameters: ast.Identifiers{"x", "y"}},

View File

@ -2,6 +2,7 @@ package jsonnet
import (
"flag"
"fmt"
"os"
"os/exec"
"testing"
@ -15,9 +16,9 @@ func init() {
flag.BoolVar(&outputPassthru, "outputPassthru", false, "Pass stdout/err from jsonnet")
}
func Benchmark_Builtin_substr(b *testing.B) {
func RunBenchmark(b *testing.B, name string) {
for n := 0; n < b.N; n++ {
cmd := exec.Command(jsonnetPath, "./builtin-benchmarks/substr.jsonnet")
cmd := exec.Command(jsonnetPath, fmt.Sprintf("./builtin-benchmarks/%s.jsonnet", name))
if outputPassthru {
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
@ -29,3 +30,11 @@ func Benchmark_Builtin_substr(b *testing.B) {
}
}
}
func Benchmark_Builtin_substr(b *testing.B) {
RunBenchmark(b, "substr")
}
func Benchmark_Builtin_reverse(b *testing.B) {
RunBenchmark(b, "reverse")
}

4
testdata/builtinReverse.golden vendored Normal file
View File

@ -0,0 +1,4 @@
[
2,
1
]

1
testdata/builtinReverse.jsonnet vendored Normal file
View File

@ -0,0 +1 @@
std.reverse([1, 2])

1
testdata/builtinReverse_empty.golden vendored Normal file
View File

@ -0,0 +1 @@
[ ]

1
testdata/builtinReverse_empty.jsonnet vendored Normal file
View File

@ -0,0 +1 @@
std.reverse([])

7
testdata/builtinReverse_many.golden vendored Normal file
View File

@ -0,0 +1,7 @@
[
"tester",
"is",
"name",
"my",
"hello"
]

1
testdata/builtinReverse_many.jsonnet vendored Normal file
View File

@ -0,0 +1 @@
std.reverse(["hello", "my", "name", "is", "tester"])

View File

@ -0,0 +1,10 @@
RUNTIME ERROR: Unexpected type string, expected array
-------------------------------------------------
testdata/builtinReverse_not_array:1:1-20 builtin function <reverse>
std.reverse("asdf")
-------------------------------------------------
During evaluation

View File

@ -0,0 +1 @@
std.reverse("asdf")

3
testdata/builtinReverse_single.golden vendored Normal file
View File

@ -0,0 +1,3 @@
[
"hello"
]

View File

@ -0,0 +1 @@
std.reverse(["hello"])