benchmark_test.go 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  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. snap := benchS.Snapshot()
  119. snap.WithNeed(protocol.LocalDeviceID, func(fi db.FileIntf) bool {
  120. count++
  121. return true
  122. })
  123. snap.Release()
  124. if count != len(secondHalf) {
  125. b.Errorf("wrong length %d != %d", count, len(secondHalf))
  126. }
  127. }
  128. b.ReportAllocs()
  129. }
  130. func BenchmarkNeedHalfRemote(b *testing.B) {
  131. ldb := db.NewLowlevel(backend.OpenMemory())
  132. defer ldb.Close()
  133. fset := db.NewFileSet("test)", fs.NewFilesystem(fs.FilesystemTypeBasic, "."), ldb)
  134. replace(fset, remoteDevice0, firstHalf)
  135. replace(fset, protocol.LocalDeviceID, files)
  136. b.ResetTimer()
  137. for i := 0; i < b.N; i++ {
  138. count := 0
  139. snap := fset.Snapshot()
  140. snap.WithNeed(remoteDevice0, func(fi db.FileIntf) bool {
  141. count++
  142. return true
  143. })
  144. snap.Release()
  145. if count != len(secondHalf) {
  146. b.Errorf("wrong length %d != %d", count, len(secondHalf))
  147. }
  148. }
  149. b.ReportAllocs()
  150. }
  151. func BenchmarkHave(b *testing.B) {
  152. ldb, benchS := getBenchFileSet()
  153. defer ldb.Close()
  154. b.ResetTimer()
  155. for i := 0; i < b.N; i++ {
  156. count := 0
  157. snap := benchS.Snapshot()
  158. snap.WithHave(protocol.LocalDeviceID, func(fi db.FileIntf) bool {
  159. count++
  160. return true
  161. })
  162. snap.Release()
  163. if count != len(firstHalf) {
  164. b.Errorf("wrong length %d != %d", count, len(firstHalf))
  165. }
  166. }
  167. b.ReportAllocs()
  168. }
  169. func BenchmarkGlobal(b *testing.B) {
  170. ldb, benchS := getBenchFileSet()
  171. defer ldb.Close()
  172. b.ResetTimer()
  173. for i := 0; i < b.N; i++ {
  174. count := 0
  175. snap := benchS.Snapshot()
  176. snap.WithGlobal(func(fi db.FileIntf) bool {
  177. count++
  178. return true
  179. })
  180. snap.Release()
  181. if count != len(files) {
  182. b.Errorf("wrong length %d != %d", count, len(files))
  183. }
  184. }
  185. b.ReportAllocs()
  186. }
  187. func BenchmarkNeedHalfTruncated(b *testing.B) {
  188. ldb, benchS := getBenchFileSet()
  189. defer ldb.Close()
  190. b.ResetTimer()
  191. for i := 0; i < b.N; i++ {
  192. count := 0
  193. snap := benchS.Snapshot()
  194. snap.WithNeedTruncated(protocol.LocalDeviceID, func(fi db.FileIntf) bool {
  195. count++
  196. return true
  197. })
  198. snap.Release()
  199. if count != len(secondHalf) {
  200. b.Errorf("wrong length %d != %d", count, len(secondHalf))
  201. }
  202. }
  203. b.ReportAllocs()
  204. }
  205. func BenchmarkHaveTruncated(b *testing.B) {
  206. ldb, benchS := getBenchFileSet()
  207. defer ldb.Close()
  208. b.ResetTimer()
  209. for i := 0; i < b.N; i++ {
  210. count := 0
  211. snap := benchS.Snapshot()
  212. snap.WithHaveTruncated(protocol.LocalDeviceID, func(fi db.FileIntf) bool {
  213. count++
  214. return true
  215. })
  216. snap.Release()
  217. if count != len(firstHalf) {
  218. b.Errorf("wrong length %d != %d", count, len(firstHalf))
  219. }
  220. }
  221. b.ReportAllocs()
  222. }
  223. func BenchmarkGlobalTruncated(b *testing.B) {
  224. ldb, benchS := getBenchFileSet()
  225. defer ldb.Close()
  226. b.ResetTimer()
  227. for i := 0; i < b.N; i++ {
  228. count := 0
  229. snap := benchS.Snapshot()
  230. snap.WithGlobalTruncated(func(fi db.FileIntf) bool {
  231. count++
  232. return true
  233. })
  234. snap.Release()
  235. if count != len(files) {
  236. b.Errorf("wrong length %d != %d", count, len(files))
  237. }
  238. }
  239. b.ReportAllocs()
  240. }