timing_test.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. package fasttemplate
  2. import (
  3. "bytes"
  4. "io"
  5. "net/url"
  6. "strings"
  7. "testing"
  8. "text/template"
  9. )
  10. var (
  11. source = "http://{{uid}}.foo.bar.com/?cb={{cb}}{{width}}&width={{width}}&height={{height}}&timeout={{timeout}}&uid={{uid}}&subid={{subid}}&ref={{ref}}"
  12. result = "http://aaasdf.foo.bar.com/?cb=12341232&width=1232&height=123&timeout=123123&uid=aaasdf&subid=asdfds&ref=http://google.com/aaa/bbb/ccc"
  13. resultEscaped = "http://aaasdf.foo.bar.com/?cb=12341232&width=1232&height=123&timeout=123123&uid=aaasdf&subid=asdfds&ref=http%3A%2F%2Fgoogle.com%2Faaa%2Fbbb%2Fccc"
  14. resultBytes = []byte(result)
  15. resultEscapedBytes = []byte(resultEscaped)
  16. m = map[string]interface{}{
  17. "cb": []byte("1234"),
  18. "width": []byte("1232"),
  19. "height": []byte("123"),
  20. "timeout": []byte("123123"),
  21. "uid": []byte("aaasdf"),
  22. "subid": []byte("asdfds"),
  23. "ref": []byte("http://google.com/aaa/bbb/ccc"),
  24. }
  25. )
  26. func map2slice(m map[string]interface{}) []string {
  27. var a []string
  28. for k, v := range m {
  29. a = append(a, "{{"+k+"}}", string(v.([]byte)))
  30. }
  31. return a
  32. }
  33. func BenchmarkStringsReplace(b *testing.B) {
  34. mSlice := map2slice(m)
  35. b.ResetTimer()
  36. b.RunParallel(func(pb *testing.PB) {
  37. for pb.Next() {
  38. x := source
  39. for i := 0; i < len(mSlice); i += 2 {
  40. x = strings.Replace(x, mSlice[i], mSlice[i+1], -1)
  41. }
  42. if x != result {
  43. b.Fatalf("Unexpected result\n%q\nExpected\n%q\n", x, result)
  44. }
  45. }
  46. })
  47. }
  48. func BenchmarkStringsReplacer(b *testing.B) {
  49. mSlice := map2slice(m)
  50. b.ResetTimer()
  51. b.RunParallel(func(pb *testing.PB) {
  52. for pb.Next() {
  53. r := strings.NewReplacer(mSlice...)
  54. x := r.Replace(source)
  55. if x != result {
  56. b.Fatalf("Unexpected result\n%q\nExpected\n%q\n", x, result)
  57. }
  58. }
  59. })
  60. }
  61. func BenchmarkTextTemplate(b *testing.B) {
  62. s := strings.Replace(source, "{{", "{{.", -1)
  63. t, err := template.New("test").Parse(s)
  64. if err != nil {
  65. b.Fatalf("Error when parsing template: %s", err)
  66. }
  67. mm := make(map[string]string)
  68. for k, v := range m {
  69. mm[k] = string(v.([]byte))
  70. }
  71. b.ResetTimer()
  72. b.RunParallel(func(pb *testing.PB) {
  73. var w bytes.Buffer
  74. for pb.Next() {
  75. if err := t.Execute(&w, mm); err != nil {
  76. b.Fatalf("error when executing template: %s", err)
  77. }
  78. x := w.Bytes()
  79. if !bytes.Equal(x, resultBytes) {
  80. b.Fatalf("unexpected result\n%q\nExpected\n%q\n", x, resultBytes)
  81. }
  82. w.Reset()
  83. }
  84. })
  85. }
  86. func BenchmarkFastTemplateExecuteFunc(b *testing.B) {
  87. t, err := NewTemplate(source, "{{", "}}")
  88. if err != nil {
  89. b.Fatalf("error in template: %s", err)
  90. }
  91. f := func(w io.Writer, tag string) (int, error) {
  92. return w.Write(m[tag].([]byte))
  93. }
  94. b.ResetTimer()
  95. b.RunParallel(func(pb *testing.PB) {
  96. var w bytes.Buffer
  97. for pb.Next() {
  98. if _, err := t.ExecuteFunc(&w, f); err != nil {
  99. b.Fatalf("unexpected error: %s", err)
  100. }
  101. x := w.Bytes()
  102. if !bytes.Equal(x, resultBytes) {
  103. b.Fatalf("unexpected result\n%q\nExpected\n%q\n", x, resultBytes)
  104. }
  105. w.Reset()
  106. }
  107. })
  108. }
  109. func BenchmarkFastTemplateExecute(b *testing.B) {
  110. t, err := NewTemplate(source, "{{", "}}")
  111. if err != nil {
  112. b.Fatalf("error in template: %s", err)
  113. }
  114. b.ResetTimer()
  115. b.RunParallel(func(pb *testing.PB) {
  116. var w bytes.Buffer
  117. for pb.Next() {
  118. if _, err := t.Execute(&w, m); err != nil {
  119. b.Fatalf("unexpected error: %s", err)
  120. }
  121. x := w.Bytes()
  122. if !bytes.Equal(x, resultBytes) {
  123. b.Fatalf("unexpected result\n%q\nExpected\n%q\n", x, resultBytes)
  124. }
  125. w.Reset()
  126. }
  127. })
  128. }
  129. func BenchmarkFastTemplateExecuteFuncString(b *testing.B) {
  130. t, err := NewTemplate(source, "{{", "}}")
  131. if err != nil {
  132. b.Fatalf("error in template: %s", err)
  133. }
  134. f := func(w io.Writer, tag string) (int, error) {
  135. return w.Write(m[tag].([]byte))
  136. }
  137. b.ResetTimer()
  138. b.RunParallel(func(pb *testing.PB) {
  139. for pb.Next() {
  140. x := t.ExecuteFuncString(f)
  141. if x != result {
  142. b.Fatalf("unexpected result\n%q\nExpected\n%q\n", x, result)
  143. }
  144. }
  145. })
  146. }
  147. func BenchmarkFastTemplateExecuteString(b *testing.B) {
  148. t, err := NewTemplate(source, "{{", "}}")
  149. if err != nil {
  150. b.Fatalf("error in template: %s", err)
  151. }
  152. b.ResetTimer()
  153. b.RunParallel(func(pb *testing.PB) {
  154. for pb.Next() {
  155. x := t.ExecuteString(m)
  156. if x != result {
  157. b.Fatalf("unexpected result\n%q\nExpected\n%q\n", x, result)
  158. }
  159. }
  160. })
  161. }
  162. func BenchmarkFastTemplateExecuteTagFunc(b *testing.B) {
  163. t, err := NewTemplate(source, "{{", "}}")
  164. if err != nil {
  165. b.Fatalf("error in template: %s", err)
  166. }
  167. mm := make(map[string]interface{})
  168. for k, v := range m {
  169. if k == "ref" {
  170. vv := v.([]byte)
  171. v = TagFunc(func(w io.Writer, tag string) (int, error) { return w.Write([]byte(url.QueryEscape(string(vv)))) })
  172. }
  173. mm[k] = v
  174. }
  175. b.ResetTimer()
  176. b.RunParallel(func(pb *testing.PB) {
  177. var w bytes.Buffer
  178. for pb.Next() {
  179. if _, err := t.Execute(&w, mm); err != nil {
  180. b.Fatalf("unexpected error: %s", err)
  181. }
  182. x := w.Bytes()
  183. if !bytes.Equal(x, resultEscapedBytes) {
  184. b.Fatalf("unexpected result\n%q\nExpected\n%q\n", x, resultEscapedBytes)
  185. }
  186. w.Reset()
  187. }
  188. })
  189. }