timing_test.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  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 BenchmarkFastTemplateExecute(b *testing.B) {
  87. t, err := NewTemplate(source, "{{", "}}")
  88. if err != nil {
  89. b.Fatalf("error in template: %s", err)
  90. }
  91. b.ResetTimer()
  92. b.RunParallel(func(pb *testing.PB) {
  93. var w bytes.Buffer
  94. for pb.Next() {
  95. if _, err := t.Execute(&w, m); err != nil {
  96. b.Fatalf("unexpected error: %s", err)
  97. }
  98. x := w.Bytes()
  99. if !bytes.Equal(x, resultBytes) {
  100. b.Fatalf("unexpected result\n%q\nExpected\n%q\n", x, resultBytes)
  101. }
  102. w.Reset()
  103. }
  104. })
  105. }
  106. func BenchmarkFastTemplateExecuteString(b *testing.B) {
  107. t, err := NewTemplate(source, "{{", "}}")
  108. if err != nil {
  109. b.Fatalf("error in template: %s", err)
  110. }
  111. b.ResetTimer()
  112. b.RunParallel(func(pb *testing.PB) {
  113. for pb.Next() {
  114. x := t.ExecuteString(m)
  115. if x != result {
  116. b.Fatalf("unexpected result\n%q\nExpected\n%q\n", x, result)
  117. }
  118. }
  119. })
  120. }
  121. func BenchmarkFastTemplateExecuteTagFunc(b *testing.B) {
  122. t, err := NewTemplate(source, "{{", "}}")
  123. if err != nil {
  124. b.Fatalf("error in template: %s", err)
  125. }
  126. mm := make(map[string]interface{})
  127. for k, v := range m {
  128. if k == "ref" {
  129. vv := v.([]byte)
  130. v = TagFunc(func(w io.Writer) (int, error) { return w.Write([]byte(url.QueryEscape(string(vv)))) })
  131. }
  132. mm[k] = v
  133. }
  134. b.ResetTimer()
  135. b.RunParallel(func(pb *testing.PB) {
  136. var w bytes.Buffer
  137. for pb.Next() {
  138. if _, err := t.Execute(&w, mm); err != nil {
  139. b.Fatalf("unexpected error: %s", err)
  140. }
  141. x := w.Bytes()
  142. if !bytes.Equal(x, resultEscapedBytes) {
  143. b.Fatalf("unexpected result\n%q\nExpected\n%q\n", x, resultEscapedBytes)
  144. }
  145. w.Reset()
  146. }
  147. })
  148. }