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.
 
 
 

215 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. // +build go1.7
  15. package spanner
  16. import (
  17. "reflect"
  18. "strconv"
  19. "testing"
  20. "cloud.google.com/go/civil"
  21. proto3 "github.com/golang/protobuf/ptypes/struct"
  22. sppb "google.golang.org/genproto/googleapis/spanner/v1"
  23. )
  24. func BenchmarkEncodeIntArray(b *testing.B) {
  25. for _, s := range []struct {
  26. name string
  27. f func(a []int) (*proto3.Value, *sppb.Type, error)
  28. }{
  29. {"Orig", encodeIntArrayOrig},
  30. {"Func", encodeIntArrayFunc},
  31. {"Reflect", encodeIntArrayReflect},
  32. } {
  33. b.Run(s.name, func(b *testing.B) {
  34. for _, size := range []int{1, 10, 100, 1000} {
  35. a := make([]int, size)
  36. b.Run(strconv.Itoa(size), func(b *testing.B) {
  37. for i := 0; i < b.N; i++ {
  38. s.f(a)
  39. }
  40. })
  41. }
  42. })
  43. }
  44. }
  45. func encodeIntArrayOrig(a []int) (*proto3.Value, *sppb.Type, error) {
  46. vs := make([]*proto3.Value, len(a))
  47. var err error
  48. for i := range a {
  49. vs[i], _, err = encodeValue(a[i])
  50. if err != nil {
  51. return nil, nil, err
  52. }
  53. }
  54. return listProto(vs...), listType(intType()), nil
  55. }
  56. func encodeIntArrayFunc(a []int) (*proto3.Value, *sppb.Type, error) {
  57. v, err := encodeArray(len(a), func(i int) interface{} { return a[i] })
  58. if err != nil {
  59. return nil, nil, err
  60. }
  61. return v, listType(intType()), nil
  62. }
  63. func encodeIntArrayReflect(a []int) (*proto3.Value, *sppb.Type, error) {
  64. v, err := encodeArrayReflect(a)
  65. if err != nil {
  66. return nil, nil, err
  67. }
  68. return v, listType(intType()), nil
  69. }
  70. func encodeArrayReflect(a interface{}) (*proto3.Value, error) {
  71. va := reflect.ValueOf(a)
  72. len := va.Len()
  73. vs := make([]*proto3.Value, len)
  74. var err error
  75. for i := 0; i < len; i++ {
  76. vs[i], _, err = encodeValue(va.Index(i).Interface())
  77. if err != nil {
  78. return nil, err
  79. }
  80. }
  81. return listProto(vs...), nil
  82. }
  83. func BenchmarkDecodeGeneric(b *testing.B) {
  84. v := stringProto("test")
  85. t := stringType()
  86. var g GenericColumnValue
  87. b.ResetTimer()
  88. for i := 0; i < b.N; i++ {
  89. decodeValue(v, t, &g)
  90. }
  91. }
  92. func BenchmarkDecodeArray(b *testing.B) {
  93. for _, size := range []int{1, 10, 100, 1000} {
  94. vals := make([]*proto3.Value, size)
  95. for i := 0; i < size; i++ {
  96. vals[i] = dateProto(d1)
  97. }
  98. lv := &proto3.ListValue{Values: vals}
  99. b.Run(strconv.Itoa(size), func(b *testing.B) {
  100. for _, s := range []struct {
  101. name string
  102. decode func(*proto3.ListValue)
  103. }{
  104. {"DateDirect", decodeArray_Date_direct},
  105. {"DateFunc", decodeArray_Date_func},
  106. {"DateReflect", decodeArray_Date_reflect},
  107. {"StringDecodeStringArray", decodeStringArrayWrap},
  108. {"StringDirect", decodeArray_String_direct},
  109. {"StringFunc", decodeArray_String_func},
  110. {"StringReflect", decodeArray_String_reflect},
  111. } {
  112. b.Run(s.name, func(b *testing.B) {
  113. for i := 0; i < b.N; i++ {
  114. s.decode(lv)
  115. }
  116. })
  117. }
  118. })
  119. }
  120. }
  121. func decodeArray_Date_direct(pb *proto3.ListValue) {
  122. a := make([]civil.Date, len(pb.Values))
  123. t := dateType()
  124. for i, v := range pb.Values {
  125. if err := decodeValue(v, t, &a[i]); err != nil {
  126. panic(err)
  127. }
  128. }
  129. }
  130. func decodeArray_Date_func(pb *proto3.ListValue) {
  131. a := make([]civil.Date, len(pb.Values))
  132. if err := decodeArray_func(pb, "DATE", dateType(), func(i int) interface{} { return &a[i] }); err != nil {
  133. panic(err)
  134. }
  135. }
  136. func decodeArray_Date_reflect(pb *proto3.ListValue) {
  137. var a []civil.Date
  138. if err := decodeArray_reflect(pb, "DATE", dateType(), &a); err != nil {
  139. panic(err)
  140. }
  141. }
  142. func decodeStringArrayWrap(pb *proto3.ListValue) {
  143. if _, err := decodeStringArray(pb); err != nil {
  144. panic(err)
  145. }
  146. }
  147. func decodeArray_String_direct(pb *proto3.ListValue) {
  148. a := make([]string, len(pb.Values))
  149. t := stringType()
  150. for i, v := range pb.Values {
  151. if err := decodeValue(v, t, &a[i]); err != nil {
  152. panic(err)
  153. }
  154. }
  155. }
  156. func decodeArray_String_func(pb *proto3.ListValue) {
  157. a := make([]string, len(pb.Values))
  158. if err := decodeArray_func(pb, "STRING", stringType(), func(i int) interface{} { return &a[i] }); err != nil {
  159. panic(err)
  160. }
  161. }
  162. func decodeArray_String_reflect(pb *proto3.ListValue) {
  163. var a []string
  164. if err := decodeArray_reflect(pb, "STRING", stringType(), &a); err != nil {
  165. panic(err)
  166. }
  167. }
  168. func decodeArray_func(pb *proto3.ListValue, name string, typ *sppb.Type, elptr func(int) interface{}) error {
  169. if pb == nil {
  170. return errNilListValue(name)
  171. }
  172. for i, v := range pb.Values {
  173. if err := decodeValue(v, typ, elptr(i)); err != nil {
  174. return errDecodeArrayElement(i, v, name, err)
  175. }
  176. }
  177. return nil
  178. }
  179. func decodeArray_reflect(pb *proto3.ListValue, name string, typ *sppb.Type, aptr interface{}) error {
  180. if pb == nil {
  181. return errNilListValue(name)
  182. }
  183. av := reflect.ValueOf(aptr).Elem()
  184. av.Set(reflect.MakeSlice(av.Type(), len(pb.Values), len(pb.Values)))
  185. for i, v := range pb.Values {
  186. if err := decodeValue(v, typ, av.Index(i).Addr().Interface()); err != nil {
  187. av.Set(reflect.Zero(av.Type())) // reset slice to nil
  188. return errDecodeArrayElement(i, v, name, err)
  189. }
  190. }
  191. return nil
  192. }