perfmonger 0.8.2 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
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