1
0

main.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. // Copyright (C) 2016 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 http://mozilla.org/MPL/2.0/.
  6. // This doesn't build on Windows due to the Rusage stuff.
  7. // +build !windows
  8. package main
  9. import (
  10. "flag"
  11. "fmt"
  12. "log"
  13. "runtime"
  14. "syscall"
  15. "time"
  16. "github.com/syncthing/syncthing/lib/rc"
  17. )
  18. var homeDir = "h1"
  19. var syncthingBin = "./bin/syncthing"
  20. var test = "scan"
  21. func main() {
  22. flag.StringVar(&homeDir, "home", homeDir, "Home directory location")
  23. flag.StringVar(&syncthingBin, "bin", syncthingBin, "Binary location")
  24. flag.StringVar(&test, "test", test, "Test to run")
  25. flag.Parse()
  26. switch test {
  27. case "scan":
  28. // scan measures the resource usage required to perform the initial
  29. // scan, without cleaning away the database first.
  30. testScan()
  31. }
  32. }
  33. // testScan starts a process and reports on the resource usage required to
  34. // perform the initial scan.
  35. func testScan() {
  36. log.Println("Starting...")
  37. p := rc.NewProcess("127.0.0.1:8081")
  38. if err := p.Start(syncthingBin, "-home", homeDir, "-no-browser"); err != nil {
  39. log.Println(err)
  40. return
  41. }
  42. defer p.Stop()
  43. wallTime := awaitScanComplete(p)
  44. report(p, wallTime)
  45. }
  46. // awaitScanComplete waits for a folder to transition idle->scanning and
  47. // then scanning->idle and returns the time taken for the scan.
  48. func awaitScanComplete(p *rc.Process) time.Duration {
  49. log.Println("Awaiting scan completion...")
  50. var t0, t1 time.Time
  51. lastEvent := 0
  52. loop:
  53. for {
  54. evs, err := p.Events(lastEvent)
  55. if err != nil {
  56. continue
  57. }
  58. for _, ev := range evs {
  59. if ev.Type == "StateChanged" {
  60. data := ev.Data.(map[string]interface{})
  61. log.Println(ev)
  62. if data["to"].(string) == "scanning" {
  63. t0 = ev.Time
  64. continue
  65. }
  66. if !t0.IsZero() && data["to"].(string) == "idle" {
  67. t1 = ev.Time
  68. break loop
  69. }
  70. }
  71. lastEvent = ev.ID
  72. }
  73. time.Sleep(250 * time.Millisecond)
  74. }
  75. return t1.Sub(t0)
  76. }
  77. // report stops the given process and reports on it's resource usage in two
  78. // ways: human readable to stderr, and CSV to stdout.
  79. func report(p *rc.Process, wallTime time.Duration) {
  80. sv, err := p.SystemVersion()
  81. if err != nil {
  82. log.Println(err)
  83. return
  84. }
  85. ss, err := p.SystemStatus()
  86. if err != nil {
  87. log.Println(err)
  88. return
  89. }
  90. proc, err := p.Stop()
  91. if err != nil {
  92. return
  93. }
  94. rusage, ok := proc.SysUsage().(*syscall.Rusage)
  95. if !ok {
  96. return
  97. }
  98. log.Println("Version:", sv.Version)
  99. log.Println("Alloc:", ss.Alloc/1024, "KiB")
  100. log.Println("Sys:", ss.Sys/1024, "KiB")
  101. log.Println("Goroutines:", ss.Goroutines)
  102. log.Println("Wall time:", wallTime)
  103. log.Println("Utime:", time.Duration(rusage.Utime.Nano()))
  104. log.Println("Stime:", time.Duration(rusage.Stime.Nano()))
  105. if runtime.GOOS == "darwin" {
  106. // Darwin reports in bytes, Linux seems to report in KiB even
  107. // though the manpage says otherwise.
  108. rusage.Maxrss /= 1024
  109. }
  110. log.Println("MaxRSS:", rusage.Maxrss, "KiB")
  111. fmt.Printf("%s,%d,%d,%d,%.02f,%.02f,%.02f,%d\n",
  112. sv.Version,
  113. ss.Alloc/1024,
  114. ss.Sys/1024,
  115. ss.Goroutines,
  116. wallTime.Seconds(),
  117. time.Duration(rusage.Utime.Nano()).Seconds(),
  118. time.Duration(rusage.Stime.Nano()).Seconds(),
  119. rusage.Maxrss)
  120. }