Skip to content

Commit 3b58014

Browse files
ghostsquadsbarzowski
authored andcommitted
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 google#111
1 parent 27b4c60 commit 3b58014

13 files changed

+64
-2
lines changed

builtin-benchmarks/reverse.jsonnet

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
foo: [
3+
std.reverse(std.range(0, 5000)) for i in std.range(0,100)
4+
],
5+
}

builtins.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,23 @@ func builtinJoin(i *interpreter, trace traceElement, sep, arrv value) (value, er
345345
}
346346
}
347347

348+
func builtinReverse(i *interpreter, trace traceElement, arrv value) (value, error) {
349+
arr, err := i.getArray(arrv, trace)
350+
if err != nil {
351+
return nil, err
352+
}
353+
354+
lenArr := len(arr.elements) // lenx holds the original array length
355+
reversed_array := make([]*cachedThunk, lenArr) // creates a slice that refer to a new array of length lenx
356+
357+
for i := 0; i < lenArr; i++ {
358+
j := lenArr - (i + 1) // j initially holds (lenx - 1) and decreases to 0 while i initially holds 0 and increase to (lenx - 1)
359+
reversed_array[i] = arr.elements[j]
360+
}
361+
362+
return makeValueArray(reversed_array), nil
363+
}
364+
348365
func builtinFilter(i *interpreter, trace traceElement, funcv, arrv value) (value, error) {
349366
arr, err := i.getArray(arrv, trace)
350367
if err != nil {
@@ -1271,6 +1288,7 @@ var funcBuiltins = buildBuiltinMap([]builtin{
12711288
&binaryBuiltin{name: "makeArray", function: builtinMakeArray, parameters: ast.Identifiers{"sz", "func"}},
12721289
&binaryBuiltin{name: "flatMap", function: builtinFlatMap, parameters: ast.Identifiers{"func", "arr"}},
12731290
&binaryBuiltin{name: "join", function: builtinJoin, parameters: ast.Identifiers{"sep", "arr"}},
1291+
&unaryBuiltin{name: "reverse", function: builtinReverse, parameters: ast.Identifiers{"arr"}},
12741292
&binaryBuiltin{name: "filter", function: builtinFilter, parameters: ast.Identifiers{"func", "arr"}},
12751293
&binaryBuiltin{name: "range", function: builtinRange, parameters: ast.Identifiers{"from", "to"}},
12761294
&binaryBuiltin{name: "primitiveEquals", function: primitiveEquals, parameters: ast.Identifiers{"x", "y"}},

builtins_benchmark_test.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package jsonnet
22

33
import (
44
"flag"
5+
"fmt"
56
"os"
67
"os/exec"
78
"testing"
@@ -15,9 +16,9 @@ func init() {
1516
flag.BoolVar(&outputPassthru, "outputPassthru", false, "Pass stdout/err from jsonnet")
1617
}
1718

18-
func Benchmark_Builtin_substr(b *testing.B) {
19+
func RunBenchmark(b *testing.B, name string) {
1920
for n := 0; n < b.N; n++ {
20-
cmd := exec.Command(jsonnetPath, "./builtin-benchmarks/substr.jsonnet")
21+
cmd := exec.Command(jsonnetPath, fmt.Sprintf("./builtin-benchmarks/%s.jsonnet", name))
2122
if outputPassthru {
2223
cmd.Stdout = os.Stdout
2324
cmd.Stderr = os.Stderr
@@ -29,3 +30,11 @@ func Benchmark_Builtin_substr(b *testing.B) {
2930
}
3031
}
3132
}
33+
34+
func Benchmark_Builtin_substr(b *testing.B) {
35+
RunBenchmark(b, "substr")
36+
}
37+
38+
func Benchmark_Builtin_reverse(b *testing.B) {
39+
RunBenchmark(b, "reverse")
40+
}

testdata/builtinReverse.golden

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[
2+
2,
3+
1
4+
]

testdata/builtinReverse.jsonnet

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
std.reverse([1, 2])

testdata/builtinReverse_empty.golden

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[ ]

testdata/builtinReverse_empty.jsonnet

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
std.reverse([])

testdata/builtinReverse_many.golden

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[
2+
"tester",
3+
"is",
4+
"name",
5+
"my",
6+
"hello"
7+
]

testdata/builtinReverse_many.jsonnet

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
std.reverse(["hello", "my", "name", "is", "tester"])
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
RUNTIME ERROR: Unexpected type string, expected array
2+
-------------------------------------------------
3+
testdata/builtinReverse_not_array:1:1-20 builtin function <reverse>
4+
5+
std.reverse("asdf")
6+
7+
-------------------------------------------------
8+
During evaluation
9+
10+
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
std.reverse("asdf")

testdata/builtinReverse_single.golden

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[
2+
"hello"
3+
]
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
std.reverse(["hello"])

0 commit comments

Comments
 (0)