decode_test.go 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. // Go support for Protocol Buffers - Google's data interchange format
  2. //
  3. // Copyright 2010 The Go Authors. All rights reserved.
  4. // https://github.com/golang/protobuf
  5. //
  6. // Redistribution and use in source and binary forms, with or without
  7. // modification, are permitted provided that the following conditions are
  8. // met:
  9. //
  10. // * Redistributions of source code must retain the above copyright
  11. // notice, this list of conditions and the following disclaimer.
  12. // * Redistributions in binary form must reproduce the above
  13. // copyright notice, this list of conditions and the following disclaimer
  14. // in the documentation and/or other materials provided with the
  15. // distribution.
  16. // * Neither the name of Google Inc. nor the names of its
  17. // contributors may be used to endorse or promote products derived from
  18. // this software without specific prior written permission.
  19. //
  20. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  23. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  24. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  25. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  26. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  27. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  28. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  29. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  30. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. // +build go1.7
  32. package proto_test
  33. import (
  34. "testing"
  35. "github.com/gogo/protobuf/proto"
  36. tpb "github.com/gogo/protobuf/proto/proto3_proto"
  37. )
  38. var (
  39. bytesBlackhole []byte
  40. msgBlackhole = new(tpb.Message)
  41. )
  42. // Disabled this Benchmark because it is using features (b.Run) from go1.7 and gogoprotobuf still have compatibility with go1.5
  43. // BenchmarkVarint32ArraySmall shows the performance on an array of small int32 fields (1 and
  44. // 2 bytes long).
  45. // func BenchmarkVarint32ArraySmall(b *testing.B) {
  46. // for i := uint(1); i <= 10; i++ {
  47. // dist := genInt32Dist([7]int{0, 3, 1}, 1<<i)
  48. // raw, err := proto.Marshal(&tpb.Message{
  49. // ShortKey: dist,
  50. // })
  51. // if err != nil {
  52. // b.Error("wrong encode", err)
  53. // }
  54. // b.Run(fmt.Sprintf("Len%v", len(dist)), func(b *testing.B) {
  55. // scratchBuf := proto.NewBuffer(nil)
  56. // b.ResetTimer()
  57. // for k := 0; k < b.N; k++ {
  58. // scratchBuf.SetBuf(raw)
  59. // msgBlackhole.Reset()
  60. // if err := scratchBuf.Unmarshal(msgBlackhole); err != nil {
  61. // b.Error("wrong decode", err)
  62. // }
  63. // }
  64. // })
  65. // }
  66. // }
  67. // Disabled this Benchmark because it is using features (b.Run) from go1.7 and gogoprotobuf still have compatibility with go1.5
  68. // BenchmarkVarint32ArrayLarge shows the performance on an array of large int32 fields (3 and
  69. // 4 bytes long, with a small number of 1, 2, 5 and 10 byte long versions).
  70. // func BenchmarkVarint32ArrayLarge(b *testing.B) {
  71. // for i := uint(1); i <= 10; i++ {
  72. // dist := genInt32Dist([7]int{0, 1, 2, 4, 8, 1, 1}, 1<<i)
  73. // raw, err := proto.Marshal(&tpb.Message{
  74. // ShortKey: dist,
  75. // })
  76. // if err != nil {
  77. // b.Error("wrong encode", err)
  78. // }
  79. // b.Run(fmt.Sprintf("Len%v", len(dist)), func(b *testing.B) {
  80. // scratchBuf := proto.NewBuffer(nil)
  81. // b.ResetTimer()
  82. // for k := 0; k < b.N; k++ {
  83. // scratchBuf.SetBuf(raw)
  84. // msgBlackhole.Reset()
  85. // if err := scratchBuf.Unmarshal(msgBlackhole); err != nil {
  86. // b.Error("wrong decode", err)
  87. // }
  88. // }
  89. // })
  90. // }
  91. // }
  92. // Disabled this Benchmark because it is using features (b.Run) from go1.7 and gogoprotobuf still have compatibility with go1.5
  93. // BenchmarkVarint64ArraySmall shows the performance on an array of small int64 fields (1 and
  94. // 2 bytes long).
  95. // func BenchmarkVarint64ArraySmall(b *testing.B) {
  96. // for i := uint(1); i <= 10; i++ {
  97. // dist := genUint64Dist([11]int{0, 3, 1}, 1<<i)
  98. // raw, err := proto.Marshal(&tpb.Message{
  99. // Key: dist,
  100. // })
  101. // if err != nil {
  102. // b.Error("wrong encode", err)
  103. // }
  104. // b.Run(fmt.Sprintf("Len%v", len(dist)), func(b *testing.B) {
  105. // scratchBuf := proto.NewBuffer(nil)
  106. // b.ResetTimer()
  107. // for k := 0; k < b.N; k++ {
  108. // scratchBuf.SetBuf(raw)
  109. // msgBlackhole.Reset()
  110. // if err := scratchBuf.Unmarshal(msgBlackhole); err != nil {
  111. // b.Error("wrong decode", err)
  112. // }
  113. // }
  114. // })
  115. // }
  116. // }
  117. // Disabled this Benchmark because it is using features (b.Run) from go1.7 and gogoprotobuf still have compatibility with go1.5
  118. // BenchmarkVarint64ArrayLarge shows the performance on an array of large int64 fields (6, 7,
  119. // and 8 bytes long with a small number of the other sizes).
  120. // func BenchmarkVarint64ArrayLarge(b *testing.B) {
  121. // for i := uint(1); i <= 10; i++ {
  122. // dist := genUint64Dist([11]int{0, 1, 1, 2, 4, 8, 16, 32, 16, 1, 1}, 1<<i)
  123. // raw, err := proto.Marshal(&tpb.Message{
  124. // Key: dist,
  125. // })
  126. // if err != nil {
  127. // b.Error("wrong encode", err)
  128. // }
  129. // b.Run(fmt.Sprintf("Len%v", len(dist)), func(b *testing.B) {
  130. // scratchBuf := proto.NewBuffer(nil)
  131. // b.ResetTimer()
  132. // for k := 0; k < b.N; k++ {
  133. // scratchBuf.SetBuf(raw)
  134. // msgBlackhole.Reset()
  135. // if err := scratchBuf.Unmarshal(msgBlackhole); err != nil {
  136. // b.Error("wrong decode", err)
  137. // }
  138. // }
  139. // })
  140. // }
  141. // }
  142. // Disabled this Benchmark because it is using features (b.Run) from go1.7 and gogoprotobuf still have compatibility with go1.5
  143. // BenchmarkVarint64ArrayMixed shows the performance of lots of small messages, each
  144. // containing a small number of large (3, 4, and 5 byte) repeated int64s.
  145. // func BenchmarkVarint64ArrayMixed(b *testing.B) {
  146. // for i := uint(1); i <= 1<<5; i <<= 1 {
  147. // dist := genUint64Dist([11]int{0, 0, 0, 4, 6, 4, 0, 0, 0, 0, 0}, int(i))
  148. // // number of sub fields
  149. // for k := uint(1); k <= 1<<10; k <<= 2 {
  150. // msg := &tpb.Message{}
  151. // for m := uint(0); m < k; m++ {
  152. // msg.Children = append(msg.Children, &tpb.Message{
  153. // Key: dist,
  154. // })
  155. // }
  156. // raw, err := proto.Marshal(msg)
  157. // if err != nil {
  158. // b.Error("wrong encode", err)
  159. // }
  160. // b.Run(fmt.Sprintf("Fields%vLen%v", k, i), func(b *testing.B) {
  161. // scratchBuf := proto.NewBuffer(nil)
  162. // b.ResetTimer()
  163. // for k := 0; k < b.N; k++ {
  164. // scratchBuf.SetBuf(raw)
  165. // msgBlackhole.Reset()
  166. // if err := scratchBuf.Unmarshal(msgBlackhole); err != nil {
  167. // b.Error("wrong decode", err)
  168. // }
  169. // }
  170. // })
  171. // }
  172. // }
  173. // }
  174. // genInt32Dist generates a slice of ints that will match the size distribution of dist.
  175. // A size of 6 corresponds to a max length varint32, which is 10 bytes. The distribution
  176. // is 1-indexed. (i.e. the value at index 1 is how many 1 byte ints to create).
  177. func genInt32Dist(dist [7]int, count int) (dest []int32) {
  178. for i := 0; i < count; i++ {
  179. for k := 0; k < len(dist); k++ {
  180. var num int32
  181. switch k {
  182. case 1:
  183. num = 1<<7 - 1
  184. case 2:
  185. num = 1<<14 - 1
  186. case 3:
  187. num = 1<<21 - 1
  188. case 4:
  189. num = 1<<28 - 1
  190. case 5:
  191. num = 1<<29 - 1
  192. case 6:
  193. num = -1
  194. }
  195. for m := 0; m < dist[k]; m++ {
  196. dest = append(dest, num)
  197. }
  198. }
  199. }
  200. return
  201. }
  202. // genUint64Dist generates a slice of ints that will match the size distribution of dist.
  203. // The distribution is 1-indexed. (i.e. the value at index 1 is how many 1 byte ints to create).
  204. func genUint64Dist(dist [11]int, count int) (dest []uint64) {
  205. for i := 0; i < count; i++ {
  206. for k := 0; k < len(dist); k++ {
  207. var num uint64
  208. switch k {
  209. case 1:
  210. num = 1<<7 - 1
  211. case 2:
  212. num = 1<<14 - 1
  213. case 3:
  214. num = 1<<21 - 1
  215. case 4:
  216. num = 1<<28 - 1
  217. case 5:
  218. num = 1<<35 - 1
  219. case 6:
  220. num = 1<<42 - 1
  221. case 7:
  222. num = 1<<49 - 1
  223. case 8:
  224. num = 1<<56 - 1
  225. case 9:
  226. num = 1<<63 - 1
  227. case 10:
  228. num = 1<<64 - 1
  229. }
  230. for m := 0; m < dist[k]; m++ {
  231. dest = append(dest, num)
  232. }
  233. }
  234. }
  235. return
  236. }
  237. // BenchmarkDecodeEmpty measures the overhead of doing the minimal possible decode.
  238. func BenchmarkDecodeEmpty(b *testing.B) {
  239. raw, err := proto.Marshal(&tpb.Message{})
  240. if err != nil {
  241. b.Error("wrong encode", err)
  242. }
  243. b.ResetTimer()
  244. for i := 0; i < b.N; i++ {
  245. if err := proto.Unmarshal(raw, msgBlackhole); err != nil {
  246. b.Error("wrong decode", err)
  247. }
  248. }
  249. }