perfmonger 0.11.2 → 0.14.0

Sign up to get free protection for your applications and to get access to all the features.
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)