perfmonger 0.11.2 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +5 -5
  3. data/NEWS +38 -1
  4. data/Rakefile +18 -7
  5. data/core/Makefile +20 -21
  6. data/core/build.sh +4 -6
  7. data/core/{perfmonger-player.go → cmd/perfmonger-player/perfmonger-player.go} +53 -10
  8. data/core/cmd/perfmonger-plot-formatter/README.md +24 -0
  9. data/core/{perfmonger-plot-formatter.go → cmd/perfmonger-plot-formatter/perfmonger-plot-formatter.go} +116 -3
  10. data/core/{perfmonger-recorder.go → cmd/perfmonger-recorder/perfmonger-recorder.go} +6 -0
  11. data/core/{perfmonger-summarizer.go → cmd/perfmonger-summarizer/perfmonger-summarizer.go} +4 -2
  12. data/core/{perfmonger-viewer.go → cmd/perfmonger-viewer/perfmonger-viewer.go} +0 -0
  13. data/core/go.mod +10 -0
  14. data/core/go.sum +17 -0
  15. data/core/subsystem/Makefile +4 -0
  16. data/core/subsystem/perfmonger_linux.go +97 -0
  17. data/core/subsystem/perfmonger_linux_test.go +40 -0
  18. data/core/subsystem/stat.go +72 -0
  19. data/core/subsystem/stat_test.go +9 -0
  20. data/core/subsystem/usage.go +80 -0
  21. data/core/utils.go +2 -2
  22. data/lib/exec/perfmonger-player_darwin_amd64 +0 -0
  23. data/lib/exec/perfmonger-player_linux_amd64 +0 -0
  24. data/lib/exec/perfmonger-plot-formatter_darwin_amd64 +0 -0
  25. data/lib/exec/perfmonger-plot-formatter_linux_amd64 +0 -0
  26. data/lib/exec/perfmonger-recorder_darwin_amd64 +0 -0
  27. data/lib/exec/perfmonger-recorder_linux_amd64 +0 -0
  28. data/lib/exec/perfmonger-summarizer_darwin_amd64 +0 -0
  29. data/lib/exec/perfmonger-summarizer_linux_amd64 +0 -0
  30. data/lib/exec/perfmonger-viewer_darwin_amd64 +0 -0
  31. data/lib/exec/perfmonger-viewer_linux_amd64 +0 -0
  32. data/lib/perfmonger/command/play.rb +10 -0
  33. data/lib/perfmonger/command/plot.rb +146 -3
  34. data/lib/perfmonger/command/record.rb +23 -2
  35. data/lib/perfmonger/command/record_option.rb +16 -0
  36. data/lib/perfmonger/version.rb +1 -1
  37. data/misc/werker-box/Dockerfile +10 -9
  38. data/misc/werker-box/build-push.sh +2 -2
  39. data/wercker.yml +10 -10
  40. metadata +12 -27
@@ -36,6 +36,7 @@ type RecorderOption struct {
36
36
  no_intr bool
37
37
  no_disk bool
38
38
  no_net bool
39
+ no_mem bool
39
40
  debug bool
40
41
  listDevices bool
41
42
  player_bin string
@@ -76,6 +77,8 @@ func parseArgs() {
76
77
  false, "Do not record disk usage")
77
78
  flag.BoolVar(&option.no_net, "no-net",
78
79
  false, "Do not record net usage")
80
+ flag.BoolVar(&option.no_mem, "no-mem",
81
+ false, "Do not record memory usage")
79
82
  flag.BoolVar(&option.debug, "debug",
80
83
  false, "Enable debug mode")
81
84
  flag.BoolVar(&option.listDevices, "list-devices",
@@ -340,6 +343,9 @@ func main() {
340
343
  if !option.no_net {
341
344
  ss.ReadNetStat(record)
342
345
  }
346
+ if !option.no_mem {
347
+ ss.ReadMemStat(record)
348
+ }
343
349
 
344
350
  err = enc.Encode(record)
345
351
  if err != nil {
@@ -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 := newPerfmongerLogReader(f)
66
+ input_reader := core.NewPerfmongerLogReader(f)
65
67
  dec := gob.NewDecoder(input_reader)
66
68
 
67
69
  err = dec.Decode(&cheader)
@@ -128,7 +130,7 @@ func main() {
128
130
  option.disk_only_regex)
129
131
  }
130
132
 
131
- if fst_record.Disk != nil && lst_record.Disk != nil {
133
+ if fst_record.Net != nil && lst_record.Net != nil {
132
134
  net_usage, err = ss.GetNetUsage(
133
135
  fst_record.Time, fst_record.Net,
134
136
  lst_record.Time, lst_record.Net)
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=
@@ -1,3 +1,7 @@
1
1
 
2
2
  all:
3
3
  make -C ../
4
+
5
+ check:
6
+ go test
7
+
@@ -429,3 +429,100 @@ func ReadNetStat(record *StatRecord) error {
429
429
 
430
430
  return nil
431
431
  }
432
+
433
+ func ReadMemStat(record *StatRecord) error {
434
+ if record == nil {
435
+ return errors.New("Valid *StatRecord is required.")
436
+ }
437
+
438
+ mem_stat := NewMemStat()
439
+
440
+ f, err := os.Open("/proc/meminfo")
441
+ if err != nil {
442
+ return err
443
+ }
444
+ defer f.Close()
445
+ scanner := bufio.NewScanner(f)
446
+
447
+ for scanner.Scan() {
448
+ var key string
449
+ var val int64
450
+ line := scanner.Text()
451
+
452
+ n, err := fmt.Sscanf(line, "%s %d", &key, &val)
453
+
454
+ if err == io.EOF {
455
+ break
456
+ } else if err != nil {
457
+ return err
458
+ }
459
+ if n != 2 {
460
+ continue
461
+ }
462
+
463
+ switch key {
464
+ case "HugePages_Surp:":
465
+ mem_stat.HugePages_Surp = val
466
+ case "HugePages_Rsvd:":
467
+ mem_stat.HugePages_Rsvd = val
468
+ case "HugePages_Free:":
469
+ mem_stat.HugePages_Free = val
470
+ case "HugePages_Total:":
471
+ mem_stat.HugePages_Total = val
472
+ case "Hugepagesize:":
473
+ mem_stat.Hugepagesize = val
474
+ case "AnonHugePages:":
475
+ mem_stat.AnonHugePages = val
476
+ case "Committed_AS:":
477
+ mem_stat.Committed_AS = val
478
+ case "CommitLimit:":
479
+ mem_stat.CommitLimit = val
480
+ case "Bounce:":
481
+ mem_stat.Bounce = val
482
+ case "NFS_Unstable:":
483
+ mem_stat.NFS_Unstable = val
484
+ case "Shmem:":
485
+ mem_stat.Shmem = val
486
+ case "Slab:":
487
+ mem_stat.Slab = val
488
+ case "SReclaimable:":
489
+ mem_stat.SReclaimable = val
490
+ case "SUnreclaim:":
491
+ mem_stat.SUnreclaim = val
492
+ case "KernelStack:":
493
+ mem_stat.KernelStack = val
494
+ case "PageTables:":
495
+ mem_stat.PageTables = val
496
+ case "Mapped:":
497
+ mem_stat.Mapped = val
498
+ case "AnonPages:":
499
+ mem_stat.AnonPages = val
500
+ case "Writeback:":
501
+ mem_stat.Writeback = val
502
+ case "Dirty:":
503
+ mem_stat.Dirty = val
504
+ case "SwapFree:":
505
+ mem_stat.SwapFree = val
506
+ case "SwapTotal:":
507
+ mem_stat.SwapTotal = val
508
+ case "Inactive:":
509
+ mem_stat.Inactive = val
510
+ case "Active:":
511
+ mem_stat.Active = val
512
+ case "SwapCached:":
513
+ mem_stat.SwapCached = val
514
+ case "Cached:":
515
+ mem_stat.Cached = val
516
+ case "Buffers:":
517
+ mem_stat.Buffers = val
518
+ case "MemFree:":
519
+ mem_stat.MemFree = val
520
+ case "MemTotal:":
521
+ mem_stat.MemTotal = val
522
+ }
523
+ }
524
+
525
+ record.Mem = mem_stat
526
+
527
+ return nil
528
+ }
@@ -1,6 +1,7 @@
1
1
  package subsystem
2
2
 
3
3
  import (
4
+ "log"
4
5
  "os"
5
6
  "testing"
6
7
  )
@@ -71,3 +72,42 @@ func TestReadNetStat(t *testing.T) {
71
72
  t.Error("Device 'lo' not found.")
72
73
  }
73
74
  }
75
+
76
+ func TestReadMemStat(t *testing.T) {
77
+ var err error
78
+ var stat_record *StatRecord = nil
79
+
80
+ err = ReadMemStat(stat_record)
81
+ if err == nil {
82
+ t.Errorf("Error should not be returned with non-nil *StatRecord.")
83
+ }
84
+
85
+ _, err = os.Stat("/proc/meminfo")
86
+ if err != nil {
87
+ t.Skip("/proc/meminfo is not present.")
88
+ }
89
+
90
+ stat_record = NewStatRecord()
91
+ err = ReadMemStat(stat_record)
92
+ if err != nil {
93
+ log.Print(err)
94
+ t.Error("Error should not be returned with valid *StatRecord.")
95
+ return
96
+ }
97
+ if stat_record.Mem == nil {
98
+ t.Error("stat_record.Mem should not be nil")
99
+ return
100
+ }
101
+
102
+ if stat_record.Mem.MemTotal == 0 {
103
+ t.Error("Cannot read MemTotal correctly")
104
+ return
105
+ }
106
+
107
+ mem := stat_record.Mem
108
+
109
+ if (mem.MemFree + mem.Cached + mem.Buffers) > mem.MemTotal {
110
+ t.Error("Inconsistent meminfo values")
111
+ return
112
+ }
113
+ }
@@ -102,6 +102,39 @@ type NetStat struct {
102
102
  Entries []*NetStatEntry
103
103
  }
104
104
 
105
+ // all values are recorded in KB
106
+ type MemStat struct {
107
+ MemTotal int64
108
+ MemFree int64
109
+ Buffers int64
110
+ Cached int64
111
+ SwapCached int64
112
+ Active int64
113
+ Inactive int64
114
+ SwapTotal int64
115
+ SwapFree int64
116
+ Dirty int64
117
+ Writeback int64
118
+ AnonPages int64
119
+ Mapped int64
120
+ Shmem int64
121
+ Slab int64
122
+ SReclaimable int64
123
+ SUnreclaim int64
124
+ KernelStack int64
125
+ PageTables int64
126
+ NFS_Unstable int64
127
+ Bounce int64
128
+ CommitLimit int64
129
+ Committed_AS int64
130
+ AnonHugePages int64
131
+ HugePages_Total int64
132
+ HugePages_Free int64
133
+ HugePages_Rsvd int64
134
+ HugePages_Surp int64
135
+ Hugepagesize int64
136
+ }
137
+
105
138
  type StatRecord struct {
106
139
  Time time.Time
107
140
  Cpu *CpuStat
@@ -110,6 +143,7 @@ type StatRecord struct {
110
143
  Disk *DiskStat
111
144
  Softirq *SoftIrqStat
112
145
  Net *NetStat
146
+ Mem *MemStat
113
147
  }
114
148
 
115
149
  func (core_stat *CpuCoreStat) Clear() {
@@ -219,6 +253,43 @@ func NewNetStat() *NetStat {
219
253
  return new(NetStat)
220
254
  }
221
255
 
256
+ func NewMemStat() *MemStat {
257
+ return new(MemStat)
258
+ }
259
+
260
+ func (entry *MemStat) Clear() {
261
+ entry.MemTotal = 0
262
+ entry.MemFree = 0
263
+ entry.Buffers = 0
264
+ entry.Cached = 0
265
+ entry.SwapCached = 0
266
+ entry.Active = 0
267
+ entry.Inactive = 0
268
+ entry.SwapTotal = 0
269
+ entry.SwapFree = 0
270
+ entry.Dirty = 0
271
+ entry.Writeback = 0
272
+ entry.AnonPages = 0
273
+ entry.Mapped = 0
274
+ entry.Shmem = 0
275
+ entry.Slab = 0
276
+ entry.SReclaimable = 0
277
+ entry.NFS_Unstable = 0
278
+ entry.SUnreclaim = 0
279
+ entry.KernelStack = 0
280
+ entry.PageTables = 0
281
+ entry.NFS_Unstable = 0
282
+ entry.Bounce = 0
283
+ entry.CommitLimit = 0
284
+ entry.Committed_AS = 0
285
+ entry.AnonHugePages = 0
286
+ entry.HugePages_Total = 0
287
+ entry.HugePages_Free = 0
288
+ entry.HugePages_Rsvd = 0
289
+ entry.HugePages_Surp = 0
290
+ entry.Hugepagesize = 0
291
+ }
292
+
222
293
  func NewStatRecord() *StatRecord {
223
294
  return &StatRecord{
224
295
  time.Now(),
@@ -228,6 +299,7 @@ func NewStatRecord() *StatRecord {
228
299
  nil,
229
300
  nil,
230
301
  nil,
302
+ nil,
231
303
  }
232
304
  }
233
305
 
@@ -262,6 +262,14 @@ func TestNewNetStat(t *testing.T) {
262
262
  }
263
263
  }
264
264
 
265
+ func TestNewMemStat(t *testing.T) {
266
+ memstat := NewMemStat()
267
+
268
+ if memstat == nil {
269
+ t.Error("failed to create MemStat")
270
+ }
271
+ }
272
+
265
273
  func TestNewStatRecord(t *testing.T) {
266
274
  stat_record := NewStatRecord()
267
275
 
@@ -278,4 +286,5 @@ func TestNewStatRecord(t *testing.T) {
278
286
  checkFieldIsNil("Disk")
279
287
  checkFieldIsNil("Softirq")
280
288
  checkFieldIsNil("Net")
289
+ checkFieldIsNil("Mem")
281
290
  }
@@ -85,6 +85,10 @@ type NetUsageEntry struct {
85
85
 
86
86
  type NetUsage map[string]*NetUsageEntry
87
87
 
88
+ type MemUsage struct {
89
+ mem *MemStat
90
+ }
91
+
88
92
  var UseColor = false
89
93
 
90
94
  func SetUseColor(use_color bool) {
@@ -562,6 +566,82 @@ func (nusage *NetUsage) WriteJsonTo(printer *projson.JsonPrinter) {
562
566
  printer.FinishObject()
563
567
  }
564
568
 
569
+ func GetMemUsage(mem *MemStat) (*MemUsage, error) {
570
+ if mem == nil {
571
+ return nil, errors.New("invalid memstat")
572
+ }
573
+
574
+ musage := new(MemUsage)
575
+ musage.mem = mem
576
+
577
+ return musage, nil
578
+ }
579
+
580
+ func (musage *MemUsage) WriteJsonTo(printer *projson.JsonPrinter) {
581
+ printer.BeginObject()
582
+
583
+ printer.PutKey("mem_total")
584
+ printer.PutInt64(musage.mem.MemTotal)
585
+ printer.PutKey("mem_used")
586
+ printer.PutInt64(musage.mem.MemTotal - musage.mem.MemFree - musage.mem.Buffers - musage.mem.Cached - musage.mem.SReclaimable)
587
+ printer.PutKey("mem_free")
588
+ printer.PutInt64(musage.mem.MemFree)
589
+ printer.PutKey("buffers")
590
+ printer.PutInt64(musage.mem.Buffers)
591
+ printer.PutKey("cached")
592
+ printer.PutInt64(musage.mem.Cached)
593
+ printer.PutKey("swap_cached")
594
+ printer.PutInt64(musage.mem.SwapCached)
595
+ printer.PutKey("active")
596
+ printer.PutInt64(musage.mem.Active)
597
+ printer.PutKey("inactive")
598
+ printer.PutInt64(musage.mem.Inactive)
599
+ printer.PutKey("swap_total")
600
+ printer.PutInt64(musage.mem.SwapTotal)
601
+ printer.PutKey("swap_free")
602
+ printer.PutInt64(musage.mem.SwapFree)
603
+ printer.PutKey("dirty")
604
+ printer.PutInt64(musage.mem.Dirty)
605
+ printer.PutKey("writeback")
606
+ printer.PutInt64(musage.mem.Writeback)
607
+ printer.PutKey("anon_pages")
608
+ printer.PutInt64(musage.mem.AnonPages)
609
+ printer.PutKey("mapped")
610
+ printer.PutInt64(musage.mem.Mapped)
611
+ printer.PutKey("shmem")
612
+ printer.PutInt64(musage.mem.Shmem)
613
+ printer.PutKey("slab")
614
+ printer.PutInt64(musage.mem.Slab)
615
+ printer.PutKey("s_reclaimable")
616
+ printer.PutInt64(musage.mem.SReclaimable)
617
+ printer.PutKey("s_unreclaim")
618
+ printer.PutInt64(musage.mem.SUnreclaim)
619
+ printer.PutKey("kernel_stack")
620
+ printer.PutInt64(musage.mem.KernelStack)
621
+ printer.PutKey("page_tables")
622
+ printer.PutInt64(musage.mem.PageTables)
623
+ printer.PutKey("nfs_unstable")
624
+ printer.PutInt64(musage.mem.NFS_Unstable)
625
+ printer.PutKey("bounce")
626
+ printer.PutInt64(musage.mem.Bounce)
627
+ printer.PutKey("commit_limit")
628
+ printer.PutInt64(musage.mem.CommitLimit)
629
+ printer.PutKey("committed_as")
630
+ printer.PutInt64(musage.mem.Committed_AS)
631
+ printer.PutKey("anon_huge_pages")
632
+ printer.PutInt64(musage.mem.AnonHugePages)
633
+ printer.PutKey("huge_pages_total")
634
+ printer.PutInt64(musage.mem.HugePages_Total)
635
+ printer.PutKey("huge_pages_free")
636
+ printer.PutInt64(musage.mem.HugePages_Free)
637
+ printer.PutKey("huge_pages_rsvd")
638
+ printer.PutInt64(musage.mem.HugePages_Rsvd)
639
+ printer.PutKey("huge_pages_surp")
640
+ printer.PutInt64(musage.mem.HugePages_Surp)
641
+
642
+ printer.FinishObject()
643
+ }
644
+
565
645
  func (entry *NetUsageEntry) WriteJsonTo(printer *projson.JsonPrinter) {
566
646
  printer.BeginObject()
567
647