benchmark_test.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. // Copyright (C) 2015 The Syncthing Authors.
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this file,
  5. // You can obtain one at https://mozilla.org/MPL/2.0/.
  6. package db_test
  7. import (
  8. "fmt"
  9. "io/ioutil"
  10. "os"
  11. "path/filepath"
  12. "testing"
  13. "github.com/syncthing/syncthing/lib/db"
  14. "github.com/syncthing/syncthing/lib/fs"
  15. "github.com/syncthing/syncthing/lib/protocol"
  16. )
  17. var files, oneFile, firstHalf, secondHalf []protocol.FileInfo
  18. var benchS *db.FileSet
  19. func lazyInitBenchFileSet() {
  20. if benchS != nil {
  21. return
  22. }
  23. for i := 0; i < 1000; i++ {
  24. files = append(files, protocol.FileInfo{
  25. Name: fmt.Sprintf("file%d", i),
  26. Version: protocol.Vector{[]protocol.Counter{{ID: myID, Value: 1000}}},
  27. Blocks: genBlocks(i),
  28. })
  29. }
  30. middle := len(files) / 2
  31. firstHalf = files[:middle]
  32. secondHalf = files[middle:]
  33. oneFile = firstHalf[middle-1 : middle]
  34. ldb, _ := tempDB()
  35. benchS = db.NewFileSet("test)", fs.NewFilesystem(fs.FilesystemTypeBasic, "."), ldb)
  36. replace(benchS, remoteDevice0, files)
  37. replace(benchS, protocol.LocalDeviceID, firstHalf)
  38. }
  39. func tempDB() (*db.Instance, string) {
  40. dir, err := ioutil.TempDir("", "syncthing")
  41. if err != nil {
  42. panic(err)
  43. }
  44. dbi, err := db.Open(filepath.Join(dir, "db"))
  45. if err != nil {
  46. panic(err)
  47. }
  48. return dbi, dir
  49. }
  50. func BenchmarkReplaceAll(b *testing.B) {
  51. ldb, dir := tempDB()
  52. defer func() {
  53. ldb.Close()
  54. os.RemoveAll(dir)
  55. }()
  56. b.ResetTimer()
  57. for i := 0; i < b.N; i++ {
  58. m := db.NewFileSet("test)", fs.NewFilesystem(fs.FilesystemTypeBasic, "."), ldb)
  59. replace(m, protocol.LocalDeviceID, files)
  60. }
  61. b.ReportAllocs()
  62. }
  63. func BenchmarkUpdateOneChanged(b *testing.B) {
  64. lazyInitBenchFileSet()
  65. changed := make([]protocol.FileInfo, 1)
  66. changed[0] = oneFile[0]
  67. changed[0].Version = changed[0].Version.Update(myID)
  68. changed[0].Blocks = genBlocks(len(changed[0].Blocks))
  69. b.ResetTimer()
  70. for i := 0; i < b.N; i++ {
  71. if i%1 == 0 {
  72. benchS.Update(protocol.LocalDeviceID, changed)
  73. } else {
  74. benchS.Update(protocol.LocalDeviceID, oneFile)
  75. }
  76. }
  77. b.ReportAllocs()
  78. }
  79. func BenchmarkUpdateOneUnchanged(b *testing.B) {
  80. lazyInitBenchFileSet()
  81. b.ResetTimer()
  82. for i := 0; i < b.N; i++ {
  83. benchS.Update(protocol.LocalDeviceID, oneFile)
  84. }
  85. b.ReportAllocs()
  86. }
  87. func BenchmarkNeedHalf(b *testing.B) {
  88. lazyInitBenchFileSet()
  89. b.ResetTimer()
  90. for i := 0; i < b.N; i++ {
  91. count := 0
  92. benchS.WithNeed(protocol.LocalDeviceID, func(fi db.FileIntf) bool {
  93. count++
  94. return true
  95. })
  96. if count != len(secondHalf) {
  97. b.Errorf("wrong length %d != %d", count, len(secondHalf))
  98. }
  99. }
  100. b.ReportAllocs()
  101. }
  102. func BenchmarkHave(b *testing.B) {
  103. lazyInitBenchFileSet()
  104. b.ResetTimer()
  105. for i := 0; i < b.N; i++ {
  106. count := 0
  107. benchS.WithHave(protocol.LocalDeviceID, func(fi db.FileIntf) bool {
  108. count++
  109. return true
  110. })
  111. if count != len(firstHalf) {
  112. b.Errorf("wrong length %d != %d", count, len(firstHalf))
  113. }
  114. }
  115. b.ReportAllocs()
  116. }
  117. func BenchmarkGlobal(b *testing.B) {
  118. lazyInitBenchFileSet()
  119. b.ResetTimer()
  120. for i := 0; i < b.N; i++ {
  121. count := 0
  122. benchS.WithGlobal(func(fi db.FileIntf) bool {
  123. count++
  124. return true
  125. })
  126. if count != len(files) {
  127. b.Errorf("wrong length %d != %d", count, len(files))
  128. }
  129. }
  130. b.ReportAllocs()
  131. }
  132. func BenchmarkNeedHalfTruncated(b *testing.B) {
  133. lazyInitBenchFileSet()
  134. b.ResetTimer()
  135. for i := 0; i < b.N; i++ {
  136. count := 0
  137. benchS.WithNeedTruncated(protocol.LocalDeviceID, func(fi db.FileIntf) bool {
  138. count++
  139. return true
  140. })
  141. if count != len(secondHalf) {
  142. b.Errorf("wrong length %d != %d", count, len(secondHalf))
  143. }
  144. }
  145. b.ReportAllocs()
  146. }
  147. func BenchmarkHaveTruncated(b *testing.B) {
  148. lazyInitBenchFileSet()
  149. b.ResetTimer()
  150. for i := 0; i < b.N; i++ {
  151. count := 0
  152. benchS.WithHaveTruncated(protocol.LocalDeviceID, func(fi db.FileIntf) bool {
  153. count++
  154. return true
  155. })
  156. if count != len(firstHalf) {
  157. b.Errorf("wrong length %d != %d", count, len(firstHalf))
  158. }
  159. }
  160. b.ReportAllocs()
  161. }
  162. func BenchmarkGlobalTruncated(b *testing.B) {
  163. lazyInitBenchFileSet()
  164. b.ResetTimer()
  165. for i := 0; i < b.N; i++ {
  166. count := 0
  167. benchS.WithGlobalTruncated(func(fi db.FileIntf) bool {
  168. count++
  169. return true
  170. })
  171. if count != len(files) {
  172. b.Errorf("wrong length %d != %d", count, len(files))
  173. }
  174. }
  175. b.ReportAllocs()
  176. }