perfmonger 0.12.1 → 0.14.2
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.
- checksums.yaml +4 -4
- data/NEWS +25 -1
- data/core/cmd/perfmonger-player/perfmonger-player.go +34 -12
- data/core/cmd/perfmonger-plot-formatter/README.md +24 -0
- data/core/cmd/perfmonger-plot-formatter/perfmonger-plot-formatter.go +115 -3
- data/core/cmd/perfmonger-summarizer/perfmonger-summarizer.go +2 -1
- data/core/subsystem/perfmonger_linux.go +2 -0
- data/core/subsystem/stat.go +2 -0
- 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/perfmonger/command/play.rb +10 -0
- data/lib/perfmonger/command/plot.rb +144 -2
- data/lib/perfmonger/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9b1f5e883802377df1cc422ab0e100f2445bdaafb7d77da2ddcb279232cd63b4
|
4
|
+
data.tar.gz: b3cf4f9bd787f1b9b47dcff4da7480d8c30385c89a3785ad0793c5c40703dd06
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cdca2aa8a3ad76a274cdc142f1738e12578dc06117de98a1e24e41aee5604452a113becdd506df19d49b5ccf7aa1e1d1eaa58ab8a52b1fd121181318f3fdad51
|
7
|
+
data.tar.gz: 76697490438d0b364be27504a7db0697d33b9f3bc5dc56f11db8dc89f5a1f682a270ad2d50bbedb40852ea759a0cf98708cc0fd159bc73568f17e11da2f43de7
|
data/NEWS
CHANGED
@@ -1,4 +1,28 @@
|
|
1
|
-
##
|
1
|
+
## 2021-XX-XX: PerfMonger 0.15.0
|
2
|
+
|
3
|
+
## 2021-12-01: PerfMonger 0.14.2
|
4
|
+
* Bugfix
|
5
|
+
* [player] subcommand:
|
6
|
+
* Read stdin if no argument is given (required behaviour for live subcommand)
|
7
|
+
|
8
|
+
## 2021-12-01: PerfMonger 0.14.1
|
9
|
+
* Changes
|
10
|
+
* [plot] subcommand:
|
11
|
+
* Skip plotting memory usage if it is not recorded
|
12
|
+
|
13
|
+
## 2021-07-27: PerfMonger 0.14.0
|
14
|
+
* New features
|
15
|
+
* [plot] subcommand:
|
16
|
+
* Added memory usage plot
|
17
|
+
* Changes
|
18
|
+
* [record] subcommand:
|
19
|
+
* Additionaly record 'Hugepagesize' in memory usage
|
20
|
+
|
21
|
+
## 2021-07-26: PerfMonger 0.13.1
|
22
|
+
* New features
|
23
|
+
* [play] subcommand:
|
24
|
+
* Added --disk-only option to filter results of not interesting disks
|
25
|
+
* Note: v0.13.0 is yanked from rubygems.org
|
2
26
|
|
3
27
|
## 2021-07-08: PerfMonger 0.12.1
|
4
28
|
* Bug fixes
|
@@ -9,16 +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
|
-
core "github.com/hayamiz/perfmonger/core"
|
16
17
|
)
|
17
18
|
|
18
19
|
type PlayerOption struct {
|
19
|
-
logfile
|
20
|
-
color
|
21
|
-
pretty
|
20
|
+
logfile string
|
21
|
+
color bool
|
22
|
+
pretty bool
|
23
|
+
disk_only string
|
24
|
+
disk_only_regex *regexp.Regexp
|
22
25
|
}
|
23
26
|
|
24
27
|
var option PlayerOption
|
@@ -50,10 +53,11 @@ func showInterruptStat(printer *projson.JsonPrinter, prev_rec *ss.StatRecord, cu
|
|
50
53
|
return nil
|
51
54
|
}
|
52
55
|
|
53
|
-
func showDiskStat(printer *projson.JsonPrinter, prev_rec *ss.StatRecord, cur_rec *ss.StatRecord) error {
|
54
|
-
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(
|
55
58
|
prev_rec.Time, prev_rec.Disk,
|
56
|
-
cur_rec.Time, cur_rec.Disk
|
59
|
+
cur_rec.Time, cur_rec.Disk,
|
60
|
+
option.disk_only_regex)
|
57
61
|
if err != nil {
|
58
62
|
return err
|
59
63
|
}
|
@@ -94,7 +98,9 @@ func showMemStat(printer *projson.JsonPrinter, cur_rec *ss.StatRecord) error {
|
|
94
98
|
return nil
|
95
99
|
}
|
96
100
|
|
97
|
-
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
|
+
|
98
104
|
printer.Reset()
|
99
105
|
if option.pretty {
|
100
106
|
printer.SetStyle(projson.SmartStyle)
|
@@ -102,6 +108,7 @@ func showStat(printer *projson.JsonPrinter, prev_rec *ss.StatRecord, cur_rec *ss
|
|
102
108
|
if option.color {
|
103
109
|
printer.SetColor(true)
|
104
110
|
}
|
111
|
+
|
105
112
|
printer.BeginObject()
|
106
113
|
printer.PutKey("time")
|
107
114
|
printer.PutFloatFmt(float64(cur_rec.Time.UnixNano())/1e9, "%.3f")
|
@@ -122,7 +129,7 @@ func showStat(printer *projson.JsonPrinter, prev_rec *ss.StatRecord, cur_rec *ss
|
|
122
129
|
}
|
123
130
|
}
|
124
131
|
if cur_rec.Disk != nil {
|
125
|
-
err := showDiskStat(printer, prev_rec, cur_rec)
|
132
|
+
err := showDiskStat(printer, prev_rec, cur_rec, disk_only_regex)
|
126
133
|
if err != nil {
|
127
134
|
return err
|
128
135
|
}
|
@@ -148,10 +155,25 @@ func showStat(printer *projson.JsonPrinter, prev_rec *ss.StatRecord, cur_rec *ss
|
|
148
155
|
func parseArgs() {
|
149
156
|
flag.BoolVar(&option.color, "color", false, "Use colored JSON output")
|
150
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")
|
151
159
|
|
152
160
|
flag.Parse()
|
153
161
|
|
154
|
-
option.
|
162
|
+
option.disk_only_regex = nil
|
163
|
+
|
164
|
+
if option.disk_only != "" {
|
165
|
+
var err error
|
166
|
+
option.disk_only_regex, err = regexp.Compile(option.disk_only)
|
167
|
+
if err != nil {
|
168
|
+
panic(err)
|
169
|
+
}
|
170
|
+
}
|
171
|
+
|
172
|
+
if len(flag.Args()) < 1 {
|
173
|
+
option.logfile = "-"
|
174
|
+
} else {
|
175
|
+
option.logfile = flag.Arg(0)
|
176
|
+
}
|
155
177
|
}
|
156
178
|
|
157
179
|
func main() {
|
@@ -160,7 +182,7 @@ func main() {
|
|
160
182
|
|
161
183
|
parseArgs()
|
162
184
|
|
163
|
-
if option.logfile == "" {
|
185
|
+
if option.logfile == "-" {
|
164
186
|
in = os.Stdin
|
165
187
|
} else {
|
166
188
|
f, err := os.Open(option.logfile)
|
@@ -219,7 +241,7 @@ func main() {
|
|
219
241
|
panic(err)
|
220
242
|
}
|
221
243
|
|
222
|
-
err = showStat(printer, prev_rec, cur_rec)
|
244
|
+
err = showStat(printer, prev_rec, cur_rec, option.disk_only_regex)
|
223
245
|
if err != nil {
|
224
246
|
printer.Reset()
|
225
247
|
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,14 +13,16 @@ import (
|
|
13
13
|
"os"
|
14
14
|
"regexp"
|
15
15
|
"sort"
|
16
|
+
"strings"
|
16
17
|
|
17
|
-
ss "github.com/hayamiz/perfmonger/core/subsystem"
|
18
18
|
"github.com/hayamiz/perfmonger/core"
|
19
|
+
ss "github.com/hayamiz/perfmonger/core/subsystem"
|
19
20
|
)
|
20
21
|
|
21
22
|
type CmdOption struct {
|
22
23
|
DiskFile string
|
23
24
|
CpuFile string
|
25
|
+
MemFile string
|
24
26
|
PerfmongerFile string
|
25
27
|
disk_only string
|
26
28
|
disk_only_regex *regexp.Regexp
|
@@ -31,8 +33,9 @@ func parseArgs() *CmdOption {
|
|
31
33
|
|
32
34
|
opt := new(CmdOption)
|
33
35
|
|
34
|
-
flag.StringVar(&opt.DiskFile, "diskfile", "./disk.dat", "Disk
|
35
|
-
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")
|
36
39
|
flag.StringVar(&opt.PerfmongerFile, "perfmonger", "", "Perfmonger log file")
|
37
40
|
flag.StringVar(&opt.disk_only, "disk-only",
|
38
41
|
"", "Select disk devices by regex")
|
@@ -80,6 +83,13 @@ type DiskDatTmpFile struct {
|
|
80
83
|
Idx int
|
81
84
|
}
|
82
85
|
|
86
|
+
type MemDatTmpFile struct {
|
87
|
+
Name string
|
88
|
+
Path string
|
89
|
+
File *os.File
|
90
|
+
Writer *bufio.Writer
|
91
|
+
}
|
92
|
+
|
83
93
|
type CpuDatTmpFile struct {
|
84
94
|
CoreId int
|
85
95
|
Path string
|
@@ -118,6 +128,20 @@ func makeCpuDatTmpFile(coreid int) *CpuDatTmpFile {
|
|
118
128
|
return ret
|
119
129
|
}
|
120
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
|
+
|
121
145
|
func printCoreUsage(writer *bufio.Writer, elapsed_time float64, coreusage *ss.CpuCoreUsage) {
|
122
146
|
writer.WriteString(
|
123
147
|
fmt.Sprintf("%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\n",
|
@@ -133,6 +157,80 @@ func printCoreUsage(writer *bufio.Writer, elapsed_time float64, coreusage *ss.Cp
|
|
133
157
|
coreusage.Idle))
|
134
158
|
}
|
135
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
|
+
|
136
234
|
func main() {
|
137
235
|
opt := parseArgs()
|
138
236
|
|
@@ -193,6 +291,13 @@ func main() {
|
|
193
291
|
cpu_writer.WriteString("# All cpu usage\n")
|
194
292
|
cpu_writer.WriteString("# elapsed_time %usr %nice %sys %iowait %hardirq %softirq %steal %guest %idle\n")
|
195
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
|
+
|
196
301
|
for {
|
197
302
|
prev_rec := &records[curr^1]
|
198
303
|
cur_rec := &records[curr]
|
@@ -284,6 +389,12 @@ func main() {
|
|
284
389
|
}
|
285
390
|
printCoreUsage(cpu_writer, prev_rec.Time.Sub(t0).Seconds(), cusage.All)
|
286
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
|
+
|
287
398
|
curr ^= 1
|
288
399
|
meta_set = true
|
289
400
|
}
|
@@ -332,6 +443,7 @@ func main() {
|
|
332
443
|
os.Remove(cpu_dat.Path)
|
333
444
|
}
|
334
445
|
cpu_writer.Flush()
|
446
|
+
mem_writer.Flush()
|
335
447
|
|
336
448
|
json_enc := json.NewEncoder(os.Stdout)
|
337
449
|
json_enc.Encode(meta)
|
@@ -12,8 +12,8 @@ import (
|
|
12
12
|
"sort"
|
13
13
|
|
14
14
|
projson "github.com/hayamiz/go-projson"
|
15
|
-
ss "github.com/hayamiz/perfmonger/core/subsystem"
|
16
15
|
"github.com/hayamiz/perfmonger/core"
|
16
|
+
ss "github.com/hayamiz/perfmonger/core/subsystem"
|
17
17
|
)
|
18
18
|
|
19
19
|
type SummaryOption struct {
|
@@ -39,6 +39,7 @@ func parseArgs() {
|
|
39
39
|
flag.Parse()
|
40
40
|
|
41
41
|
if len(flag.Args()) < 1 {
|
42
|
+
fmt.Fprintln(os.Stderr, "Insufficient argument")
|
42
43
|
os.Exit(1)
|
43
44
|
}
|
44
45
|
|
@@ -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 {
|
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|
|
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.2
|
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-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -102,6 +102,7 @@ files:
|
|
102
102
|
- core/Makefile
|
103
103
|
- core/build.sh
|
104
104
|
- core/cmd/perfmonger-player/perfmonger-player.go
|
105
|
+
- core/cmd/perfmonger-plot-formatter/README.md
|
105
106
|
- core/cmd/perfmonger-plot-formatter/perfmonger-plot-formatter.go
|
106
107
|
- core/cmd/perfmonger-recorder/perfmonger-recorder.go
|
107
108
|
- core/cmd/perfmonger-summarizer/perfmonger-summarizer.go
|