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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9610baac2556f61a8deb2cab5c7d4c10dac9c7da69c0c07a2f7d2b5f2414199e
4
- data.tar.gz: 1e94e2c14421eabddd25f60abb8ef6e749aa57a557c4d661830b52fc5f91d7ca
3
+ metadata.gz: 9b1f5e883802377df1cc422ab0e100f2445bdaafb7d77da2ddcb279232cd63b4
4
+ data.tar.gz: b3cf4f9bd787f1b9b47dcff4da7480d8c30385c89a3785ad0793c5c40703dd06
5
5
  SHA512:
6
- metadata.gz: 7a5f69061b79e2dcafe707bdb24b5a7be0443df2130bd928f33a7aba7a56623a946979ac22e0a82ce367f6d8d17d66facaf7286c6fe1c09016f8cedfc43dc5f6
7
- data.tar.gz: 9754fb8acc4b1a521c2daf2a67017d95ec018b414f7f808989589efa498f3f66003f93d1d8d6aa7455a008259486f7ea71dae8c8d2934c52ed0b55e9dd0b0a1f
6
+ metadata.gz: cdca2aa8a3ad76a274cdc142f1738e12578dc06117de98a1e24e41aee5604452a113becdd506df19d49b5ccf7aa1e1d1eaa58ab8a52b1fd121181318f3fdad51
7
+ data.tar.gz: 76697490438d0b364be27504a7db0697d33b9f3bc5dc56f11db8dc89f5a1f682a270ad2d50bbedb40852ea759a0cf98708cc0fd159bc73568f17e11da2f43de7
data/NEWS CHANGED
@@ -1,4 +1,28 @@
1
- ## 20XX-XX-XX: PerfMonger 0.13.0
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 string
20
- color bool
21
- pretty bool
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.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(
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) error {
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.logfile = flag.Arg(0)
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 performance data file")
35
- 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")
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:":
@@ -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
@@ -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, "-cpufile", @cpu_dat,
151
- "-diskfile", @disk_dat]
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|
@@ -1,3 +1,3 @@
1
1
  module PerfMonger
2
- VERSION = "0.12.1"
2
+ VERSION = "0.14.2"
3
3
  end
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.12.1
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-07-12 00:00:00.000000000 Z
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