You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

212 lines
5.3 KiB

  1. // Copyright 2017 Google LLC
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package spanner
  15. import (
  16. "reflect"
  17. "strconv"
  18. "testing"
  19. "cloud.google.com/go/civil"
  20. proto3 "github.com/golang/protobuf/ptypes/struct"
  21. sppb "google.golang.org/genproto/googleapis/spanner/v1"
  22. )
  23. func BenchmarkEncodeIntArray(b *testing.B) {
  24. for _, s := range []struct {
  25. name string
  26. f func(a []int) (*proto3.Value, *sppb.Type, error)
  27. }{
  28. {"Orig", encodeIntArrayOrig},
  29. {"Func", encodeIntArrayFunc},
  30. {"Reflect", encodeIntArrayReflect},
  31. } {
  32. b.Run(s.name, func(b *testing.B) {
  33. for _, size := range []int{1, 10, 100, 1000} {
  34. a := make([]int, size)
  35. b.Run(strconv.Itoa(size), func(b *testing.B) {
  36. for i := 0; i < b.N; i++ {
  37. s.f(a)
  38. }
  39. })
  40. }
  41. })
  42. }
  43. }
  44. func encodeIntArrayOrig(a []int) (*proto3.Value, *sppb.Type, error) {
  45. vs := make([]*proto3.Value, len(a))
  46. var err error
  47. for i := range a {
  48. vs[i], _, err = encodeValue(a[i])
  49. if err != nil {
  50. return nil, nil, err
  51. }
  52. }
  53. return listProto(vs...), listType(intType()), nil
  54. }
  55. func encodeIntArrayFunc(a []int) (*proto3.Value, *sppb.Type, error) {
  56. v, err := encodeArray(len(a), func(i int) interface{} { return a[i] })
  57. if err != nil {
  58. return nil, nil, err
  59. }
  60. return v, listType(intType()), nil
  61. }
  62. func encodeIntArrayReflect(a []int) (*proto3.Value, *sppb.Type, error) {
  63. v, err := encodeArrayReflect(a)
  64. if err != nil {
  65. return nil, nil, err
  66. }
  67. return v, listType(intType()), nil
  68. }
  69. func encodeArrayReflect(a interface{}) (*proto3.Value, error) {
  70. va := reflect.ValueOf(a)
  71. len := va.Len()
  72. vs := make([]*proto3.Value, len)
  73. var err error
  74. for i := 0; i < len; i++ {
  75. vs[i], _, err = encodeValue(va.Index(i).Interface())
  76. if err != nil {
  77. return nil, err
  78. }
  79. }
  80. return listProto(vs...), nil
  81. }
  82. func BenchmarkDecodeGeneric(b *testing.B) {
  83. v := stringProto("test")
  84. t := stringType()
  85. var g GenericColumnValue
  86. b.ResetTimer()
  87. for i := 0; i < b.N; i++ {
  88. decodeValue(v, t, &g)
  89. }
  90. }
  91. func BenchmarkDecodeArray(b *testing.B) {
  92. for _, size := range []int{1, 10, 100, 1000} {
  93. vals := make([]*proto3.Value, size)
  94. for i := 0; i < size; i++ {
  95. vals[i] = dateProto(d1)
  96. }
  97. lv := &proto3.ListValue{Values: vals}
  98. b.Run(strconv.Itoa(size), func(b *testing.B) {
  99. for _, s := range []struct {
  100. name string
  101. decode func(*proto3.ListValue)
  102. }{
  103. {"DateDirect", decodeArrayDateDirect},
  104. {"DateFunc", decodeArrayDateFunc},
  105. {"DateReflect", decodeArrayDateReflect},
  106. {"StringDecodeStringArray", decodeStringArrayWrap},
  107. {"StringDirect", decodeArrayStringDirect},
  108. {"StringFunc", decodeArrayStringFunc},
  109. {"StringReflect", decodeArrayStringReflect},
  110. } {
  111. b.Run(s.name, func(b *testing.B) {
  112. for i := 0; i < b.N; i++ {
  113. s.decode(lv)
  114. }
  115. })
  116. }
  117. })
  118. }
  119. }
  120. func decodeArrayDateDirect(pb *proto3.ListValue) {
  121. a := make([]civil.Date, len(pb.Values))
  122. t := dateType()
  123. for i, v := range pb.Values {
  124. if err := decodeValue(v, t, &a[i]); err != nil {
  125. panic(err)
  126. }
  127. }
  128. }
  129. func decodeArrayDateFunc(pb *proto3.ListValue) {
  130. a := make([]civil.Date, len(pb.Values))
  131. if err := decodeArrayFunc(pb, "DATE", dateType(), func(i int) interface{} { return &a[i] }); err != nil {
  132. panic(err)
  133. }
  134. }
  135. func decodeArrayDateReflect(pb *proto3.ListValue) {
  136. var a []civil.Date
  137. if err := decodeArrayReflect(pb, "DATE", dateType(), &a); err != nil {
  138. panic(err)
  139. }
  140. }
  141. func decodeStringArrayWrap(pb *proto3.ListValue) {
  142. if _, err := decodeStringArray(pb); err != nil {
  143. panic(err)
  144. }
  145. }
  146. func decodeArrayStringDirect(pb *proto3.ListValue) {
  147. a := make([]string, len(pb.Values))
  148. t := stringType()
  149. for i, v := range pb.Values {
  150. if err := decodeValue(v, t, &a[i]); err != nil {
  151. panic(err)
  152. }
  153. }
  154. }
  155. func decodeArrayStringFunc(pb *proto3.ListValue) {
  156. a := make([]string, len(pb.Values))
  157. if err := decodeArrayFunc(pb, "STRING", stringType(), func(i int) interface{} { return &a[i] }); err != nil {
  158. panic(err)
  159. }
  160. }
  161. func decodeArrayStringReflect(pb *proto3.ListValue) {
  162. var a []string
  163. if err := decodeArrayReflect(pb, "STRING", stringType(), &a); err != nil {
  164. panic(err)
  165. }
  166. }
  167. func decodeArrayFunc(pb *proto3.ListValue, name string, typ *sppb.Type, elptr func(int) interface{}) error {
  168. if pb == nil {
  169. return errNilListValue(name)
  170. }
  171. for i, v := range pb.Values {
  172. if err := decodeValue(v, typ, elptr(i)); err != nil {
  173. return errDecodeArrayElement(i, v, name, err)
  174. }
  175. }
  176. return nil
  177. }
  178. func decodeArrayReflect(pb *proto3.ListValue, name string, typ *sppb.Type, aptr interface{}) error {
  179. if pb == nil {
  180. return errNilListValue(name)
  181. }
  182. av := reflect.ValueOf(aptr).Elem()
  183. av.Set(reflect.MakeSlice(av.Type(), len(pb.Values), len(pb.Values)))
  184. for i, v := range pb.Values {
  185. if err := decodeValue(v, typ, av.Index(i).Addr().Interface()); err != nil {
  186. av.Set(reflect.Zero(av.Type())) // reset slice to nil
  187. return errDecodeArrayElement(i, v, name, err)
  188. }
  189. }
  190. return nil
  191. }