perfmonger 0.12.0 → 0.14.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/NEWS +25 -1
- data/Rakefile +18 -7
- data/core/Makefile +20 -21
- data/core/build.sh +4 -6
- data/core/{perfmonger-player.go → cmd/perfmonger-player/perfmonger-player.go} +34 -10
- data/core/cmd/perfmonger-plot-formatter/README.md +24 -0
- data/core/{perfmonger-plot-formatter.go → cmd/perfmonger-plot-formatter/perfmonger-plot-formatter.go} +116 -3
- data/core/{perfmonger-recorder.go → cmd/perfmonger-recorder/perfmonger-recorder.go} +0 -0
- data/core/{perfmonger-summarizer.go → cmd/perfmonger-summarizer/perfmonger-summarizer.go} +3 -1
- data/core/{perfmonger-viewer.go → cmd/perfmonger-viewer/perfmonger-viewer.go} +0 -0
- data/core/go.mod +10 -0
- data/core/go.sum +17 -0
- data/core/subsystem/perfmonger_linux.go +2 -0
- data/core/subsystem/stat.go +2 -0
- data/core/utils.go +2 -2
- data/lib/exec/perfmonger-player_darwin_amd64 +0 -0
- data/lib/exec/perfmonger-player_linux_amd64 +0 -0
- data/lib/exec/perfmonger-plot-formatter_darwin_amd64 +0 -0
- data/lib/exec/perfmonger-plot-formatter_linux_amd64 +0 -0
- data/lib/exec/perfmonger-recorder_darwin_amd64 +0 -0
- data/lib/exec/perfmonger-recorder_linux_amd64 +0 -0
- data/lib/exec/perfmonger-summarizer_darwin_amd64 +0 -0
- data/lib/exec/perfmonger-summarizer_linux_amd64 +0 -0
- data/lib/exec/perfmonger-viewer_darwin_amd64 +0 -0
- data/lib/exec/perfmonger-viewer_linux_amd64 +0 -0
- data/lib/perfmonger/command/play.rb +10 -0
- data/lib/perfmonger/command/plot.rb +144 -2
- data/lib/perfmonger/command/record.rb +23 -2
- data/lib/perfmonger/version.rb +1 -1
- metadata +10 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 42856e6da789b3ad1a522b95bc642bdf7abe1e2fb7679e4839b7da7e3157b6a9
|
4
|
+
data.tar.gz: 937b2f2557ad06fe36e230c623ab07773d17bc1dd278e80b87bb8fb881a9427c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4f06a76145f4f4aafd9f4fa8e2de7ef855190729d25b98a6ab36a8bcbcb1ee41242736e96b3c15693ffeb341ee229f3852f00f36b27785b84124e587fdcfad41
|
7
|
+
data.tar.gz: 86b957bb0edbf89f0cb7904b0059d75db11366eb26ca1b1112cd4c7566aa896240dc430d4d56a177c00c4862ebbf677f73f3447bda9e798226d7fcbf60836408
|
data/NEWS
CHANGED
@@ -1,4 +1,28 @@
|
|
1
|
-
##
|
1
|
+
## 2021-XX-XX: PerfMonger 0.15.0
|
2
|
+
|
3
|
+
## 2021-12-01: PerfMonger 0.14.1
|
4
|
+
* Changes
|
5
|
+
* [plot] subcommand:
|
6
|
+
* Skip plotting memory usage if it is not recorded
|
7
|
+
|
8
|
+
## 2021-07-27: PerfMonger 0.14.0
|
9
|
+
* New features
|
10
|
+
* [plot] subcommand:
|
11
|
+
* Added memory usage plot
|
12
|
+
* Changes
|
13
|
+
* [record] subcommand:
|
14
|
+
* Additionaly record 'Hugepagesize' in memory usage
|
15
|
+
|
16
|
+
## 2021-07-26: PerfMonger 0.13.1
|
17
|
+
* New features
|
18
|
+
* [play] subcommand:
|
19
|
+
* Added --disk-only option to filter results of not interesting disks
|
20
|
+
* Note: v0.13.0 is yanked from rubygems.org
|
21
|
+
|
22
|
+
## 2021-07-08: PerfMonger 0.12.1
|
23
|
+
* Bug fixes
|
24
|
+
* [record] subcommand:
|
25
|
+
* --kill waits until a recorder process surely exits
|
2
26
|
|
3
27
|
## 2021-05-10: PerfMonger 0.12.0
|
4
28
|
* New features
|
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
|
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
|
-
|
43
|
-
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
-
|
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
|
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
|
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
|
19
|
-
color
|
20
|
-
pretty
|
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.
|
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
|
}
|
@@ -93,7 +98,9 @@ func showMemStat(printer *projson.JsonPrinter, cur_rec *ss.StatRecord) error {
|
|
93
98
|
return nil
|
94
99
|
}
|
95
100
|
|
96
|
-
func showStat(printer *projson.JsonPrinter, prev_rec *ss.StatRecord, cur_rec *ss.StatRecord
|
101
|
+
func showStat(printer *projson.JsonPrinter, prev_rec *ss.StatRecord, cur_rec *ss.StatRecord,
|
102
|
+
disk_only_regex *regexp.Regexp) error {
|
103
|
+
|
97
104
|
printer.Reset()
|
98
105
|
if option.pretty {
|
99
106
|
printer.SetStyle(projson.SmartStyle)
|
@@ -101,6 +108,7 @@ func showStat(printer *projson.JsonPrinter, prev_rec *ss.StatRecord, cur_rec *ss
|
|
101
108
|
if option.color {
|
102
109
|
printer.SetColor(true)
|
103
110
|
}
|
111
|
+
|
104
112
|
printer.BeginObject()
|
105
113
|
printer.PutKey("time")
|
106
114
|
printer.PutFloatFmt(float64(cur_rec.Time.UnixNano())/1e9, "%.3f")
|
@@ -121,7 +129,7 @@ func showStat(printer *projson.JsonPrinter, prev_rec *ss.StatRecord, cur_rec *ss
|
|
121
129
|
}
|
122
130
|
}
|
123
131
|
if cur_rec.Disk != nil {
|
124
|
-
err := showDiskStat(printer, prev_rec, cur_rec)
|
132
|
+
err := showDiskStat(printer, prev_rec, cur_rec, disk_only_regex)
|
125
133
|
if err != nil {
|
126
134
|
return err
|
127
135
|
}
|
@@ -147,9 +155,25 @@ func showStat(printer *projson.JsonPrinter, prev_rec *ss.StatRecord, cur_rec *ss
|
|
147
155
|
func parseArgs() {
|
148
156
|
flag.BoolVar(&option.color, "color", false, "Use colored JSON output")
|
149
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")
|
150
159
|
|
151
160
|
flag.Parse()
|
152
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
|
+
|
153
177
|
option.logfile = flag.Arg(0)
|
154
178
|
}
|
155
179
|
|
@@ -169,7 +193,7 @@ func main() {
|
|
169
193
|
in = f
|
170
194
|
defer f.Close()
|
171
195
|
}
|
172
|
-
input_reader :=
|
196
|
+
input_reader := core.NewPerfmongerLogReader(in)
|
173
197
|
dec := gob.NewDecoder(input_reader)
|
174
198
|
|
175
199
|
out = bufio.NewWriter(os.Stdout)
|
@@ -218,7 +242,7 @@ func main() {
|
|
218
242
|
panic(err)
|
219
243
|
}
|
220
244
|
|
221
|
-
err = showStat(printer, prev_rec, cur_rec)
|
245
|
+
err = showStat(printer, prev_rec, cur_rec, option.disk_only_regex)
|
222
246
|
if err != nil {
|
223
247
|
printer.Reset()
|
224
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
|
34
|
-
flag.StringVar(&opt.CpuFile, "cpufile", "./cpu.dat", "CPU
|
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 :=
|
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)
|
File without changes
|
@@ -12,6 +12,7 @@ import (
|
|
12
12
|
"sort"
|
13
13
|
|
14
14
|
projson "github.com/hayamiz/go-projson"
|
15
|
+
"github.com/hayamiz/perfmonger/core"
|
15
16
|
ss "github.com/hayamiz/perfmonger/core/subsystem"
|
16
17
|
)
|
17
18
|
|
@@ -38,6 +39,7 @@ func parseArgs() {
|
|
38
39
|
flag.Parse()
|
39
40
|
|
40
41
|
if len(flag.Args()) < 1 {
|
42
|
+
fmt.Fprintln(os.Stderr, "Insufficient argument")
|
41
43
|
os.Exit(1)
|
42
44
|
}
|
43
45
|
|
@@ -61,7 +63,7 @@ func main() {
|
|
61
63
|
}
|
62
64
|
defer f.Close()
|
63
65
|
|
64
|
-
input_reader :=
|
66
|
+
input_reader := core.NewPerfmongerLogReader(f)
|
65
67
|
dec := gob.NewDecoder(input_reader)
|
66
68
|
|
67
69
|
err = dec.Decode(&cheader)
|
File without changes
|
data/core/go.mod
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
module github.com/hayamiz/perfmonger/core
|
2
|
+
|
3
|
+
go 1.15
|
4
|
+
|
5
|
+
require (
|
6
|
+
github.com/hayamiz/go-projson v0.0.0-20210510072849-3503bd24ae61
|
7
|
+
github.com/jroimartin/gocui v0.4.0
|
8
|
+
github.com/nsf/termbox-go v1.1.1
|
9
|
+
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a
|
10
|
+
)
|
data/core/go.sum
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
github.com/hayamiz/go-projson v0.0.0-20210510072849-3503bd24ae61 h1:elFR/pEri9bFREP6YvJQDcFjncPBDhG+SwWJjYSvY8s=
|
2
|
+
github.com/hayamiz/go-projson v0.0.0-20210510072849-3503bd24ae61/go.mod h1:Zkuug8uJZoQ8V34UfDAFVmKLVHPhe+TJUAazUzh6s1k=
|
3
|
+
github.com/jroimartin/gocui v0.4.0 h1:52jnalstgmc25FmtGcWqa0tcbMEWS6RpFLsOIO+I+E8=
|
4
|
+
github.com/jroimartin/gocui v0.4.0/go.mod h1:7i7bbj99OgFHzo7kB2zPb8pXLqMBSQegY7azfqXMkyY=
|
5
|
+
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
|
6
|
+
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
7
|
+
github.com/nsf/termbox-go v1.1.1 h1:nksUPLCb73Q++DwbYUBEglYBRPZyoXJdrj5L+TkjyZY=
|
8
|
+
github.com/nsf/termbox-go v1.1.1/go.mod h1:T0cTdVuOwf7pHQNtfhnEbzHbcNyCEcVU4YPpouCbVxo=
|
9
|
+
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a h1:kr2P4QFmQr29mSLA43kwrOcgcReGTfbE9N577tCTuBc=
|
10
|
+
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
11
|
+
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
12
|
+
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw=
|
13
|
+
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
14
|
+
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
|
15
|
+
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
16
|
+
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
17
|
+
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
@@ -469,6 +469,8 @@ func ReadMemStat(record *StatRecord) error {
|
|
469
469
|
mem_stat.HugePages_Free = val
|
470
470
|
case "HugePages_Total:":
|
471
471
|
mem_stat.HugePages_Total = val
|
472
|
+
case "Hugepagesize:":
|
473
|
+
mem_stat.Hugepagesize = val
|
472
474
|
case "AnonHugePages:":
|
473
475
|
mem_stat.AnonHugePages = val
|
474
476
|
case "Committed_AS:":
|
data/core/subsystem/stat.go
CHANGED
@@ -132,6 +132,7 @@ type MemStat struct {
|
|
132
132
|
HugePages_Free int64
|
133
133
|
HugePages_Rsvd int64
|
134
134
|
HugePages_Surp int64
|
135
|
+
Hugepagesize int64
|
135
136
|
}
|
136
137
|
|
137
138
|
type StatRecord struct {
|
@@ -286,6 +287,7 @@ func (entry *MemStat) Clear() {
|
|
286
287
|
entry.HugePages_Free = 0
|
287
288
|
entry.HugePages_Rsvd = 0
|
288
289
|
entry.HugePages_Surp = 0
|
290
|
+
entry.Hugepagesize = 0
|
289
291
|
}
|
290
292
|
|
291
293
|
func NewStatRecord() *StatRecord {
|
data/core/utils.go
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
package
|
1
|
+
package core
|
2
2
|
|
3
3
|
import (
|
4
4
|
"bufio"
|
@@ -6,7 +6,7 @@ import (
|
|
6
6
|
"io"
|
7
7
|
)
|
8
8
|
|
9
|
-
func
|
9
|
+
func NewPerfmongerLogReader(source io.Reader) io.Reader {
|
10
10
|
var ret io.Reader
|
11
11
|
reader := bufio.NewReader(source)
|
12
12
|
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -26,6 +26,10 @@ EOS
|
|
26
26
|
@pretty = true
|
27
27
|
end
|
28
28
|
|
29
|
+
@disk_only_regex = nil
|
30
|
+
@parser.on('--disk-only REGEX', "Select disk devices that matches REGEX (Ex. 'sd[b-d]')") do |regex|
|
31
|
+
@disk_only_regex = regex
|
32
|
+
end
|
29
33
|
end
|
30
34
|
|
31
35
|
def parse_args(argv)
|
@@ -62,6 +66,12 @@ EOS
|
|
62
66
|
if @pretty
|
63
67
|
cmd << "-pretty"
|
64
68
|
end
|
69
|
+
|
70
|
+
if @disk_only_regex
|
71
|
+
cmd << "-disk-only"
|
72
|
+
cmd << @disk_only_regex
|
73
|
+
end
|
74
|
+
|
65
75
|
cmd << @logfile
|
66
76
|
|
67
77
|
Process.exec(*cmd)
|
@@ -145,10 +145,13 @@ EOS
|
|
145
145
|
|
146
146
|
@disk_dat = File.expand_path("disk.dat", @tmpdir)
|
147
147
|
@cpu_dat = File.expand_path("cpu.dat", @tmpdir)
|
148
|
+
@mem_dat = File.expand_path("mem.dat", @tmpdir)
|
148
149
|
|
149
150
|
meta_json = nil
|
150
|
-
cmd = [formatter_bin, "-perfmonger", @data_file,
|
151
|
-
|
151
|
+
cmd = [formatter_bin, "-perfmonger", @data_file,
|
152
|
+
"-cpufile", @cpu_dat,
|
153
|
+
"-diskfile", @disk_dat,
|
154
|
+
"-memfile", @mem_dat]
|
152
155
|
if @disk_only_regex
|
153
156
|
cmd << "-disk-only"
|
154
157
|
cmd << @disk_only
|
@@ -164,6 +167,7 @@ EOS
|
|
164
167
|
|
165
168
|
plot_disk(meta)
|
166
169
|
plot_cpu(meta)
|
170
|
+
plot_mem(meta)
|
167
171
|
|
168
172
|
FileUtils.rm_rf(@tmpdir)
|
169
173
|
|
@@ -508,6 +512,144 @@ EOS
|
|
508
512
|
end
|
509
513
|
end # def
|
510
514
|
|
515
|
+
def plot_mem(meta)
|
516
|
+
pdf_filename = @output_prefix + 'mem.pdf'
|
517
|
+
gp_filename = @output_prefix + 'mem.gp'
|
518
|
+
dat_filename = @output_prefix + 'mem.dat'
|
519
|
+
|
520
|
+
unless File.exists?(dat_filename)
|
521
|
+
$stderr.puts("WARN: memory usage info is not available.")
|
522
|
+
return
|
523
|
+
end
|
524
|
+
|
525
|
+
if @output_type != 'pdf'
|
526
|
+
img_filename = @output_prefix + 'cpu.' + @output_type
|
527
|
+
else
|
528
|
+
img_filename = nil
|
529
|
+
end
|
530
|
+
|
531
|
+
start_time = meta["start_time"]
|
532
|
+
end_time = meta["end_time"]
|
533
|
+
|
534
|
+
mem_scaling = 2.0**20 # KB -> GB
|
535
|
+
|
536
|
+
# "elapsed_time", // 1
|
537
|
+
# "mem_total", // 2
|
538
|
+
# "mem_used", // 3
|
539
|
+
# "mem_free", // 4
|
540
|
+
# "buffers", // 5
|
541
|
+
# "cached", // 6
|
542
|
+
# "swap_cached", // 7
|
543
|
+
# "active", // 8
|
544
|
+
# "inactive", // 9
|
545
|
+
# "swap_total", // 10
|
546
|
+
# "swap_free", // 11
|
547
|
+
# "dirty", // 12
|
548
|
+
# "writeback", // 13
|
549
|
+
# "anon_pages", // 14
|
550
|
+
# "mapped", // 15
|
551
|
+
# "shmem", // 16
|
552
|
+
# "slab", // 17
|
553
|
+
# "s_reclaimable", // 18
|
554
|
+
# "s_unreclaim", // 19
|
555
|
+
# "kernel_stack", // 20
|
556
|
+
# "page_tables", // 21
|
557
|
+
# "nfs_unstable", // 22
|
558
|
+
# "bounce", // 23
|
559
|
+
# "commit_limit", // 24
|
560
|
+
# "committed_as", // 25
|
561
|
+
# "anon_huge_pages", // 26
|
562
|
+
# "huge_pages_total", // 27
|
563
|
+
# "huge_pages_free", // 28
|
564
|
+
# "huge_pages_rsvd", // 29
|
565
|
+
# "huge_pages_surp"}, // 30
|
566
|
+
# "hugepagesize"}, // 31
|
567
|
+
|
568
|
+
Dir.chdir(@tmpdir) do
|
569
|
+
total = `tail -n+2 #{dat_filename}|head -n1`.split[1].to_f
|
570
|
+
if total == 0.0
|
571
|
+
raise RuntimeError.new("Failed to get MemTotal value from mem.dat file: #{dat_filename}")
|
572
|
+
end
|
573
|
+
|
574
|
+
gpfile = File.open(gp_filename, 'w')
|
575
|
+
|
576
|
+
pdf_file = File.join(@output_dir, "mem.pdf")
|
577
|
+
gpfile.puts <<EOS
|
578
|
+
set term pdfcairo enhanced color size 6in,2.5in
|
579
|
+
set title "Memory usage"
|
580
|
+
set output "#{pdf_filename}"
|
581
|
+
set key outside center bottom horizontal
|
582
|
+
set size 1.0, 1.0
|
583
|
+
|
584
|
+
set xlabel "elapsed time [sec]"
|
585
|
+
set ylabel "memory usage [GB]"
|
586
|
+
|
587
|
+
# scaling
|
588
|
+
s = #{mem_scaling}
|
589
|
+
|
590
|
+
set grid
|
591
|
+
set xrange [#{@offset_time}:#{end_time - start_time}]
|
592
|
+
set yrange [0:#{total * 1.2}/s]
|
593
|
+
|
594
|
+
# line styles
|
595
|
+
set style line 1 lt 1 lc rgb '#66C2A5' # teal
|
596
|
+
set style line 2 lt 1 lc rgb '#FC8D62' # orange
|
597
|
+
set style line 3 lt 1 lc rgb '#8DA0CB' # lilac
|
598
|
+
set style line 4 lt 1 lc rgb '#E78AC3' # magentat
|
599
|
+
set style line 5 lt 1 lc rgb '#A6D854' # lime green
|
600
|
+
set style line 6 lt 1 lc rgb '#FFD92F' # banana
|
601
|
+
set style line 7 lt 1 lc rgb '#E5C494' # tan
|
602
|
+
set style line 8 lt 1 lc rgb '#B3B3B3' # grey
|
603
|
+
|
604
|
+
# palette
|
605
|
+
set palette maxcolors 8
|
606
|
+
set palette defined ( 0 '#66C2A5',\
|
607
|
+
1 '#FC8D62',\
|
608
|
+
2 '#8DA0CB',\
|
609
|
+
3 '#E78AC3',\
|
610
|
+
4 '#A6D854',\
|
611
|
+
5 '#FFD92F',\
|
612
|
+
6 '#E5C494',\
|
613
|
+
7 '#B3B3B3' )
|
614
|
+
|
615
|
+
used(total, free, cached, buffers, srecl) = \\
|
616
|
+
( (total - free - cache(cached, srecl) - buffers < 0) ? \\
|
617
|
+
(total - free) : \\
|
618
|
+
(total - free - cache(cached, srecl) - buffers) )
|
619
|
+
|
620
|
+
cache(cached, srecl) = cached + srecl
|
621
|
+
|
622
|
+
plot "#{dat_filename}" usi 1:($4/s+$5/s+cache($6, $18)/s+$16/s+used($2, $4, $6, $5, $18)/s) wi filledcurves x1 ls 8 ti "free", \\
|
623
|
+
"#{dat_filename}" usi 1:($5/s+cache($6, $18)/s+$16/s+used($2, $4, $6, $5, $18)/s) wi filledcurves x1 ls 3 ti "buffers", \\
|
624
|
+
"#{dat_filename}" usi 1:(cache($6, $18)/s+$16/s+used($2, $4, $6, $5, $18)/s) wi filledcurves x1 ls 5 ti "cached", \\
|
625
|
+
"#{dat_filename}" usi 1:($16/s+used($2, $4, $6, $5, $18)/s) wi filledcurves x1 ls 6 ti "shared", \\
|
626
|
+
"#{dat_filename}" usi 1:(used($2, $4, $6, $5, $18)/s) wi filledcurves x1 ls 2 ti "used", \\
|
627
|
+
"#{dat_filename}" usi 1:(($27-$28)*$31/s) wi lines dt (4,4) lc rgb 'black' lw 2.5 ti 'used (hugepage)'
|
628
|
+
|
629
|
+
EOS
|
630
|
+
|
631
|
+
gpfile.close
|
632
|
+
system("gnuplot #{gpfile.path}")
|
633
|
+
|
634
|
+
if @output_type != 'pdf'
|
635
|
+
system("convert -density 150 -background white #{pdf_filename} #{img_filename}")
|
636
|
+
end
|
637
|
+
end # chdir
|
638
|
+
|
639
|
+
copy_targets = []
|
640
|
+
copy_targets << pdf_filename
|
641
|
+
copy_targets << img_filename if img_filename
|
642
|
+
|
643
|
+
if @save_gpfiles
|
644
|
+
copy_targets << gp_filename
|
645
|
+
copy_targets << dat_filename
|
646
|
+
end
|
647
|
+
|
648
|
+
copy_targets.each do |target|
|
649
|
+
FileUtils.copy(File.join(@tmpdir, target), @output_dir)
|
650
|
+
end
|
651
|
+
end # def
|
652
|
+
|
511
653
|
private
|
512
654
|
def factors(n)
|
513
655
|
(2..([n, n / 2].max).to_i).select do |x|
|
@@ -31,7 +31,8 @@ class RecordCommand < BaseCommand
|
|
31
31
|
if @option.kill
|
32
32
|
unless session_pid
|
33
33
|
# There is nothing to be killed
|
34
|
-
|
34
|
+
$stderr.puts("[ERROR] No perfmonger record session is running.")
|
35
|
+
return false
|
35
36
|
end
|
36
37
|
|
37
38
|
begin
|
@@ -44,12 +45,32 @@ class RecordCommand < BaseCommand
|
|
44
45
|
f.flock(File::LOCK_UN)
|
45
46
|
end
|
46
47
|
end
|
48
|
+
|
49
|
+
# wait until the process surely exits
|
50
|
+
sleeptime = 0.05
|
51
|
+
try = 0
|
52
|
+
while true
|
53
|
+
begin
|
54
|
+
Process.kill(:INT, session_pid)
|
55
|
+
rescue Errno::ESRCH
|
56
|
+
# no such process
|
57
|
+
break
|
58
|
+
end
|
59
|
+
sleep(sleeptime)
|
60
|
+
sleeptime *= 2
|
61
|
+
try += 1
|
62
|
+
if try >= 5
|
63
|
+
$stderr.puts("[ERROR] Cannot stop perfmonger record session correctly. PID=#{session_pid}")
|
64
|
+
return false
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
47
68
|
return true
|
48
69
|
end
|
49
70
|
|
50
71
|
if @option.status
|
51
72
|
unless session_pid
|
52
|
-
puts "[ERROR] No perfmonger
|
73
|
+
puts "[ERROR] No perfmonger record session is running."
|
53
74
|
return false
|
54
75
|
end
|
55
76
|
|
data/lib/perfmonger/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: perfmonger
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.14.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yuto HAYAMIZU
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-12-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -101,11 +101,14 @@ files:
|
|
101
101
|
- Rakefile
|
102
102
|
- core/Makefile
|
103
103
|
- core/build.sh
|
104
|
-
- core/perfmonger-player.go
|
105
|
-
- core/perfmonger-plot-formatter.
|
106
|
-
- core/perfmonger-
|
107
|
-
- core/perfmonger-
|
108
|
-
- core/perfmonger-
|
104
|
+
- core/cmd/perfmonger-player/perfmonger-player.go
|
105
|
+
- core/cmd/perfmonger-plot-formatter/README.md
|
106
|
+
- core/cmd/perfmonger-plot-formatter/perfmonger-plot-formatter.go
|
107
|
+
- core/cmd/perfmonger-recorder/perfmonger-recorder.go
|
108
|
+
- core/cmd/perfmonger-summarizer/perfmonger-summarizer.go
|
109
|
+
- core/cmd/perfmonger-viewer/perfmonger-viewer.go
|
110
|
+
- core/go.mod
|
111
|
+
- core/go.sum
|
109
112
|
- core/subsystem/Makefile
|
110
113
|
- core/subsystem/perfmonger.go
|
111
114
|
- core/subsystem/perfmonger_darwin.go
|