perfmonger 0.10.2 → 0.12.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +3 -0
  3. data/.travis.yml +9 -8
  4. data/HOWTO.md +0 -1
  5. data/NEWS +49 -5
  6. data/README.md +77 -27
  7. data/Rakefile +33 -11
  8. data/core/Makefile +22 -31
  9. data/core/build.sh +6 -8
  10. data/core/cmd/perfmonger-player/perfmonger-player.go +247 -0
  11. data/core/{perfmonger-plot-formatter.go → cmd/perfmonger-plot-formatter/perfmonger-plot-formatter.go} +20 -5
  12. data/core/{perfmonger-recorder.go → cmd/perfmonger-recorder/perfmonger-recorder.go} +22 -2
  13. data/core/{perfmonger-summarizer.go → cmd/perfmonger-summarizer/perfmonger-summarizer.go} +22 -15
  14. data/core/cmd/perfmonger-viewer/perfmonger-viewer.go +164 -0
  15. data/core/go.mod +10 -0
  16. data/core/go.sum +17 -0
  17. data/core/subsystem/Makefile +4 -0
  18. data/core/subsystem/perfmonger_linux.go +95 -0
  19. data/core/subsystem/perfmonger_linux_test.go +40 -0
  20. data/core/subsystem/stat.go +70 -0
  21. data/core/subsystem/stat_test.go +9 -0
  22. data/core/subsystem/usage.go +223 -66
  23. data/core/subsystem/usage_test.go +62 -32
  24. data/core/utils.go +2 -2
  25. data/{bin → exe}/perfmonger +0 -0
  26. data/lib/exec/perfmonger-player_darwin_amd64 +0 -0
  27. data/lib/exec/perfmonger-player_linux_amd64 +0 -0
  28. data/lib/exec/perfmonger-plot-formatter_darwin_amd64 +0 -0
  29. data/lib/exec/perfmonger-plot-formatter_linux_amd64 +0 -0
  30. data/lib/exec/perfmonger-recorder_darwin_amd64 +0 -0
  31. data/lib/exec/perfmonger-recorder_linux_amd64 +0 -0
  32. data/lib/exec/perfmonger-summarizer_darwin_amd64 +0 -0
  33. data/lib/exec/perfmonger-summarizer_linux_amd64 +0 -0
  34. data/lib/exec/perfmonger-viewer_darwin_amd64 +0 -0
  35. data/lib/exec/perfmonger-viewer_linux_amd64 +0 -0
  36. data/lib/perfmonger/command/fingerprint.rb +26 -1
  37. data/lib/perfmonger/command/live.rb +19 -0
  38. data/lib/perfmonger/command/play.rb +16 -0
  39. data/lib/perfmonger/command/plot.rb +23 -9
  40. data/lib/perfmonger/command/record.rb +24 -3
  41. data/lib/perfmonger/command/record_option.rb +16 -0
  42. data/lib/perfmonger/command/server.rb +1 -1
  43. data/lib/perfmonger/version.rb +1 -1
  44. data/misc/werker-box/Dockerfile +34 -0
  45. data/misc/werker-box/build-push.sh +7 -0
  46. data/perfmonger.gemspec +2 -1
  47. data/spec/data/busy100.pgr.played +3 -3
  48. data/spec/fingerprint_spec.rb +1 -1
  49. data/spec/live_spec.rb +2 -3
  50. data/spec/perfmonger_spec.rb +1 -1
  51. data/spec/play_spec.rb +1 -1
  52. data/spec/plot_spec.rb +16 -1
  53. data/spec/record_spec.rb +10 -1
  54. data/spec/spec_helper.rb +28 -3
  55. data/spec/stat_spec.rb +2 -2
  56. data/spec/summary_spec.rb +1 -1
  57. data/wercker.yml +29 -16
  58. metadata +34 -14
  59. data/core/perfmonger-player.go +0 -196
  60. data/lib/exec/perfmonger-player_linux_386 +0 -0
  61. data/lib/exec/perfmonger-plot-formatter_linux_386 +0 -0
  62. data/lib/exec/perfmonger-recorder_linux_386 +0 -0
  63. data/lib/exec/perfmonger-summarizer_linux_386 +0 -0
@@ -0,0 +1,247 @@
1
+ //usr/bin/env go run $0 $@ ; exit
2
+
3
+ package main
4
+
5
+ import (
6
+ "bufio"
7
+ "encoding/gob"
8
+ "flag"
9
+ "fmt"
10
+ "io"
11
+ "os"
12
+
13
+ projson "github.com/hayamiz/go-projson"
14
+ ss "github.com/hayamiz/perfmonger/core/subsystem"
15
+ core "github.com/hayamiz/perfmonger/core"
16
+ )
17
+
18
+ type PlayerOption struct {
19
+ logfile string
20
+ color bool
21
+ pretty bool
22
+ }
23
+
24
+ var option PlayerOption
25
+ var init_rec ss.StatRecord
26
+
27
+ func showCpuStat(printer *projson.JsonPrinter, prev_rec *ss.StatRecord, cur_rec *ss.StatRecord) error {
28
+ cusage, err := ss.GetCpuUsage(prev_rec.Cpu, cur_rec.Cpu)
29
+ if err != nil {
30
+ return err
31
+ }
32
+
33
+ printer.PutKey("cpu")
34
+ cusage.WriteJsonTo(printer)
35
+
36
+ return nil
37
+ }
38
+
39
+ func showInterruptStat(printer *projson.JsonPrinter, prev_rec *ss.StatRecord, cur_rec *ss.StatRecord) error {
40
+ intr_usage, err := ss.GetInterruptUsage(
41
+ prev_rec.Time, prev_rec.Interrupt,
42
+ cur_rec.Time, cur_rec.Interrupt)
43
+ if err != nil {
44
+ return err
45
+ }
46
+
47
+ printer.PutKey("intr")
48
+ intr_usage.WriteJsonTo(printer)
49
+
50
+ return nil
51
+ }
52
+
53
+ func showDiskStat(printer *projson.JsonPrinter, prev_rec *ss.StatRecord, cur_rec *ss.StatRecord) error {
54
+ dusage, err := ss.GetDiskUsage(
55
+ prev_rec.Time, prev_rec.Disk,
56
+ cur_rec.Time, cur_rec.Disk)
57
+ if err != nil {
58
+ return err
59
+ }
60
+
61
+ printer.PutKey("disk")
62
+
63
+ dusage.WriteJsonTo(printer)
64
+
65
+ return nil
66
+ }
67
+
68
+ func showNetStat(printer *projson.JsonPrinter, prev_rec *ss.StatRecord, cur_rec *ss.StatRecord) error {
69
+ dusage, err := ss.GetNetUsage(
70
+ prev_rec.Time, prev_rec.Net,
71
+ cur_rec.Time, cur_rec.Net,
72
+ )
73
+ if err != nil {
74
+ return err
75
+ }
76
+
77
+ printer.PutKey("net")
78
+
79
+ dusage.WriteJsonTo(printer)
80
+
81
+ return nil
82
+ }
83
+
84
+ func showMemStat(printer *projson.JsonPrinter, cur_rec *ss.StatRecord) error {
85
+ musage, err := ss.GetMemUsage(cur_rec.Mem)
86
+ if err != nil {
87
+ return err
88
+ }
89
+
90
+ printer.PutKey("mem")
91
+
92
+ musage.WriteJsonTo(printer)
93
+
94
+ return nil
95
+ }
96
+
97
+ func showStat(printer *projson.JsonPrinter, prev_rec *ss.StatRecord, cur_rec *ss.StatRecord) error {
98
+ printer.Reset()
99
+ if option.pretty {
100
+ printer.SetStyle(projson.SmartStyle)
101
+ }
102
+ if option.color {
103
+ printer.SetColor(true)
104
+ }
105
+ printer.BeginObject()
106
+ printer.PutKey("time")
107
+ printer.PutFloatFmt(float64(cur_rec.Time.UnixNano())/1e9, "%.3f")
108
+ printer.PutKey("elapsed_time")
109
+ printer.PutFloatFmt((float64(cur_rec.Time.UnixNano())-float64(init_rec.Time.UnixNano()))/1e9,
110
+ "%.3f")
111
+
112
+ if cur_rec.Cpu != nil {
113
+ err := showCpuStat(printer, prev_rec, cur_rec)
114
+ if err != nil {
115
+ return err
116
+ }
117
+ }
118
+ if cur_rec.Interrupt != nil {
119
+ err := showInterruptStat(printer, prev_rec, cur_rec)
120
+ if err != nil {
121
+ return err
122
+ }
123
+ }
124
+ if cur_rec.Disk != nil {
125
+ err := showDiskStat(printer, prev_rec, cur_rec)
126
+ if err != nil {
127
+ return err
128
+ }
129
+ }
130
+ if cur_rec.Net != nil {
131
+ err := showNetStat(printer, prev_rec, cur_rec)
132
+ if err != nil {
133
+ return err
134
+ }
135
+ }
136
+ if cur_rec.Mem != nil {
137
+ err := showMemStat(printer, cur_rec)
138
+ if err != nil {
139
+ return err
140
+ }
141
+ }
142
+
143
+ printer.FinishObject()
144
+
145
+ return nil
146
+ }
147
+
148
+ func parseArgs() {
149
+ flag.BoolVar(&option.color, "color", false, "Use colored JSON output")
150
+ flag.BoolVar(&option.pretty, "pretty", false, "Use human readable JSON output")
151
+
152
+ flag.Parse()
153
+
154
+ option.logfile = flag.Arg(0)
155
+ }
156
+
157
+ func main() {
158
+ var in *os.File
159
+ var out *bufio.Writer
160
+
161
+ parseArgs()
162
+
163
+ if option.logfile == "" {
164
+ in = os.Stdin
165
+ } else {
166
+ f, err := os.Open(option.logfile)
167
+ if err != nil {
168
+ panic(err)
169
+ }
170
+ in = f
171
+ defer f.Close()
172
+ }
173
+ input_reader := core.NewPerfmongerLogReader(in)
174
+ dec := gob.NewDecoder(input_reader)
175
+
176
+ out = bufio.NewWriter(os.Stdout)
177
+
178
+ var cheader ss.CommonHeader
179
+ var pheader ss.PlatformHeader
180
+ var records = make([]ss.StatRecord, 2)
181
+ curr := 0
182
+
183
+ var err error
184
+
185
+ err = dec.Decode(&cheader)
186
+ if err == io.EOF {
187
+ return
188
+ }
189
+ if err != nil {
190
+ panic(err)
191
+ }
192
+ err = dec.Decode(&pheader)
193
+ if err == io.EOF {
194
+ return
195
+ }
196
+ if err != nil {
197
+ panic(err)
198
+ }
199
+
200
+ // read first record
201
+ err = dec.Decode(&records[curr])
202
+ if err == io.EOF {
203
+ return
204
+ } else if err != nil {
205
+ panic(err)
206
+ }
207
+ init_rec = records[curr]
208
+ curr ^= 1
209
+
210
+ printer := projson.NewPrinter()
211
+ for {
212
+ prev_rec := &records[curr^1]
213
+ cur_rec := &records[curr]
214
+
215
+ err = dec.Decode(cur_rec)
216
+ if err == io.EOF {
217
+ break
218
+ } else if err != nil {
219
+ panic(err)
220
+ }
221
+
222
+ err = showStat(printer, prev_rec, cur_rec)
223
+ if err != nil {
224
+ printer.Reset()
225
+ fmt.Fprintln(os.Stderr, "skip by err")
226
+ continue
227
+ }
228
+
229
+ if str, err := printer.String(); err != nil {
230
+ fmt.Println("error", err)
231
+ fmt.Println(str)
232
+ } else {
233
+ _, err = out.WriteString(str + "\n")
234
+ }
235
+ err = out.Flush()
236
+ if err != nil {
237
+ // stdout is closed
238
+ break
239
+ }
240
+
241
+ printer.Reset()
242
+
243
+ curr ^= 1
244
+ }
245
+
246
+ return
247
+ }
@@ -11,23 +11,31 @@ import (
11
11
  "io"
12
12
  "io/ioutil"
13
13
  "os"
14
+ "regexp"
14
15
  "sort"
15
16
 
16
17
  ss "github.com/hayamiz/perfmonger/core/subsystem"
18
+ "github.com/hayamiz/perfmonger/core"
17
19
  )
18
20
 
19
21
  type CmdOption struct {
20
- DiskFile string
21
- CpuFile string
22
- PerfmongerFile string
22
+ DiskFile string
23
+ CpuFile string
24
+ PerfmongerFile string
25
+ disk_only string
26
+ disk_only_regex *regexp.Regexp
23
27
  }
24
28
 
25
29
  func parseArgs() *CmdOption {
30
+ var err error
31
+
26
32
  opt := new(CmdOption)
27
33
 
28
34
  flag.StringVar(&opt.DiskFile, "diskfile", "./disk.dat", "Disk performance data file")
29
35
  flag.StringVar(&opt.CpuFile, "cpufile", "./cpu.dat", "CPU performance data file")
30
36
  flag.StringVar(&opt.PerfmongerFile, "perfmonger", "", "Perfmonger log file")
37
+ flag.StringVar(&opt.disk_only, "disk-only",
38
+ "", "Select disk devices by regex")
31
39
 
32
40
  flag.Parse()
33
41
 
@@ -36,6 +44,11 @@ func parseArgs() *CmdOption {
36
44
  os.Exit(1)
37
45
  }
38
46
 
47
+ opt.disk_only_regex, err = regexp.Compile(opt.disk_only)
48
+ if err != nil {
49
+ panic(err)
50
+ }
51
+
39
52
  return opt
40
53
  }
41
54
 
@@ -129,7 +142,7 @@ func main() {
129
142
  }
130
143
  defer f.Close()
131
144
 
132
- input_reader := newPerfmongerLogReader(f)
145
+ input_reader := core.NewPerfmongerLogReader(f)
133
146
  dec := gob.NewDecoder(input_reader)
134
147
 
135
148
  var cheader ss.CommonHeader
@@ -192,7 +205,9 @@ func main() {
192
205
  }
193
206
 
194
207
  // Disk usage
195
- dusage, err := ss.GetDiskUsage(prev_rec.Time, prev_rec.Disk, cur_rec.Time, cur_rec.Disk)
208
+ dusage, err := ss.GetDiskUsage1(prev_rec.Time, prev_rec.Disk,
209
+ cur_rec.Time, cur_rec.Disk,
210
+ opt.disk_only_regex)
196
211
  if err != nil {
197
212
  panic(err)
198
213
  }
@@ -36,6 +36,7 @@ type RecorderOption struct {
36
36
  no_intr bool
37
37
  no_disk bool
38
38
  no_net bool
39
+ no_mem bool
39
40
  debug bool
40
41
  listDevices bool
41
42
  player_bin string
@@ -43,6 +44,8 @@ type RecorderOption struct {
43
44
  targetDisks *map[string]bool
44
45
  background bool
45
46
  gzip bool
47
+ color bool
48
+ pretty bool
46
49
  }
47
50
 
48
51
  var option RecorderOption
@@ -74,6 +77,8 @@ func parseArgs() {
74
77
  false, "Do not record disk usage")
75
78
  flag.BoolVar(&option.no_net, "no-net",
76
79
  false, "Do not record net usage")
80
+ flag.BoolVar(&option.no_mem, "no-mem",
81
+ false, "Do not record memory usage")
77
82
  flag.BoolVar(&option.debug, "debug",
78
83
  false, "Enable debug mode")
79
84
  flag.BoolVar(&option.listDevices, "list-devices",
@@ -86,6 +91,10 @@ func parseArgs() {
86
91
  "", "Run perfmonger-player to show JSON output")
87
92
  flag.BoolVar(&option.gzip, "gzip",
88
93
  false, "Save a logfile in gzipped format")
94
+ flag.BoolVar(&option.color, "color",
95
+ false, "Colored output (for live subcmd)")
96
+ flag.BoolVar(&option.pretty, "pretty",
97
+ false, "Pretty output (for live subcmd)")
89
98
 
90
99
  flag.Parse()
91
100
 
@@ -190,7 +199,7 @@ func main() {
190
199
  parseArgs()
191
200
 
192
201
  hostname, _ := os.Hostname()
193
- cheader := &ss.CommonHeader{ss.Linux, hostname, time.Now()}
202
+ cheader := &ss.CommonHeader{Platform: ss.Linux, Hostname: hostname, StartTime: time.Now()}
194
203
 
195
204
  platform_header := ss.NewPlatformHeader()
196
205
 
@@ -206,7 +215,15 @@ func main() {
206
215
  var player_stdout io.ReadCloser = nil
207
216
 
208
217
  if option.player_bin != "" {
209
- player_cmd = exec.Command(option.player_bin)
218
+ if option.color {
219
+ if option.pretty {
220
+ player_cmd = exec.Command(option.player_bin, "-color", "-pretty")
221
+ } else {
222
+ player_cmd = exec.Command(option.player_bin, "-color")
223
+ }
224
+ } else {
225
+ player_cmd = exec.Command(option.player_bin)
226
+ }
210
227
  player_stdin, err = player_cmd.StdinPipe()
211
228
  if err != nil {
212
229
  fmt.Fprintf(os.Stderr, "Failed to get stdin of %s", option.player_bin)
@@ -326,6 +343,9 @@ func main() {
326
343
  if !option.no_net {
327
344
  ss.ReadNetStat(record)
328
345
  }
346
+ if !option.no_mem {
347
+ ss.ReadMemStat(record)
348
+ }
329
349
 
330
350
  err = enc.Encode(record)
331
351
  if err != nil {
@@ -3,7 +3,6 @@
3
3
  package main
4
4
 
5
5
  import (
6
- "bytes"
7
6
  "encoding/gob"
8
7
  "flag"
9
8
  "fmt"
@@ -12,7 +11,9 @@ import (
12
11
  "regexp"
13
12
  "sort"
14
13
 
14
+ projson "github.com/hayamiz/go-projson"
15
15
  ss "github.com/hayamiz/perfmonger/core/subsystem"
16
+ "github.com/hayamiz/perfmonger/core"
16
17
  )
17
18
 
18
19
  type SummaryOption struct {
@@ -61,7 +62,7 @@ func main() {
61
62
  }
62
63
  defer f.Close()
63
64
 
64
- input_reader := newPerfmongerLogReader(f)
65
+ input_reader := core.NewPerfmongerLogReader(f)
65
66
  dec := gob.NewDecoder(input_reader)
66
67
 
67
68
  err = dec.Decode(&cheader)
@@ -128,7 +129,7 @@ func main() {
128
129
  option.disk_only_regex)
129
130
  }
130
131
 
131
- if fst_record.Disk != nil && lst_record.Disk != nil {
132
+ if fst_record.Net != nil && lst_record.Net != nil {
132
133
  net_usage, err = ss.GetNetUsage(
133
134
  fst_record.Time, fst_record.Net,
134
135
  lst_record.Time, lst_record.Net)
@@ -137,32 +138,38 @@ func main() {
137
138
  interval := lst_record.Time.Sub(fst_record.Time)
138
139
 
139
140
  if option.json {
140
- buf := bytes.NewBuffer([]byte{})
141
+ printer := projson.NewPrinter()
141
142
 
142
- buf.WriteString(fmt.Sprintf(`{"exectime":%.3f`, interval.Seconds()))
143
+ printer.BeginObject()
144
+ printer.PutKey("exectime")
145
+ printer.PutFloatFmt(interval.Seconds(), "%.3f")
143
146
  if cpu_usage != nil {
144
- buf.WriteString(`,"cpu":`)
145
- cpu_usage.WriteJsonTo(buf)
147
+ printer.PutKey("cpu")
148
+ cpu_usage.WriteJsonTo(printer)
146
149
  }
147
150
 
148
151
  if intr_usage != nil {
149
- buf.WriteString(`,"intr":`)
150
- intr_usage.WriteJsonTo(buf)
152
+ printer.PutKey("intr")
153
+ intr_usage.WriteJsonTo(printer)
151
154
  }
152
155
 
153
156
  if disk_usage != nil {
154
- buf.WriteString(`,"disk":`)
155
- disk_usage.WriteJsonTo(buf)
157
+ printer.PutKey("disk")
158
+ disk_usage.WriteJsonTo(printer)
156
159
  }
157
160
 
158
161
  if net_usage != nil {
159
- buf.WriteString(`,"net":`)
160
- net_usage.WriteJsonTo(buf)
162
+ printer.PutKey("net")
163
+ net_usage.WriteJsonTo(printer)
161
164
  }
162
165
 
163
- buf.WriteByte('}')
166
+ printer.FinishObject()
164
167
 
165
- fmt.Println(buf.String())
168
+ if str, err := printer.String(); err != nil {
169
+ fmt.Println("skip by err")
170
+ } else {
171
+ fmt.Println(str)
172
+ }
166
173
  } else {
167
174
  if option.title == "" {
168
175
  fmt.Println("== performance summary ==")