perfmonger 0.11.2 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +5 -5
  3. data/NEWS +38 -1
  4. data/Rakefile +18 -7
  5. data/core/Makefile +20 -21
  6. data/core/build.sh +4 -6
  7. data/core/{perfmonger-player.go → cmd/perfmonger-player/perfmonger-player.go} +53 -10
  8. data/core/cmd/perfmonger-plot-formatter/README.md +24 -0
  9. data/core/{perfmonger-plot-formatter.go → cmd/perfmonger-plot-formatter/perfmonger-plot-formatter.go} +116 -3
  10. data/core/{perfmonger-recorder.go → cmd/perfmonger-recorder/perfmonger-recorder.go} +6 -0
  11. data/core/{perfmonger-summarizer.go → cmd/perfmonger-summarizer/perfmonger-summarizer.go} +4 -2
  12. data/core/{perfmonger-viewer.go → cmd/perfmonger-viewer/perfmonger-viewer.go} +0 -0
  13. data/core/go.mod +10 -0
  14. data/core/go.sum +17 -0
  15. data/core/subsystem/Makefile +4 -0
  16. data/core/subsystem/perfmonger_linux.go +97 -0
  17. data/core/subsystem/perfmonger_linux_test.go +40 -0
  18. data/core/subsystem/stat.go +72 -0
  19. data/core/subsystem/stat_test.go +9 -0
  20. data/core/subsystem/usage.go +80 -0
  21. data/core/utils.go +2 -2
  22. data/lib/exec/perfmonger-player_darwin_amd64 +0 -0
  23. data/lib/exec/perfmonger-player_linux_amd64 +0 -0
  24. data/lib/exec/perfmonger-plot-formatter_darwin_amd64 +0 -0
  25. data/lib/exec/perfmonger-plot-formatter_linux_amd64 +0 -0
  26. data/lib/exec/perfmonger-recorder_darwin_amd64 +0 -0
  27. data/lib/exec/perfmonger-recorder_linux_amd64 +0 -0
  28. data/lib/exec/perfmonger-summarizer_darwin_amd64 +0 -0
  29. data/lib/exec/perfmonger-summarizer_linux_amd64 +0 -0
  30. data/lib/exec/perfmonger-viewer_darwin_amd64 +0 -0
  31. data/lib/exec/perfmonger-viewer_linux_amd64 +0 -0
  32. data/lib/perfmonger/command/play.rb +10 -0
  33. data/lib/perfmonger/command/plot.rb +146 -3
  34. data/lib/perfmonger/command/record.rb +23 -2
  35. data/lib/perfmonger/command/record_option.rb +16 -0
  36. data/lib/perfmonger/version.rb +1 -1
  37. data/misc/werker-box/Dockerfile +10 -9
  38. data/misc/werker-box/build-push.sh +2 -2
  39. data/wercker.yml +10 -10
  40. metadata +12 -27
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4a60a8aaed2af9077a0027baf15afc68856ed6c5d9a08267dde6a903abeea762
4
- data.tar.gz: 46113a4949d34a74737acac64f8d032b31cf3bddfdad51dbc158fc0599fa1151
3
+ metadata.gz: 7cafa0eb63dce619c0f5cf2f23042db020e435905eb7d00e2338d3c499495d02
4
+ data.tar.gz: ab6875fdfe16bd70461db8569b4c5572bbd261e931a6efa98c2bede6660e9d1b
5
5
  SHA512:
6
- metadata.gz: 4eacfdf595f3bd39bc64f5516ef8d14eff0a49e9f8befdf7a2102b642dd604be88328783fceb7a1b3163a883554eb624d1b46e88a3a13c23b9265ef0a4b1343c
7
- data.tar.gz: 1b416767ae0201a1cbb7f500c99f14c88566a86c7a8e03c5f0d56a3b1ba0ba8b12b5491a0a5ac35d2b06263b6af5fbd6b22e7550df8720bd78a183e8c4b68eae
6
+ metadata.gz: 17bb023ddebbde5fda03b2ed90411274a335e34ac5ddc83e4df7821454e40484957688ed7dfe72b9245190006fee0c2e1e39aa375fe17c12f95bba9838f2d767
7
+ data.tar.gz: 259636bb0f5049e404ec752edf0e659b23b8bc1adcaea69ef2f0db4cc3bfccac028793fd48920d9e4a54e5cda86a3a52581eb2dc250abd0b5f8476dec815772f
data/.travis.yml CHANGED
@@ -4,7 +4,7 @@ install:
4
4
  - sudo apt-get install gnuplot
5
5
  - gnuplot -e "set terminal" < /dev/null 2>&1
6
6
  - bundle install
7
- - go_version="1.8.3"
7
+ - go_version="1.14.1"
8
8
  - wget http://golang.org/dl/go${go_version}.linux-amd64.tar.gz
9
9
  - sudo tar -C /usr/local -xzf go${go_version}.linux-amd64.tar.gz
10
10
  - export PATH=$PATH:/usr/local/go/bin
@@ -12,10 +12,10 @@ install:
12
12
  - export PATH="$PATH:$GOPATH/bin"
13
13
  - mkdir -p "$HOME/go/{src,pkg,bin}"
14
14
  rvm:
15
- - 2.2.10
16
- - 2.3.8
17
- - 2.4.5
18
- - 2.5.3
15
+ - 2.4.9
16
+ - 2.5.7
17
+ - 2.6.5
18
+ - 2.7.0
19
19
  script:
20
20
  - rake go_get
21
21
  - rake spec
data/NEWS CHANGED
@@ -1,9 +1,46 @@
1
- ## 20XX-XX-XX: PerfMonger 0.12.0
1
+ ## 2021-XX-XX: PerfMonger 0.15.0
2
+
3
+ ## 2021-07-27: PerfMonger 0.14.0
4
+ * New features
5
+ * [plot] subcommand:
6
+ * Added memory usage plot
7
+ * Changes
8
+ * [record] subcommand:
9
+ * Additionaly record 'Hugepagesize' in memory usage
10
+
11
+ ## 2021-07-26: PerfMonger 0.13.1
12
+ * New features
13
+ * [play] subcommand:
14
+ * Added --disk-only option to filter results of not interesting disks
15
+ * Note: v0.13.0 is yanked from rubygems.org
16
+
17
+ ## 2021-07-08: PerfMonger 0.12.1
18
+ * Bug fixes
19
+ * [record] subcommand:
20
+ * --kill waits until a recorder process surely exits
21
+
22
+ ## 2021-05-10: PerfMonger 0.12.0
23
+ * New features
24
+ * [record] subcommand:
25
+ * Add memory usage collection
26
+
27
+ ## 2021-02-10: PerfMonger 0.11.3
28
+ * Bug fixes
29
+ * [plot] subcommand:
30
+ * Fall back to available gnuplot terminal
31
+ * Changes
32
+ * [plot] subcommand:
33
+ * Added --with-gnuplot option for specifying gnuplot binary
2
34
 
3
35
  ## 2020-03-31: PerfMonger 0.11.2
4
36
  * Bug fixes
5
37
  * [plot] subcommand:
6
38
  * Remove temporary directory correctly
39
+ * Changes
40
+ * CI environment
41
+ * Changed golang version to 1.14
42
+ * Dropped support of ruby older than 2.4
43
+ * Added ruby 2.6 and 2.7
7
44
 
8
45
  ## 2018-05-15: PerfMonger 0.11.1
9
46
  * Bug fixes
data/Rakefile CHANGED
@@ -2,7 +2,7 @@ require 'rubygems'
2
2
  require 'rspec/core/rake_task'
3
3
  require "bundler/gem_tasks"
4
4
 
5
- task :default => [:spec, :test_core]
5
+ task :default => [:spec, :test_core, :analyze_core]
6
6
 
7
7
  desc "Run all specs in spec directory"
8
8
  RSpec::Core::RakeTask.new(:spec)
@@ -30,19 +30,30 @@ task :go_get do
30
30
  sh "go get -u github.com/jroimartin/gocui"
31
31
  end
32
32
 
33
- desc "Run tests of core recorder/player"
33
+ desc "Run tests of golang core library"
34
34
  task :test_core => [:cross_build_core] do
35
35
  Dir.chdir("./core/subsystem") do
36
+ # check coverage
36
37
  sh "go test -v -cover"
37
-
38
- # running static analysis
39
- sh "go vet *.go"
40
38
  end
39
+ end
41
40
 
42
- Dir.chdir("./core") do
43
- sh "go vet *.go"
41
+ desc "Run static-analysis of golang core library"
42
+ task :analyze_core => [:cross_build_core] do
43
+ # running static analysis
44
+ Dir.chdir("./core/subsystem") do
45
+ ["linux", "darwin"].each do |platform|
46
+ puts "* ./core/subsystem"
47
+ sh "go vet perfmonger_#{platform}.go $(ls *.go | grep -v perfmonger_)"
48
+ end
44
49
  end
45
50
 
51
+ Dir["./core", "./core/cmd/*"].each do |dir|
52
+ Dir.chdir(dir) do
53
+ puts "* #{dir}"
54
+ sh "go vet *.go"
55
+ end
56
+ end
46
57
  end
47
58
 
48
59
  desc "Removed generated files"
data/core/Makefile CHANGED
@@ -2,51 +2,50 @@
2
2
  # generated by build.sh
3
3
 
4
4
  GO_DEPS := subsystem/perfmonger_darwin.go subsystem/perfmonger.go subsystem/perfmonger_linux.go subsystem/perfmonger_linux_test.go subsystem/stat.go subsystem/stat_test.go subsystem/usage.go subsystem/usage_test.go utils.go
5
- GO_SRC := utils.go
6
5
 
7
6
  .PHONY: all build clean
8
7
 
9
8
  all: build
10
9
 
11
10
 
12
- ../lib/exec/perfmonger-recorder_linux_amd64: perfmonger-recorder.go $(GO_DEPS)
13
- go build -o $@ perfmonger-recorder.go $(GO_SRC)
11
+ ../lib/exec/perfmonger-recorder_linux_amd64: cmd/perfmonger-recorder/perfmonger-recorder.go $(GO_DEPS)
12
+ cd cmd/perfmonger-recorder && go build -o ../../$@ perfmonger-recorder.go
14
13
 
15
14
 
16
- ../lib/exec/perfmonger-player_linux_amd64: perfmonger-player.go $(GO_DEPS)
17
- go build -o $@ perfmonger-player.go $(GO_SRC)
15
+ ../lib/exec/perfmonger-player_linux_amd64: cmd/perfmonger-player/perfmonger-player.go $(GO_DEPS)
16
+ cd cmd/perfmonger-player && go build -o ../../$@ perfmonger-player.go
18
17
 
19
18
 
20
- ../lib/exec/perfmonger-viewer_linux_amd64: perfmonger-viewer.go $(GO_DEPS)
21
- go build -o $@ perfmonger-viewer.go $(GO_SRC)
19
+ ../lib/exec/perfmonger-viewer_linux_amd64: cmd/perfmonger-viewer/perfmonger-viewer.go $(GO_DEPS)
20
+ cd cmd/perfmonger-viewer && go build -o ../../$@ perfmonger-viewer.go
22
21
 
23
22
 
24
- ../lib/exec/perfmonger-summarizer_linux_amd64: perfmonger-summarizer.go $(GO_DEPS)
25
- go build -o $@ perfmonger-summarizer.go $(GO_SRC)
23
+ ../lib/exec/perfmonger-summarizer_linux_amd64: cmd/perfmonger-summarizer/perfmonger-summarizer.go $(GO_DEPS)
24
+ cd cmd/perfmonger-summarizer && go build -o ../../$@ perfmonger-summarizer.go
26
25
 
27
26
 
28
- ../lib/exec/perfmonger-plot-formatter_linux_amd64: perfmonger-plot-formatter.go $(GO_DEPS)
29
- go build -o $@ perfmonger-plot-formatter.go $(GO_SRC)
27
+ ../lib/exec/perfmonger-plot-formatter_linux_amd64: cmd/perfmonger-plot-formatter/perfmonger-plot-formatter.go $(GO_DEPS)
28
+ cd cmd/perfmonger-plot-formatter && go build -o ../../$@ perfmonger-plot-formatter.go
30
29
 
31
30
 
32
- ../lib/exec/perfmonger-recorder_darwin_amd64: perfmonger-recorder.go $(GO_DEPS)
33
- go build -o $@ perfmonger-recorder.go $(GO_SRC)
31
+ ../lib/exec/perfmonger-recorder_darwin_amd64: cmd/perfmonger-recorder/perfmonger-recorder.go $(GO_DEPS)
32
+ cd cmd/perfmonger-recorder && go build -o ../../$@ perfmonger-recorder.go
34
33
 
35
34
 
36
- ../lib/exec/perfmonger-player_darwin_amd64: perfmonger-player.go $(GO_DEPS)
37
- go build -o $@ perfmonger-player.go $(GO_SRC)
35
+ ../lib/exec/perfmonger-player_darwin_amd64: cmd/perfmonger-player/perfmonger-player.go $(GO_DEPS)
36
+ cd cmd/perfmonger-player && go build -o ../../$@ perfmonger-player.go
38
37
 
39
38
 
40
- ../lib/exec/perfmonger-viewer_darwin_amd64: perfmonger-viewer.go $(GO_DEPS)
41
- go build -o $@ perfmonger-viewer.go $(GO_SRC)
39
+ ../lib/exec/perfmonger-viewer_darwin_amd64: cmd/perfmonger-viewer/perfmonger-viewer.go $(GO_DEPS)
40
+ cd cmd/perfmonger-viewer && go build -o ../../$@ perfmonger-viewer.go
42
41
 
43
42
 
44
- ../lib/exec/perfmonger-summarizer_darwin_amd64: perfmonger-summarizer.go $(GO_DEPS)
45
- go build -o $@ perfmonger-summarizer.go $(GO_SRC)
43
+ ../lib/exec/perfmonger-summarizer_darwin_amd64: cmd/perfmonger-summarizer/perfmonger-summarizer.go $(GO_DEPS)
44
+ cd cmd/perfmonger-summarizer && go build -o ../../$@ perfmonger-summarizer.go
46
45
 
47
46
 
48
- ../lib/exec/perfmonger-plot-formatter_darwin_amd64: perfmonger-plot-formatter.go $(GO_DEPS)
49
- go build -o $@ perfmonger-plot-formatter.go $(GO_SRC)
47
+ ../lib/exec/perfmonger-plot-formatter_darwin_amd64: cmd/perfmonger-plot-formatter/perfmonger-plot-formatter.go $(GO_DEPS)
48
+ cd cmd/perfmonger-plot-formatter && go build -o ../../$@ perfmonger-plot-formatter.go
50
49
 
51
50
 
52
51
  build: ../lib/exec/perfmonger-recorder_linux_amd64 ../lib/exec/perfmonger-player_linux_amd64 ../lib/exec/perfmonger-viewer_linux_amd64 ../lib/exec/perfmonger-summarizer_linux_amd64 ../lib/exec/perfmonger-plot-formatter_linux_amd64 ../lib/exec/perfmonger-recorder_darwin_amd64 ../lib/exec/perfmonger-player_darwin_amd64 ../lib/exec/perfmonger-viewer_darwin_amd64 ../lib/exec/perfmonger-summarizer_darwin_amd64 ../lib/exec/perfmonger-plot-formatter_darwin_amd64
data/core/build.sh CHANGED
@@ -1,7 +1,6 @@
1
1
  #!/bin/bash
2
2
 
3
- READLINK=$(type -p greadlink readlink | head -1)
4
- cd $(dirname $($READLINK -f $0))
3
+ cd $(cd $(dirname $0); pwd)
5
4
 
6
5
  if [[ $1 = "-" ]]; then
7
6
  # do self build
@@ -33,7 +32,7 @@ fi
33
32
 
34
33
  set -e
35
34
 
36
- GO_DEPS=$(ls subsystem/*.go; ls utils.go)
35
+ GO_DEPS=$(ls subsystem/*.go utils.go)
37
36
 
38
37
  makefile=`mktemp`
39
38
 
@@ -42,7 +41,6 @@ cat <<EOF > $makefile
42
41
  # generated by build.sh
43
42
 
44
43
  GO_DEPS := $(echo ${GO_DEPS})
45
- GO_SRC := utils.go
46
44
 
47
45
  .PHONY: all build clean
48
46
 
@@ -62,8 +60,8 @@ for idx in $(seq 0 $((${#TARGET[@]}-1))); do
62
60
 
63
61
  cat <<EOF >> $makefile
64
62
 
65
- ../lib/exec/perfmonger-${subcmd}_${var_GOOS}_${var_GOARCH}: perfmonger-${subcmd}.go \$(GO_DEPS)
66
- go build -o \$@ perfmonger-$subcmd.go \$(GO_SRC)
63
+ ../lib/exec/perfmonger-${subcmd}_${var_GOOS}_${var_GOARCH}: cmd/perfmonger-${subcmd}/perfmonger-${subcmd}.go \$(GO_DEPS)
64
+ cd cmd/perfmonger-${subcmd} && go build -o ../../\$@ perfmonger-$subcmd.go
67
65
 
68
66
  EOF
69
67
  done
@@ -9,15 +9,19 @@ import (
9
9
  "fmt"
10
10
  "io"
11
11
  "os"
12
+ "regexp"
12
13
 
13
14
  projson "github.com/hayamiz/go-projson"
15
+ core "github.com/hayamiz/perfmonger/core"
14
16
  ss "github.com/hayamiz/perfmonger/core/subsystem"
15
17
  )
16
18
 
17
19
  type PlayerOption struct {
18
- logfile string
19
- color bool
20
- pretty bool
20
+ logfile string
21
+ color bool
22
+ pretty bool
23
+ disk_only string
24
+ disk_only_regex *regexp.Regexp
21
25
  }
22
26
 
23
27
  var option PlayerOption
@@ -49,10 +53,11 @@ func showInterruptStat(printer *projson.JsonPrinter, prev_rec *ss.StatRecord, cu
49
53
  return nil
50
54
  }
51
55
 
52
- func showDiskStat(printer *projson.JsonPrinter, prev_rec *ss.StatRecord, cur_rec *ss.StatRecord) error {
53
- dusage, err := ss.GetDiskUsage(
56
+ func showDiskStat(printer *projson.JsonPrinter, prev_rec *ss.StatRecord, cur_rec *ss.StatRecord, disk_only_regex *regexp.Regexp) error {
57
+ dusage, err := ss.GetDiskUsage1(
54
58
  prev_rec.Time, prev_rec.Disk,
55
- cur_rec.Time, cur_rec.Disk)
59
+ cur_rec.Time, cur_rec.Disk,
60
+ option.disk_only_regex)
56
61
  if err != nil {
57
62
  return err
58
63
  }
@@ -80,7 +85,22 @@ func showNetStat(printer *projson.JsonPrinter, prev_rec *ss.StatRecord, cur_rec
80
85
  return nil
81
86
  }
82
87
 
83
- func showStat(printer *projson.JsonPrinter, prev_rec *ss.StatRecord, cur_rec *ss.StatRecord) error {
88
+ func showMemStat(printer *projson.JsonPrinter, cur_rec *ss.StatRecord) error {
89
+ musage, err := ss.GetMemUsage(cur_rec.Mem)
90
+ if err != nil {
91
+ return err
92
+ }
93
+
94
+ printer.PutKey("mem")
95
+
96
+ musage.WriteJsonTo(printer)
97
+
98
+ return nil
99
+ }
100
+
101
+ func showStat(printer *projson.JsonPrinter, prev_rec *ss.StatRecord, cur_rec *ss.StatRecord,
102
+ disk_only_regex *regexp.Regexp) error {
103
+
84
104
  printer.Reset()
85
105
  if option.pretty {
86
106
  printer.SetStyle(projson.SmartStyle)
@@ -88,6 +108,7 @@ func showStat(printer *projson.JsonPrinter, prev_rec *ss.StatRecord, cur_rec *ss
88
108
  if option.color {
89
109
  printer.SetColor(true)
90
110
  }
111
+
91
112
  printer.BeginObject()
92
113
  printer.PutKey("time")
93
114
  printer.PutFloatFmt(float64(cur_rec.Time.UnixNano())/1e9, "%.3f")
@@ -108,7 +129,7 @@ func showStat(printer *projson.JsonPrinter, prev_rec *ss.StatRecord, cur_rec *ss
108
129
  }
109
130
  }
110
131
  if cur_rec.Disk != nil {
111
- err := showDiskStat(printer, prev_rec, cur_rec)
132
+ err := showDiskStat(printer, prev_rec, cur_rec, disk_only_regex)
112
133
  if err != nil {
113
134
  return err
114
135
  }
@@ -119,6 +140,12 @@ func showStat(printer *projson.JsonPrinter, prev_rec *ss.StatRecord, cur_rec *ss
119
140
  return err
120
141
  }
121
142
  }
143
+ if cur_rec.Mem != nil {
144
+ err := showMemStat(printer, cur_rec)
145
+ if err != nil {
146
+ return err
147
+ }
148
+ }
122
149
 
123
150
  printer.FinishObject()
124
151
 
@@ -128,9 +155,25 @@ func showStat(printer *projson.JsonPrinter, prev_rec *ss.StatRecord, cur_rec *ss
128
155
  func parseArgs() {
129
156
  flag.BoolVar(&option.color, "color", false, "Use colored JSON output")
130
157
  flag.BoolVar(&option.pretty, "pretty", false, "Use human readable JSON output")
158
+ flag.StringVar(&option.disk_only, "disk-only", "", "Select disk devices by regex")
131
159
 
132
160
  flag.Parse()
133
161
 
162
+ if len(flag.Args()) < 1 {
163
+ fmt.Fprintln(os.Stderr, "Insufficient argument")
164
+ os.Exit(1)
165
+ }
166
+
167
+ option.disk_only_regex = nil
168
+
169
+ if option.disk_only != "" {
170
+ var err error
171
+ option.disk_only_regex, err = regexp.Compile(option.disk_only)
172
+ if err != nil {
173
+ panic(err)
174
+ }
175
+ }
176
+
134
177
  option.logfile = flag.Arg(0)
135
178
  }
136
179
 
@@ -150,7 +193,7 @@ func main() {
150
193
  in = f
151
194
  defer f.Close()
152
195
  }
153
- input_reader := newPerfmongerLogReader(in)
196
+ input_reader := core.NewPerfmongerLogReader(in)
154
197
  dec := gob.NewDecoder(input_reader)
155
198
 
156
199
  out = bufio.NewWriter(os.Stdout)
@@ -199,7 +242,7 @@ func main() {
199
242
  panic(err)
200
243
  }
201
244
 
202
- err = showStat(printer, prev_rec, cur_rec)
245
+ err = showStat(printer, prev_rec, cur_rec, option.disk_only_regex)
203
246
  if err != nil {
204
247
  printer.Reset()
205
248
  fmt.Fprintln(os.Stderr, "skip by err")
@@ -0,0 +1,24 @@
1
+ # perfmonger-plot-formatter
2
+
3
+ `perfmonger-plot-formatter` is a command to generate data files for plotting
4
+ various metrices recorded by `perfmonger-recorder`.
5
+
6
+ ## Notes on memory usage records
7
+
8
+ ### `free(1)` compatible summarization
9
+
10
+ - total: `MemStat.MemTotal`
11
+ - used: `if (memUsed < 0) { MemStat.MemTotal - MemStat.MemFree } else { memUsed }`
12
+ - memUsed := `MemStat.MemTotal - MemStat.MemFree - mainCached - MemStat.Buffers`
13
+ - mainCached := `MemStat.Cached + MemStat.SReclaimable`
14
+ - free: `MemStat.MemFree`
15
+ - shared: `MemStat.Shmem`
16
+ - buffers: `MemStat.Buffers`
17
+ - cache: `mainCached`
18
+ - mainCached := `MemStat.Cached + MemStat.SReclaimable`
19
+ - available: `MemStat.MemAvailable`
20
+
21
+ ### Additional info
22
+
23
+ - hugeTotal: `MemStat.HugePages_Total`
24
+ - hugeUsed: `MemStat.HugePages_Total - MemStat.HugePages_Free`
@@ -13,13 +13,16 @@ import (
13
13
  "os"
14
14
  "regexp"
15
15
  "sort"
16
+ "strings"
16
17
 
18
+ "github.com/hayamiz/perfmonger/core"
17
19
  ss "github.com/hayamiz/perfmonger/core/subsystem"
18
20
  )
19
21
 
20
22
  type CmdOption struct {
21
23
  DiskFile string
22
24
  CpuFile string
25
+ MemFile string
23
26
  PerfmongerFile string
24
27
  disk_only string
25
28
  disk_only_regex *regexp.Regexp
@@ -30,8 +33,9 @@ func parseArgs() *CmdOption {
30
33
 
31
34
  opt := new(CmdOption)
32
35
 
33
- flag.StringVar(&opt.DiskFile, "diskfile", "./disk.dat", "Disk performance data file")
34
- flag.StringVar(&opt.CpuFile, "cpufile", "./cpu.dat", "CPU performance data file")
36
+ flag.StringVar(&opt.DiskFile, "diskfile", "./disk.dat", "Disk usage data file for gnuplot")
37
+ flag.StringVar(&opt.CpuFile, "cpufile", "./cpu.dat", "CPU usage data file for gnuplot")
38
+ flag.StringVar(&opt.MemFile, "memfile", "./mem.dat", "Memory usage data file for gnuplot")
35
39
  flag.StringVar(&opt.PerfmongerFile, "perfmonger", "", "Perfmonger log file")
36
40
  flag.StringVar(&opt.disk_only, "disk-only",
37
41
  "", "Select disk devices by regex")
@@ -79,6 +83,13 @@ type DiskDatTmpFile struct {
79
83
  Idx int
80
84
  }
81
85
 
86
+ type MemDatTmpFile struct {
87
+ Name string
88
+ Path string
89
+ File *os.File
90
+ Writer *bufio.Writer
91
+ }
92
+
82
93
  type CpuDatTmpFile struct {
83
94
  CoreId int
84
95
  Path string
@@ -117,6 +128,20 @@ func makeCpuDatTmpFile(coreid int) *CpuDatTmpFile {
117
128
  return ret
118
129
  }
119
130
 
131
+ func makeMemDatTmpFile() *MemDatTmpFile {
132
+ ret := new(MemDatTmpFile)
133
+
134
+ f, err := ioutil.TempFile("", "perfmonger-mem")
135
+ if err != nil {
136
+ panic(err)
137
+ }
138
+ ret.File = f
139
+ ret.Path = f.Name()
140
+ ret.Writer = bufio.NewWriter(f)
141
+
142
+ return ret
143
+ }
144
+
120
145
  func printCoreUsage(writer *bufio.Writer, elapsed_time float64, coreusage *ss.CpuCoreUsage) {
121
146
  writer.WriteString(
122
147
  fmt.Sprintf("%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\n",
@@ -132,6 +157,80 @@ func printCoreUsage(writer *bufio.Writer, elapsed_time float64, coreusage *ss.Cp
132
157
  coreusage.Idle))
133
158
  }
134
159
 
160
+ func printMemUsage(writer *bufio.Writer, elapsed_time float64, mem *ss.MemStat) {
161
+ if mem == nil {
162
+ writer.WriteString("#")
163
+ writer.WriteString(
164
+ strings.Join([]string{
165
+ "elapsed_time", // 1
166
+ "mem_total", // 2
167
+ "mem_used", // 3
168
+ "mem_free", // 4
169
+ "buffers", // 5
170
+ "cached", // 6
171
+ "swap_cached", // 7
172
+ "active", // 8
173
+ "inactive", // 9
174
+ "swap_total", // 10
175
+ "swap_free", // 11
176
+ "dirty", // 12
177
+ "writeback", // 13
178
+ "anon_pages", // 14
179
+ "mapped", // 15
180
+ "shmem", // 16
181
+ "slab", // 17
182
+ "s_reclaimable", // 18
183
+ "s_unreclaim", // 19
184
+ "kernel_stack", // 20
185
+ "page_tables", // 21
186
+ "nfs_unstable", // 22
187
+ "bounce", // 23
188
+ "commit_limit", // 24
189
+ "committed_as", // 25
190
+ "anon_huge_pages", // 26
191
+ "huge_pages_total", // 27
192
+ "huge_pages_free", // 28
193
+ "huge_pages_rsvd", // 29
194
+ "huge_pages_surp", // 30
195
+ "hugepagesize"}, // 31
196
+ "\t"))
197
+ writer.WriteString("\n")
198
+ } else {
199
+ writer.WriteString(fmt.Sprintf("%f\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n",
200
+ elapsed_time,
201
+ mem.MemTotal,
202
+ mem.MemTotal-mem.MemFree-mem.Buffers-mem.Cached-mem.SReclaimable,
203
+ mem.MemFree,
204
+ mem.Buffers,
205
+ mem.Cached,
206
+ mem.SwapCached,
207
+ mem.Active,
208
+ mem.Inactive,
209
+ mem.SwapTotal,
210
+ mem.SwapFree,
211
+ mem.Dirty,
212
+ mem.Writeback,
213
+ mem.AnonPages,
214
+ mem.Mapped,
215
+ mem.Shmem,
216
+ mem.Slab,
217
+ mem.SReclaimable,
218
+ mem.SUnreclaim,
219
+ mem.KernelStack,
220
+ mem.PageTables,
221
+ mem.NFS_Unstable,
222
+ mem.Bounce,
223
+ mem.CommitLimit,
224
+ mem.Committed_AS,
225
+ mem.AnonHugePages,
226
+ mem.HugePages_Total,
227
+ mem.HugePages_Free,
228
+ mem.HugePages_Rsvd,
229
+ mem.HugePages_Surp,
230
+ mem.Hugepagesize))
231
+ }
232
+ }
233
+
135
234
  func main() {
136
235
  opt := parseArgs()
137
236
 
@@ -141,7 +240,7 @@ func main() {
141
240
  }
142
241
  defer f.Close()
143
242
 
144
- input_reader := newPerfmongerLogReader(f)
243
+ input_reader := core.NewPerfmongerLogReader(f)
145
244
  dec := gob.NewDecoder(input_reader)
146
245
 
147
246
  var cheader ss.CommonHeader
@@ -192,6 +291,13 @@ func main() {
192
291
  cpu_writer.WriteString("# All cpu usage\n")
193
292
  cpu_writer.WriteString("# elapsed_time %usr %nice %sys %iowait %hardirq %softirq %steal %guest %idle\n")
194
293
 
294
+ f, err = os.Create(opt.MemFile)
295
+ if err != nil {
296
+ panic(err)
297
+ }
298
+ defer f.Close()
299
+ mem_writer := bufio.NewWriter(f)
300
+
195
301
  for {
196
302
  prev_rec := &records[curr^1]
197
303
  cur_rec := &records[curr]
@@ -283,6 +389,12 @@ func main() {
283
389
  }
284
390
  printCoreUsage(cpu_writer, prev_rec.Time.Sub(t0).Seconds(), cusage.All)
285
391
 
392
+ if !meta_set {
393
+ // print column labels
394
+ printMemUsage(mem_writer, prev_rec.Time.Sub(t0).Seconds(), nil)
395
+ }
396
+ printMemUsage(mem_writer, prev_rec.Time.Sub(t0).Seconds(), cur_rec.Mem)
397
+
286
398
  curr ^= 1
287
399
  meta_set = true
288
400
  }
@@ -331,6 +443,7 @@ func main() {
331
443
  os.Remove(cpu_dat.Path)
332
444
  }
333
445
  cpu_writer.Flush()
446
+ mem_writer.Flush()
334
447
 
335
448
  json_enc := json.NewEncoder(os.Stdout)
336
449
  json_enc.Encode(meta)