benchmark_test.go 7.1 KB

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