perfmonger 0.8.2 → 0.9.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4a10e8d2334c72c7e5c730a741cb461e71df2e50
4
- data.tar.gz: fda2f62538fdcba060ef6e6d68377fca3208fc5b
3
+ metadata.gz: c6c4a036c08d2f75fc25b25da1b773e025461880
4
+ data.tar.gz: 87182b819268cdcd289ea1cfb89f8672cc307947
5
5
  SHA512:
6
- metadata.gz: 098aad2506d627754ac570a6f9ae733d7bf7e2a118fa33dd0114fe290838e33926cea8d2f6675da1aea20a5c026df871f0a147098c711d431fde895b4f9e42ee
7
- data.tar.gz: bb2f83fe43a83203f49ebc55c65bc64902e056dd469eb43d64e6508eaa0d652c11c9774d0ec80b6dbd4fca1394e9c4872f60d872738cf028f1dc287e8bed4e72
6
+ metadata.gz: dcb1dd5f6086bff622f66dc7eb15a835604d0ce63fb2ea7b3d6ab022d3b5724384ca54ec38525c31984bc06dc08c87ca89cb21da7a62696bfaf665df6474d8a8
7
+ data.tar.gz: cb33cd2fe403d279687a6ad680fbda8af96c778b65b485f6f4b6024eac8e80c8fc6efd79e4e225f1a02fcbfa2f79cfe5061857716ff62fc3b7c4a1a828ca2568
data/.gitignore CHANGED
@@ -8,3 +8,6 @@
8
8
  /lib/exec/
9
9
  /ext/perfmonger/Makefile
10
10
  /core/perfmonger-summarizer
11
+ /cpu.dat
12
+ /disk.dat
13
+ /perfmonger.pgr
data/NEWS CHANGED
@@ -1,5 +1,13 @@
1
- ## XXXX-XX-XX: PerfMonger 0.9.0
2
- * ...
1
+ ## 2016-12-12: PerfMonger 0.9.0
2
+ * New features
3
+ * [init-shell] subcommand: Added for loading shell completion function from rcfile
4
+ * zsh support
5
+ * bash support
6
+ * [fingerprint]
7
+ * log LVM, fdisk, and lsblk info
8
+ * [plot]
9
+ * Fast plot data formatting with new core implementation
10
+ * Improved shell completion
3
11
 
4
12
  ## 2016-11-22: PerfMonger 0.8.2
5
13
  * Bug fixes
data/core/Makefile CHANGED
@@ -20,6 +20,10 @@ all: build
20
20
  go build -o $@ perfmonger-summarizer.go
21
21
 
22
22
 
23
+ ../lib/exec/perfmonger-plot-formatter_linux_386: perfmonger-plot-formatter.go $(GOSRC)
24
+ go build -o $@ perfmonger-plot-formatter.go
25
+
26
+
23
27
  ../lib/exec/perfmonger-recorder_linux_amd64: perfmonger-recorder.go $(GOSRC)
24
28
  go build -o $@ perfmonger-recorder.go
25
29
 
@@ -32,6 +36,10 @@ all: build
32
36
  go build -o $@ perfmonger-summarizer.go
33
37
 
34
38
 
39
+ ../lib/exec/perfmonger-plot-formatter_linux_amd64: perfmonger-plot-formatter.go $(GOSRC)
40
+ go build -o $@ perfmonger-plot-formatter.go
41
+
42
+
35
43
  ../lib/exec/perfmonger-recorder_darwin_amd64: perfmonger-recorder.go $(GOSRC)
36
44
  go build -o $@ perfmonger-recorder.go
37
45
 
@@ -44,8 +52,12 @@ all: build
44
52
  go build -o $@ perfmonger-summarizer.go
45
53
 
46
54
 
47
- build: ../lib/exec/perfmonger-recorder_linux_386 ../lib/exec/perfmonger-player_linux_386 ../lib/exec/perfmonger-summarizer_linux_386 ../lib/exec/perfmonger-recorder_linux_amd64 ../lib/exec/perfmonger-player_linux_amd64 ../lib/exec/perfmonger-summarizer_linux_amd64 ../lib/exec/perfmonger-recorder_darwin_amd64 ../lib/exec/perfmonger-player_darwin_amd64 ../lib/exec/perfmonger-summarizer_darwin_amd64
55
+ ../lib/exec/perfmonger-plot-formatter_darwin_amd64: perfmonger-plot-formatter.go $(GOSRC)
56
+ go build -o $@ perfmonger-plot-formatter.go
57
+
58
+
59
+ build: ../lib/exec/perfmonger-recorder_linux_386 ../lib/exec/perfmonger-player_linux_386 ../lib/exec/perfmonger-summarizer_linux_386 ../lib/exec/perfmonger-plot-formatter_linux_386 ../lib/exec/perfmonger-recorder_linux_amd64 ../lib/exec/perfmonger-player_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-summarizer_darwin_amd64 ../lib/exec/perfmonger-plot-formatter_darwin_amd64
48
60
 
49
61
  clean:
50
- rm -f ../lib/exec/perfmonger-recorder_linux_386 ../lib/exec/perfmonger-player_linux_386 ../lib/exec/perfmonger-summarizer_linux_386 ../lib/exec/perfmonger-recorder_linux_amd64 ../lib/exec/perfmonger-player_linux_amd64 ../lib/exec/perfmonger-summarizer_linux_amd64 ../lib/exec/perfmonger-recorder_darwin_amd64 ../lib/exec/perfmonger-player_darwin_amd64 ../lib/exec/perfmonger-summarizer_darwin_amd64
62
+ rm -f ../lib/exec/perfmonger-recorder_linux_386 ../lib/exec/perfmonger-player_linux_386 ../lib/exec/perfmonger-summarizer_linux_386 ../lib/exec/perfmonger-plot-formatter_linux_386 ../lib/exec/perfmonger-recorder_linux_amd64 ../lib/exec/perfmonger-player_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-summarizer_darwin_amd64 ../lib/exec/perfmonger-plot-formatter_darwin_amd64
51
63
 
data/core/build.sh CHANGED
@@ -54,7 +54,7 @@ for idx in $(seq 0 $((${#TARGET[@]}-1))); do
54
54
  export GOOS=$1
55
55
  export GOARCH=$2
56
56
 
57
- for subcmd in recorder player summarizer; do
57
+ for subcmd in recorder player summarizer plot-formatter; do
58
58
  TARGETS+=(../lib/exec/perfmonger-${subcmd}_${GOOS}_${GOARCH})
59
59
 
60
60
  cat <<EOF >> Makefile
@@ -0,0 +1,325 @@
1
+ //usr/bin/env go run $0 $@ ; exit
2
+
3
+ package main
4
+
5
+ import (
6
+ "bufio"
7
+ "encoding/gob"
8
+ "encoding/json"
9
+ "flag"
10
+ "fmt"
11
+ "io"
12
+ "io/ioutil"
13
+ "os"
14
+ "sort"
15
+
16
+ ss "github.com/hayamiz/perfmonger/core/subsystem"
17
+ )
18
+
19
+ type CmdOption struct {
20
+ DiskFile string
21
+ CpuFile string
22
+ PerfmongerFile string
23
+ }
24
+
25
+ func parseArgs() *CmdOption {
26
+ opt := new(CmdOption)
27
+
28
+ flag.StringVar(&opt.DiskFile, "diskfile", "./disk.dat", "Disk performance data file")
29
+ flag.StringVar(&opt.CpuFile, "cpufile", "./cpu.dat", "CPU performance data file")
30
+ flag.StringVar(&opt.PerfmongerFile, "perfmonger", "", "Perfmonger log file")
31
+
32
+ flag.Parse()
33
+
34
+ if opt.PerfmongerFile == "" {
35
+ os.Stderr.WriteString("[ERROR] perfmonger log file is required.\n")
36
+ os.Exit(1)
37
+ }
38
+
39
+ return opt
40
+ }
41
+
42
+ type DiskMetaEntry struct {
43
+ Name string `json:"name"`
44
+ Idx int `json:"idx"`
45
+ }
46
+
47
+ type DiskMeta struct {
48
+ Devices []DiskMetaEntry `json:"devices"`
49
+ }
50
+
51
+ type CpuMeta struct {
52
+ NumCore int `json:"num_core"`
53
+ }
54
+
55
+ type PlotMeta struct {
56
+ Disk DiskMeta `json:"disk"`
57
+ Cpu CpuMeta `json:"cpu"`
58
+ StartTime float64 `json:"start_time"`
59
+ EndTime float64 `json:"end_time"`
60
+ }
61
+
62
+ type DiskDatTmpFile struct {
63
+ Name string
64
+ Path string
65
+ File *os.File
66
+ Writer *bufio.Writer
67
+ Idx int
68
+ }
69
+
70
+ type CpuDatTmpFile struct {
71
+ CoreId int
72
+ Path string
73
+ File *os.File
74
+ Writer *bufio.Writer
75
+ }
76
+
77
+ func makeDiskDatTmpFile(dname string, idx int) *DiskDatTmpFile {
78
+ ret := new(DiskDatTmpFile)
79
+ ret.Name = dname
80
+ ret.Idx = idx
81
+
82
+ f, err := ioutil.TempFile("", "perfmonger-"+dname)
83
+ if err != nil {
84
+ panic(err)
85
+ }
86
+ ret.File = f
87
+ ret.Path = f.Name()
88
+ ret.Writer = bufio.NewWriter(f)
89
+
90
+ return ret
91
+ }
92
+
93
+ func makeCpuDatTmpFile(coreid int) *CpuDatTmpFile {
94
+ ret := new(CpuDatTmpFile)
95
+ ret.CoreId = coreid
96
+
97
+ f, err := ioutil.TempFile("", fmt.Sprintf("perfmonger-core%d-", coreid))
98
+ if err != nil {
99
+ panic(err)
100
+ }
101
+ ret.File = f
102
+ ret.Path = f.Name()
103
+ ret.Writer = bufio.NewWriter(f)
104
+
105
+ return ret
106
+ }
107
+
108
+ func printCoreUsage(writer *bufio.Writer, elapsed_time float64, coreusage *ss.CpuCoreUsage) {
109
+ writer.WriteString(
110
+ fmt.Sprintf("%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\n",
111
+ elapsed_time,
112
+ coreusage.User,
113
+ coreusage.Nice,
114
+ coreusage.Sys,
115
+ coreusage.Iowait,
116
+ coreusage.Hardirq,
117
+ coreusage.Softirq,
118
+ coreusage.Steal,
119
+ coreusage.Guest,
120
+ coreusage.Idle))
121
+ }
122
+
123
+ func main() {
124
+ opt := parseArgs()
125
+
126
+ var in *os.File
127
+
128
+ f, err := os.Open(opt.PerfmongerFile)
129
+ if err != nil {
130
+ panic(err)
131
+ }
132
+ in = f
133
+ defer f.Close()
134
+
135
+ dec := gob.NewDecoder(bufio.NewReader(in))
136
+
137
+ var cheader ss.CommonHeader
138
+ var pheader ss.PlatformHeader
139
+ var records = make([]ss.StatRecord, 2)
140
+ curr := 0
141
+
142
+ err = dec.Decode(&cheader)
143
+ if err == io.EOF {
144
+ return
145
+ }
146
+ if err != nil {
147
+ panic(err)
148
+ }
149
+ err = dec.Decode(&pheader)
150
+ if err == io.EOF {
151
+ return
152
+ }
153
+ if err != nil {
154
+ panic(err)
155
+ }
156
+
157
+ // read first record
158
+ err = dec.Decode(&records[curr])
159
+ if err == io.EOF {
160
+ return
161
+ } else if err != nil {
162
+ panic(err)
163
+ }
164
+ t0 := records[curr].Time
165
+ curr ^= 1
166
+
167
+ meta_set := false
168
+ meta := PlotMeta{}
169
+ meta.StartTime = float64(records[0].Time.UnixNano()) / 1.0e9
170
+
171
+ disk_dat_files := map[string]*DiskDatTmpFile{}
172
+ cpu_dat_files := make([]*CpuDatTmpFile, records[0].Cpu.NumCore)
173
+ meta.Cpu.NumCore = records[0].Cpu.NumCore
174
+
175
+ f, err = os.Create(opt.CpuFile)
176
+ if err != nil {
177
+ panic(err)
178
+ }
179
+ defer f.Close()
180
+ cpu_writer := bufio.NewWriter(f)
181
+
182
+ cpu_writer.WriteString("# All cpu usage\n")
183
+ cpu_writer.WriteString("# elapsed_time %usr %nice %sys %iowait %hardirq %softirq %steal %guest %idle\n")
184
+
185
+ for {
186
+ prev_rec := &records[curr^1]
187
+ cur_rec := &records[curr]
188
+
189
+ err := dec.Decode(cur_rec)
190
+ if err == io.EOF {
191
+ break
192
+ } else if err != nil {
193
+ panic(err)
194
+ }
195
+
196
+ // Disk usage
197
+ dusage, err := ss.GetDiskUsage(prev_rec.Time, prev_rec.Disk, cur_rec.Time, cur_rec.Disk)
198
+ if err != nil {
199
+ panic(err)
200
+ }
201
+ didx := 0
202
+
203
+ var dnames []string
204
+ for dname, _ := range *dusage {
205
+ if dname != "total" {
206
+ dnames = append(dnames, dname)
207
+ }
208
+ }
209
+ sort.Strings(dnames)
210
+ dnames = append(dnames, "total")
211
+
212
+ // for dname, dusage_entry := range *dusage {
213
+ for _, dname := range dnames {
214
+ dusage_entry, ok := (*dusage)[dname]
215
+ if !ok {
216
+ panic("device '" + dname + "' not found")
217
+ }
218
+
219
+ if !meta_set {
220
+ meta.Disk.Devices =
221
+ append(meta.Disk.Devices,
222
+ DiskMetaEntry{Name: dname, Idx: didx})
223
+ }
224
+
225
+ disk_dat, ok := disk_dat_files[dname]
226
+ if !ok {
227
+ disk_dat = makeDiskDatTmpFile(dname, didx)
228
+ disk_dat_files[dname] = disk_dat
229
+ defer disk_dat.File.Close()
230
+
231
+ disk_dat.Writer.WriteString("\n\n\n")
232
+ disk_dat.Writer.WriteString("# device: " + disk_dat.Name + "\n")
233
+ disk_dat.Writer.WriteString(fmt.Sprintln(
234
+ "# elapsed_time r_iops w_iops r_MB/s w_MB/s r_latency w_latency r_avgsz w_avgsz qdepth"))
235
+ }
236
+
237
+ elapsed_time := prev_rec.Time.Sub(t0).Seconds()
238
+ disk_dat.Writer.WriteString(
239
+ fmt.Sprintf("%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\n",
240
+ elapsed_time,
241
+ dusage_entry.RdIops,
242
+ dusage_entry.WrIops,
243
+ dusage_entry.RdSecps*512.0/1024.0/1024.0,
244
+ dusage_entry.WrSecps*512.0/1024.0/1024.0,
245
+ dusage_entry.RdLatency,
246
+ dusage_entry.WrLatency,
247
+ dusage_entry.AvgRdSize,
248
+ dusage_entry.AvgWrSize,
249
+ dusage_entry.ReqQlen))
250
+
251
+ didx += 1
252
+ }
253
+
254
+ // Cpu usage
255
+ cusage, err := ss.GetCpuUsage(prev_rec.Cpu, cur_rec.Cpu)
256
+ if err != nil {
257
+ panic(err)
258
+ }
259
+ for coreid, coreusage := range cusage.CoreUsages {
260
+ cpu_dat := cpu_dat_files[coreid]
261
+ if cpu_dat == nil {
262
+ cpu_dat = makeCpuDatTmpFile(coreid)
263
+ cpu_dat_files[coreid] = cpu_dat
264
+ defer cpu_dat.File.Close()
265
+
266
+ cpu_dat.Writer.WriteString(fmt.Sprintf("\n\n\n# core: %d\n", coreid))
267
+ cpu_dat.Writer.WriteString("# elapsed_time %usr %nice %sys %iowait %hardirq %softirq %steal %guest %idle\n")
268
+ }
269
+
270
+ printCoreUsage(cpu_dat.Writer, prev_rec.Time.Sub(t0).Seconds(), coreusage)
271
+ }
272
+ printCoreUsage(cpu_writer, prev_rec.Time.Sub(t0).Seconds(), cusage.All)
273
+
274
+ curr ^= 1
275
+ meta_set = true
276
+ }
277
+
278
+ meta.EndTime = float64(records[curr^1].Time.UnixNano()) / 1.0e9
279
+
280
+ for _, disk_dat := range disk_dat_files {
281
+ disk_dat.Writer.Flush()
282
+ disk_dat.File.Close()
283
+ }
284
+
285
+ f, err = os.Create(opt.DiskFile)
286
+ if err != nil {
287
+ panic(err)
288
+ }
289
+ defer f.Close()
290
+ df_writer := bufio.NewWriter(f)
291
+
292
+ for _, dev := range meta.Disk.Devices {
293
+ disk_dat, ok := disk_dat_files[dev.Name]
294
+ if !ok {
295
+ panic(dev.Name)
296
+ }
297
+
298
+ content, err := ioutil.ReadFile(disk_dat.Path)
299
+ if err != nil {
300
+ panic(err)
301
+ }
302
+
303
+ df_writer.Write(content)
304
+
305
+ os.Remove(disk_dat.Path)
306
+ }
307
+ df_writer.Flush()
308
+
309
+ for _, cpu_dat := range cpu_dat_files {
310
+ cpu_dat.Writer.Flush()
311
+ cpu_dat.File.Close()
312
+
313
+ content, err := ioutil.ReadFile(cpu_dat.Path)
314
+ if err != nil {
315
+ panic(err)
316
+ }
317
+
318
+ cpu_writer.Write(content)
319
+ os.Remove(cpu_dat.Path)
320
+ }
321
+ cpu_writer.Flush()
322
+
323
+ json_enc := json.NewEncoder(os.Stdout)
324
+ json_enc.Encode(meta)
325
+ }
@@ -96,7 +96,19 @@ func GetCpuCoreUsage(c1 *CpuCoreStat, c2 *CpuCoreStat) (*CpuCoreUsage, error) {
96
96
  itv := c2.Uptime() - c1.Uptime()
97
97
 
98
98
  if itv == 0 {
99
- return nil, errors.New("uptime difference is zero")
99
+ // return nil, errors.New("uptime difference is zero")
100
+ usage.User = 0
101
+ usage.Nice = 0
102
+ usage.Sys = 0
103
+ usage.Idle = 0
104
+ usage.Iowait = 0
105
+ usage.Hardirq = 0
106
+ usage.Softirq = 0
107
+ usage.Steal = 0
108
+ usage.Guest = 0
109
+ usage.GuestNice = 0
110
+
111
+ return usage, nil
100
112
  } else if itv < 0 {
101
113
  return nil, errors.New("uptime difference is negative")
102
114
  }
data/lib/perfmonger.rb CHANGED
@@ -13,3 +13,4 @@ require 'perfmonger/command/play.rb'
13
13
  require 'perfmonger/command/plot.rb'
14
14
  require 'perfmonger/command/server.rb'
15
15
  require 'perfmonger/command/fingerprint.rb'
16
+ require 'perfmonger/command/init-shell.rb'
@@ -55,6 +55,10 @@ class CoreFinder
55
55
  def summarizer
56
56
  self.find("summarizer")
57
57
  end
58
+
59
+ def plot_formatter
60
+ self.find("plot-formatter")
61
+ end
58
62
  end
59
63
  end
60
64