benchmark_test.go 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  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. "testing"
  10. "github.com/syncthing/syncthing/lib/db"
  11. "github.com/syncthing/syncthing/lib/db/backend"
  12. "github.com/syncthing/syncthing/lib/fs"
  13. "github.com/syncthing/syncthing/lib/protocol"
  14. )
  15. var files, oneFile, firstHalf, secondHalf []protocol.FileInfo
  16. func lazyInitBenchFiles() {
  17. if files != nil {
  18. return
  19. }
  20. files = make([]protocol.FileInfo, 0, 1000)
  21. for i := 0; i < 1000; i++ {
  22. files = append(files, protocol.FileInfo{
  23. Name: fmt.Sprintf("file%d", i),
  24. Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1000}}},
  25. Blocks: genBlocks(i),
  26. })
  27. }
  28. middle := len(files) / 2
  29. firstHalf = files[:middle]
  30. secondHalf = files[middle:]
  31. oneFile = firstHalf[middle-1 : middle]
  32. }
  33. func getBenchFileSet() (*db.Lowlevel, *db.FileSet) {
  34. lazyInitBenchFiles()
  35. ldb := db.NewLowlevel(backend.OpenMemory())
  36. benchS := db.NewFileSet("test)", fs.NewFilesystem(fs.FilesystemTypeBasic, "."), ldb)
  37. replace(benchS, remoteDevice0, files)
  38. replace(benchS, protocol.LocalDeviceID, firstHalf)
  39. return ldb, benchS
  40. }
  41. func BenchmarkReplaceAll(b *testing.B) {
  42. ldb := db.NewLowlevel(backend.OpenMemory())
  43. defer ldb.Close()
  44. b.ResetTimer()
  45. for i := 0; i < b.N; i++ {
  46. m := db.NewFileSet("test)", fs.NewFilesystem(fs.FilesystemTypeBasic, "."), ldb)
  47. replace(m, protocol.LocalDeviceID, files)
  48. }
  49. b.ReportAllocs()
  50. }
  51. func BenchmarkUpdateOneChanged(b *testing.B) {
  52. ldb, benchS := getBenchFileSet()
  53. defer ldb.Close()
  54. changed := make([]protocol.FileInfo, 1)
  55. changed[0] = oneFile[0]
  56. changed[0].Version = changed[0].Version.Copy().Update(myID)
  57. b.ResetTimer()
  58. for i := 0; i < b.N; i++ {
  59. if i%2 == 0 {
  60. benchS.Update(protocol.LocalDeviceID, changed)
  61. } else {
  62. benchS.Update(protocol.LocalDeviceID, oneFile)
  63. }
  64. }
  65. b.ReportAllocs()
  66. }
  67. func BenchmarkUpdate100Changed(b *testing.B) {
  68. ldb, benchS := getBenchFileSet()
  69. defer ldb.Close()
  70. unchanged := files[100:200]
  71. changed := append([]protocol.FileInfo{}, unchanged...)
  72. for i := range changed {
  73. changed[i].Version = changed[i].Version.Copy().Update(myID)
  74. }
  75. b.ResetTimer()
  76. for i := 0; i < b.N; i++ {
  77. if i%2 == 0 {
  78. benchS.Update(protocol.LocalDeviceID, changed)
  79. } else {
  80. benchS.Update(protocol.LocalDeviceID, unchanged)
  81. }
  82. }
  83. b.ReportAllocs()
  84. }
  85. func BenchmarkUpdate100ChangedRemote(b *testing.B) {
  86. ldb, benchS := getBenchFileSet()
  87. defer ldb.Close()
  88. unchanged := files[100:200]
  89. changed := append([]protocol.FileInfo{}, unchanged...)
  90. for i := range changed {
  91. changed[i].Version = changed[i].Version.Copy().Update(myID)
  92. }
  93. b.ResetTimer()
  94. for i := 0; i < b.N; i++ {
  95. if i%2 == 0 {
  96. benchS.Update(remoteDevice0, changed)
  97. } else {
  98. benchS.Update(remoteDevice0, unchanged)
  99. }
  100. }
  101. b.ReportAllocs()
  102. }
  103. func BenchmarkUpdateOneUnchanged(b *testing.B) {
  104. ldb, benchS := getBenchFileSet()
  105. defer ldb.Close()
  106. b.ResetTimer()
  107. for i := 0; i < b.N; i++ {
  108. benchS.Update(protocol.LocalDeviceID, oneFile)
  109. }
  110. b.ReportAllocs()
  111. }
  112. func BenchmarkNeedHalf(b *testing.B) {
  113. ldb, benchS := getBenchFileSet()
  114. defer ldb.Close()
  115. b.ResetTimer()
  116. for i := 0; i < b.N; i++ {
  117. count := 0
  118. benchS.WithNeed(protocol.LocalDeviceID, func(fi db.FileIntf) bool {
  119. count++
  120. return true
  121. })
  122. if count != len(secondHalf) {
  123. b.Errorf("wrong length %d != %d", count, len(secondHalf))
  124. }
  125. }
  126. b.ReportAllocs()
  127. }
  128. func BenchmarkNeedHalfRemote(b *testing.B) {
  129. ldb := db.NewLowlevel(backend.OpenMemory())
  130. defer ldb.Close()
  131. fset := db.NewFileSet("test)", fs.NewFilesystem(fs.FilesystemTypeBasic, "."), ldb)
  132. replace(fset, remoteDevice0, firstHalf)
  133. replace(fset, protocol.LocalDeviceID, files)
  134. b.ResetTimer()
  135. for i := 0; i < b.N; i++ {
  136. count := 0
  137. fset.WithNeed(remoteDevice0, 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 BenchmarkHave(b *testing.B) {
  148. ldb, benchS := getBenchFileSet()
  149. defer ldb.Close()
  150. b.ResetTimer()
  151. for i := 0; i < b.N; i++ {
  152. count := 0
  153. benchS.WithHave(protocol.LocalDeviceID, func(fi db.FileIntf) bool {
  154. count++
  155. return true
  156. })
  157. if count != len(firstHalf) {
  158. b.Errorf("wrong length %d != %d", count, len(firstHalf))
  159. }
  160. }
  161. b.ReportAllocs()
  162. }
  163. func BenchmarkGlobal(b *testing.B) {
  164. ldb, benchS := getBenchFileSet()
  165. defer ldb.Close()
  166. b.ResetTimer()
  167. for i := 0; i < b.N; i++ {
  168. count := 0
  169. benchS.WithGlobal(func(fi db.FileIntf) bool {
  170. count++
  171. return true
  172. })
  173. if count != len(files) {
  174. b.Errorf("wrong length %d != %d", count, len(files))
  175. }
  176. }
  177. b.ReportAllocs()
  178. }
  179. func BenchmarkNeedHalfTruncated(b *testing.B) {
  180. ldb, benchS := getBenchFileSet()
  181. defer ldb.Close()
  182. b.ResetTimer()
  183. for i := 0; i < b.N; i++ {
  184. count := 0
  185. benchS.WithNeedTruncated(protocol.LocalDeviceID, func(fi db.FileIntf) bool {
  186. count++
  187. return true
  188. })
  189. if count != len(secondHalf) {
  190. b.Errorf("wrong length %d != %d", count, len(secondHalf))
  191. }
  192. }
  193. b.ReportAllocs()
  194. }
  195. func BenchmarkHaveTruncated(b *testing.B) {
  196. ldb, benchS := getBenchFileSet()
  197. defer ldb.Close()
  198. b.ResetTimer()
  199. for i := 0; i < b.N; i++ {
  200. count := 0
  201. benchS.WithHaveTruncated(protocol.LocalDeviceID, func(fi db.FileIntf) bool {
  202. count++
  203. return true
  204. })
  205. if count != len(firstHalf) {
  206. b.Errorf("wrong length %d != %d", count, len(firstHalf))
  207. }
  208. }
  209. b.ReportAllocs()
  210. }
  211. func BenchmarkGlobalTruncated(b *testing.B) {
  212. ldb, benchS := getBenchFileSet()
  213. defer ldb.Close()
  214. b.ResetTimer()
  215. for i := 0; i < b.N; i++ {
  216. count := 0
  217. benchS.WithGlobalTruncated(func(fi db.FileIntf) bool {
  218. count++
  219. return true
  220. })
  221. if count != len(files) {
  222. b.Errorf("wrong length %d != %d", count, len(files))
  223. }
  224. }
  225. b.ReportAllocs()
  226. }