benchmark_test.go 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  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, filesUpdated, oneFile, firstHalf, secondHalf, changed100, unchanged100 []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. unchanged100 := files[100:200]
  33. changed100 := append([]protocol.FileInfo{}, unchanged100...)
  34. for i := range changed100 {
  35. changed100[i].Version = changed100[i].Version.Copy().Update(myID)
  36. }
  37. }
  38. func getBenchFileSet() (*db.Lowlevel, *db.FileSet) {
  39. lazyInitBenchFiles()
  40. ldb := db.NewLowlevel(backend.OpenMemory())
  41. benchS := db.NewFileSet("test)", fs.NewFilesystem(fs.FilesystemTypeBasic, "."), ldb)
  42. replace(benchS, remoteDevice0, files)
  43. replace(benchS, protocol.LocalDeviceID, firstHalf)
  44. return ldb, benchS
  45. }
  46. func BenchmarkReplaceAll(b *testing.B) {
  47. ldb := db.NewLowlevel(backend.OpenMemory())
  48. defer ldb.Close()
  49. b.ResetTimer()
  50. for i := 0; i < b.N; i++ {
  51. m := db.NewFileSet("test)", fs.NewFilesystem(fs.FilesystemTypeBasic, "."), ldb)
  52. replace(m, protocol.LocalDeviceID, files)
  53. }
  54. b.ReportAllocs()
  55. }
  56. func BenchmarkUpdateOneChanged(b *testing.B) {
  57. ldb, benchS := getBenchFileSet()
  58. defer ldb.Close()
  59. changed := make([]protocol.FileInfo, 1)
  60. changed[0] = oneFile[0]
  61. changed[0].Version = changed[0].Version.Copy().Update(myID)
  62. b.ResetTimer()
  63. for i := 0; i < b.N; i++ {
  64. if i%2 == 0 {
  65. benchS.Update(protocol.LocalDeviceID, changed)
  66. } else {
  67. benchS.Update(protocol.LocalDeviceID, oneFile)
  68. }
  69. }
  70. b.ReportAllocs()
  71. }
  72. func BenchmarkUpdate100Changed(b *testing.B) {
  73. ldb, benchS := getBenchFileSet()
  74. defer ldb.Close()
  75. b.ResetTimer()
  76. for i := 0; i < b.N; i++ {
  77. if i%2 == 0 {
  78. benchS.Update(protocol.LocalDeviceID, changed100)
  79. } else {
  80. benchS.Update(protocol.LocalDeviceID, unchanged100)
  81. }
  82. }
  83. b.ReportAllocs()
  84. }
  85. func setup10Remotes(benchS *db.FileSet) {
  86. idBase := remoteDevice1.String()[1:]
  87. first := 'J'
  88. for i := 0; i < 10; i++ {
  89. id, _ := protocol.DeviceIDFromString(fmt.Sprintf("%v%s", first+rune(i), idBase))
  90. if i%2 == 0 {
  91. benchS.Update(id, changed100)
  92. } else {
  93. benchS.Update(id, unchanged100)
  94. }
  95. }
  96. }
  97. func BenchmarkUpdate100Changed10Remotes(b *testing.B) {
  98. ldb, benchS := getBenchFileSet()
  99. defer ldb.Close()
  100. setup10Remotes(benchS)
  101. b.ResetTimer()
  102. for i := 0; i < b.N; i++ {
  103. if i%2 == 0 {
  104. benchS.Update(protocol.LocalDeviceID, changed100)
  105. } else {
  106. benchS.Update(protocol.LocalDeviceID, unchanged100)
  107. }
  108. }
  109. b.ReportAllocs()
  110. }
  111. func BenchmarkUpdate100ChangedRemote(b *testing.B) {
  112. ldb, benchS := getBenchFileSet()
  113. defer ldb.Close()
  114. b.ResetTimer()
  115. for i := 0; i < b.N; i++ {
  116. if i%2 == 0 {
  117. benchS.Update(remoteDevice0, changed100)
  118. } else {
  119. benchS.Update(remoteDevice0, unchanged100)
  120. }
  121. }
  122. b.ReportAllocs()
  123. }
  124. func BenchmarkUpdate100ChangedRemote10Remotes(b *testing.B) {
  125. ldb, benchS := getBenchFileSet()
  126. defer ldb.Close()
  127. b.ResetTimer()
  128. for i := 0; i < b.N; i++ {
  129. if i%2 == 0 {
  130. benchS.Update(remoteDevice0, changed100)
  131. } else {
  132. benchS.Update(remoteDevice0, unchanged100)
  133. }
  134. }
  135. b.ReportAllocs()
  136. }
  137. func BenchmarkUpdateOneUnchanged(b *testing.B) {
  138. ldb, benchS := getBenchFileSet()
  139. defer ldb.Close()
  140. b.ResetTimer()
  141. for i := 0; i < b.N; i++ {
  142. benchS.Update(protocol.LocalDeviceID, oneFile)
  143. }
  144. b.ReportAllocs()
  145. }
  146. func BenchmarkNeedHalf(b *testing.B) {
  147. ldb, benchS := getBenchFileSet()
  148. defer ldb.Close()
  149. b.ResetTimer()
  150. for i := 0; i < b.N; i++ {
  151. count := 0
  152. snap := benchS.Snapshot()
  153. snap.WithNeed(protocol.LocalDeviceID, func(fi db.FileIntf) bool {
  154. count++
  155. return true
  156. })
  157. snap.Release()
  158. if count != len(secondHalf) {
  159. b.Errorf("wrong length %d != %d", count, len(secondHalf))
  160. }
  161. }
  162. b.ReportAllocs()
  163. }
  164. func BenchmarkNeedHalfRemote(b *testing.B) {
  165. ldb := db.NewLowlevel(backend.OpenMemory())
  166. defer ldb.Close()
  167. fset := db.NewFileSet("test)", fs.NewFilesystem(fs.FilesystemTypeBasic, "."), ldb)
  168. replace(fset, remoteDevice0, firstHalf)
  169. replace(fset, protocol.LocalDeviceID, files)
  170. b.ResetTimer()
  171. for i := 0; i < b.N; i++ {
  172. count := 0
  173. snap := fset.Snapshot()
  174. snap.WithNeed(remoteDevice0, func(fi db.FileIntf) bool {
  175. count++
  176. return true
  177. })
  178. snap.Release()
  179. if count != len(secondHalf) {
  180. b.Errorf("wrong length %d != %d", count, len(secondHalf))
  181. }
  182. }
  183. b.ReportAllocs()
  184. }
  185. func BenchmarkHave(b *testing.B) {
  186. ldb, benchS := getBenchFileSet()
  187. defer ldb.Close()
  188. b.ResetTimer()
  189. for i := 0; i < b.N; i++ {
  190. count := 0
  191. snap := benchS.Snapshot()
  192. snap.WithHave(protocol.LocalDeviceID, func(fi db.FileIntf) bool {
  193. count++
  194. return true
  195. })
  196. snap.Release()
  197. if count != len(firstHalf) {
  198. b.Errorf("wrong length %d != %d", count, len(firstHalf))
  199. }
  200. }
  201. b.ReportAllocs()
  202. }
  203. func BenchmarkGlobal(b *testing.B) {
  204. ldb, benchS := getBenchFileSet()
  205. defer ldb.Close()
  206. b.ResetTimer()
  207. for i := 0; i < b.N; i++ {
  208. count := 0
  209. snap := benchS.Snapshot()
  210. snap.WithGlobal(func(fi db.FileIntf) bool {
  211. count++
  212. return true
  213. })
  214. snap.Release()
  215. if count != len(files) {
  216. b.Errorf("wrong length %d != %d", count, len(files))
  217. }
  218. }
  219. b.ReportAllocs()
  220. }
  221. func BenchmarkNeedHalfTruncated(b *testing.B) {
  222. ldb, benchS := getBenchFileSet()
  223. defer ldb.Close()
  224. b.ResetTimer()
  225. for i := 0; i < b.N; i++ {
  226. count := 0
  227. snap := benchS.Snapshot()
  228. snap.WithNeedTruncated(protocol.LocalDeviceID, func(fi db.FileIntf) bool {
  229. count++
  230. return true
  231. })
  232. snap.Release()
  233. if count != len(secondHalf) {
  234. b.Errorf("wrong length %d != %d", count, len(secondHalf))
  235. }
  236. }
  237. b.ReportAllocs()
  238. }
  239. func BenchmarkHaveTruncated(b *testing.B) {
  240. ldb, benchS := getBenchFileSet()
  241. defer ldb.Close()
  242. b.ResetTimer()
  243. for i := 0; i < b.N; i++ {
  244. count := 0
  245. snap := benchS.Snapshot()
  246. snap.WithHaveTruncated(protocol.LocalDeviceID, func(fi db.FileIntf) bool {
  247. count++
  248. return true
  249. })
  250. snap.Release()
  251. if count != len(firstHalf) {
  252. b.Errorf("wrong length %d != %d", count, len(firstHalf))
  253. }
  254. }
  255. b.ReportAllocs()
  256. }
  257. func BenchmarkGlobalTruncated(b *testing.B) {
  258. ldb, benchS := getBenchFileSet()
  259. defer ldb.Close()
  260. b.ResetTimer()
  261. for i := 0; i < b.N; i++ {
  262. count := 0
  263. snap := benchS.Snapshot()
  264. snap.WithGlobalTruncated(func(fi db.FileIntf) bool {
  265. count++
  266. return true
  267. })
  268. snap.Release()
  269. if count != len(files) {
  270. b.Errorf("wrong length %d != %d", count, len(files))
  271. }
  272. }
  273. b.ReportAllocs()
  274. }
  275. func BenchmarkNeedCount(b *testing.B) {
  276. ldb, benchS := getBenchFileSet()
  277. defer ldb.Close()
  278. benchS.Update(protocol.LocalDeviceID, changed100)
  279. b.ResetTimer()
  280. for i := 0; i < b.N; i++ {
  281. snap := benchS.Snapshot()
  282. _ = snap.NeedSize(protocol.LocalDeviceID)
  283. snap.Release()
  284. }
  285. b.ReportAllocs()
  286. }