perfmonger 0.10.2 → 0.12.1
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 +5 -5
- data/.gitignore +3 -0
- data/.travis.yml +9 -8
- data/HOWTO.md +0 -1
- data/NEWS +49 -5
- data/README.md +77 -27
- data/Rakefile +33 -11
- data/core/Makefile +22 -31
- data/core/build.sh +6 -8
- data/core/cmd/perfmonger-player/perfmonger-player.go +247 -0
- data/core/{perfmonger-plot-formatter.go → cmd/perfmonger-plot-formatter/perfmonger-plot-formatter.go} +20 -5
- data/core/{perfmonger-recorder.go → cmd/perfmonger-recorder/perfmonger-recorder.go} +22 -2
- data/core/{perfmonger-summarizer.go → cmd/perfmonger-summarizer/perfmonger-summarizer.go} +22 -15
- data/core/cmd/perfmonger-viewer/perfmonger-viewer.go +164 -0
- data/core/go.mod +10 -0
- data/core/go.sum +17 -0
- data/core/subsystem/Makefile +4 -0
- data/core/subsystem/perfmonger_linux.go +95 -0
- data/core/subsystem/perfmonger_linux_test.go +40 -0
- data/core/subsystem/stat.go +70 -0
- data/core/subsystem/stat_test.go +9 -0
- data/core/subsystem/usage.go +223 -66
- data/core/subsystem/usage_test.go +62 -32
- data/core/utils.go +2 -2
- data/{bin → exe}/perfmonger +0 -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/exec/perfmonger-viewer_darwin_amd64 +0 -0
- data/lib/exec/perfmonger-viewer_linux_amd64 +0 -0
- data/lib/perfmonger/command/fingerprint.rb +26 -1
- data/lib/perfmonger/command/live.rb +19 -0
- data/lib/perfmonger/command/play.rb +16 -0
- data/lib/perfmonger/command/plot.rb +23 -9
- data/lib/perfmonger/command/record.rb +24 -3
- data/lib/perfmonger/command/record_option.rb +16 -0
- data/lib/perfmonger/command/server.rb +1 -1
- data/lib/perfmonger/version.rb +1 -1
- data/misc/werker-box/Dockerfile +34 -0
- data/misc/werker-box/build-push.sh +7 -0
- data/perfmonger.gemspec +2 -1
- data/spec/data/busy100.pgr.played +3 -3
- data/spec/fingerprint_spec.rb +1 -1
- data/spec/live_spec.rb +2 -3
- data/spec/perfmonger_spec.rb +1 -1
- data/spec/play_spec.rb +1 -1
- data/spec/plot_spec.rb +16 -1
- data/spec/record_spec.rb +10 -1
- data/spec/spec_helper.rb +28 -3
- data/spec/stat_spec.rb +2 -2
- data/spec/summary_spec.rb +1 -1
- data/wercker.yml +29 -16
- metadata +34 -14
- data/core/perfmonger-player.go +0 -196
- data/lib/exec/perfmonger-player_linux_386 +0 -0
- data/lib/exec/perfmonger-plot-formatter_linux_386 +0 -0
- data/lib/exec/perfmonger-recorder_linux_386 +0 -0
- data/lib/exec/perfmonger-summarizer_linux_386 +0 -0
data/spec/perfmonger_spec.rb
CHANGED
data/spec/play_spec.rb
CHANGED
data/spec/plot_spec.rb
CHANGED
@@ -2,7 +2,7 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
# TODO: examples for options
|
4
4
|
|
5
|
-
describe '[plot] subcommand' do
|
5
|
+
RSpec.describe '[plot] subcommand' do
|
6
6
|
let(:busy100_disk_dat) {
|
7
7
|
File.read(data_file "busy100.pgr.plot-formatted.disk.dat")
|
8
8
|
}
|
@@ -74,4 +74,19 @@ describe '[plot] subcommand' do
|
|
74
74
|
expect("disk.dat").to have_file_content busy100_disk_dat
|
75
75
|
expect("cpu.dat").to have_file_content busy100_cpu_dat
|
76
76
|
end
|
77
|
+
|
78
|
+
it "should work with --disk-only option" do
|
79
|
+
busy100 = data_file "busy100.pgr.gz"
|
80
|
+
|
81
|
+
cmd = "#{perfmonger_bin} plot --save #{busy100} --disk-only sda1"
|
82
|
+
|
83
|
+
run(cmd, 30)
|
84
|
+
|
85
|
+
expect(last_command_started).to be_successfully_executed
|
86
|
+
|
87
|
+
disk_dat = File.expand_path("disk.dat", last_command_started.working_directory)
|
88
|
+
total_write_iops = `cat #{disk_dat}|grep total -A 2|tail -n1|awk '{print $3}'`.to_f
|
89
|
+
|
90
|
+
expect(total_write_iops).to be_within(1.67).of(0.01)
|
91
|
+
end
|
77
92
|
end
|
data/spec/record_spec.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe '[record] subcommand' do
|
3
|
+
RSpec.describe '[record] subcommand' do
|
4
4
|
before(:each) do
|
5
5
|
skip_if_proc_is_not_available
|
6
6
|
end
|
@@ -9,7 +9,16 @@ describe '[record] subcommand' do
|
|
9
9
|
cmd = "#{perfmonger_bin} record --timeout 1"
|
10
10
|
run(cmd)
|
11
11
|
expect(last_command_started).to be_successfully_executed
|
12
|
+
expect("perfmonger.pgr.gz").to be_an_existing_file # default file name
|
13
|
+
expect(last_command_started.stdout).to be_empty
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should create a non-gzipped logfile' do
|
17
|
+
cmd = "#{perfmonger_bin} record --timeout 1 --no-gzip"
|
18
|
+
run(cmd)
|
19
|
+
expect(last_command_started).to be_successfully_executed
|
12
20
|
expect("perfmonger.pgr").to be_an_existing_file # default file name
|
13
21
|
expect(last_command_started.stdout).to be_empty
|
14
22
|
end
|
23
|
+
|
15
24
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -19,15 +19,40 @@ def data_file(rel_path)
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def perfmonger_bin
|
22
|
-
File.expand_path('../../
|
22
|
+
File.expand_path('../../exe/perfmonger', __FILE__)
|
23
23
|
end
|
24
24
|
|
25
25
|
RSpec.configure do |config|
|
26
|
-
|
26
|
+
config.expect_with :rspec do |expectations|
|
27
|
+
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
28
|
+
end
|
29
|
+
|
30
|
+
config.mock_with :rspec do |mocks|
|
31
|
+
mocks.verify_partial_doubles = true
|
32
|
+
end
|
33
|
+
|
34
|
+
config.shared_context_metadata_behavior = :apply_to_host_groups
|
35
|
+
|
36
|
+
config.filter_run_when_matching :focus
|
37
|
+
|
38
|
+
config.example_status_persistence_file_path = "spec/examples.txt"
|
39
|
+
|
40
|
+
config.disable_monkey_patching!
|
41
|
+
|
42
|
+
config.warnings = true
|
43
|
+
|
44
|
+
if config.files_to_run.one?
|
45
|
+
config.default_formatter = "doc"
|
46
|
+
end
|
47
|
+
|
48
|
+
config.profile_examples = 10
|
49
|
+
|
50
|
+
config.order = :random
|
51
|
+
# Kernel.srand config.seed
|
27
52
|
end
|
28
53
|
|
29
54
|
def skip_if_proc_is_not_available
|
30
|
-
if ! File.
|
55
|
+
if ! File.exist?("/proc/diskstats")
|
31
56
|
skip "/proc/diskstats is not available."
|
32
57
|
end
|
33
58
|
end
|
data/spec/stat_spec.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
|
2
2
|
require 'spec_helper'
|
3
3
|
|
4
|
-
describe '[stat] subcommand' do
|
4
|
+
RSpec.describe '[stat] subcommand' do
|
5
5
|
before(:each) do
|
6
6
|
skip_if_proc_is_not_available
|
7
7
|
end
|
@@ -10,6 +10,6 @@ describe '[stat] subcommand' do
|
|
10
10
|
cmd = "#{perfmonger_bin} stat -- sleep 1"
|
11
11
|
run(cmd)
|
12
12
|
expect(last_command_started).to be_successfully_executed
|
13
|
-
expect("perfmonger.pgr").to be_an_existing_file
|
13
|
+
expect("perfmonger.pgr.gz").to be_an_existing_file
|
14
14
|
end
|
15
15
|
end
|
data/spec/summary_spec.rb
CHANGED
data/wercker.yml
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
box: hayamiz/rvm-
|
1
|
+
box: hayamiz/go-rvm:wercker-env-0.11.2
|
2
2
|
# Build definition
|
3
3
|
build:
|
4
4
|
# The steps that will be executed on build
|
@@ -6,19 +6,17 @@ build:
|
|
6
6
|
# http://devcenter.wercker.com/articles/languages/ruby.html
|
7
7
|
steps:
|
8
8
|
- script:
|
9
|
-
name:
|
9
|
+
name: prepare perfmonger go subsystem
|
10
10
|
code: |
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
source /etc/profile.d/rvm.sh
|
12
|
+
rvm use 2.4.9
|
13
|
+
rake go_get
|
14
14
|
|
15
15
|
- script:
|
16
|
-
name:
|
16
|
+
name: switch ruby to 2.4.9
|
17
17
|
code: |
|
18
|
-
|
19
|
-
|
20
|
-
- rvm-use:
|
21
|
-
version: 1.9.3-p551
|
18
|
+
source /etc/profile.d/rvm.sh
|
19
|
+
rvm use 2.4.9
|
22
20
|
- bundle-install
|
23
21
|
- script:
|
24
22
|
name: run rspec
|
@@ -26,8 +24,11 @@ build:
|
|
26
24
|
bundle exec rake clean
|
27
25
|
bundle exec rake spec
|
28
26
|
|
29
|
-
-
|
30
|
-
|
27
|
+
- script:
|
28
|
+
name: switch ruby to 2.5.7
|
29
|
+
code: |
|
30
|
+
source /etc/profile.d/rvm.sh
|
31
|
+
rvm use 2.5.7
|
31
32
|
- bundle-install
|
32
33
|
- script:
|
33
34
|
name: run rspec
|
@@ -35,8 +36,11 @@ build:
|
|
35
36
|
bundle exec rake clean
|
36
37
|
bundle exec rake spec
|
37
38
|
|
38
|
-
-
|
39
|
-
|
39
|
+
- script:
|
40
|
+
name: switch ruby to 2.6.5
|
41
|
+
code: |
|
42
|
+
source /etc/profile.d/rvm.sh
|
43
|
+
rvm use 2.6.5
|
40
44
|
- bundle-install
|
41
45
|
- script:
|
42
46
|
name: run rspec
|
@@ -44,8 +48,11 @@ build:
|
|
44
48
|
bundle exec rake clean
|
45
49
|
bundle exec rake spec
|
46
50
|
|
47
|
-
-
|
48
|
-
|
51
|
+
- script:
|
52
|
+
name: switch ruby to 2.7.0
|
53
|
+
code: |
|
54
|
+
source /etc/profile.d/rvm.sh
|
55
|
+
rvm use 2.7.0
|
49
56
|
- bundle-install
|
50
57
|
- script:
|
51
58
|
name: run rspec
|
@@ -57,3 +64,9 @@ build:
|
|
57
64
|
name: run go test
|
58
65
|
code: |
|
59
66
|
bundle exec rake test_core
|
67
|
+
after-steps:
|
68
|
+
- slack-notifier:
|
69
|
+
url: $SLACK_URL
|
70
|
+
channel: pokeme
|
71
|
+
username: werckerbot
|
72
|
+
notify_on: "failed"
|
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.12.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yuto HAYAMIZU
|
8
8
|
autorequire:
|
9
|
-
bindir:
|
9
|
+
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-07-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -99,13 +99,15 @@ files:
|
|
99
99
|
- NEWS
|
100
100
|
- README.md
|
101
101
|
- Rakefile
|
102
|
-
- bin/perfmonger
|
103
102
|
- core/Makefile
|
104
103
|
- core/build.sh
|
105
|
-
- core/perfmonger-player.go
|
106
|
-
- core/perfmonger-plot-formatter.go
|
107
|
-
- core/perfmonger-recorder.go
|
108
|
-
- core/perfmonger-summarizer.go
|
104
|
+
- core/cmd/perfmonger-player/perfmonger-player.go
|
105
|
+
- core/cmd/perfmonger-plot-formatter/perfmonger-plot-formatter.go
|
106
|
+
- core/cmd/perfmonger-recorder/perfmonger-recorder.go
|
107
|
+
- core/cmd/perfmonger-summarizer/perfmonger-summarizer.go
|
108
|
+
- core/cmd/perfmonger-viewer/perfmonger-viewer.go
|
109
|
+
- core/go.mod
|
110
|
+
- core/go.sum
|
109
111
|
- core/subsystem/Makefile
|
110
112
|
- core/subsystem/perfmonger.go
|
111
113
|
- core/subsystem/perfmonger_darwin.go
|
@@ -129,18 +131,17 @@ files:
|
|
129
131
|
- data/assets/js/canvasjs.js
|
130
132
|
- data/assets/js/canvasjs.min.js
|
131
133
|
- data/sysstat.ioconf
|
134
|
+
- exe/perfmonger
|
132
135
|
- lib/exec/perfmonger-player_darwin_amd64
|
133
|
-
- lib/exec/perfmonger-player_linux_386
|
134
136
|
- lib/exec/perfmonger-player_linux_amd64
|
135
137
|
- lib/exec/perfmonger-plot-formatter_darwin_amd64
|
136
|
-
- lib/exec/perfmonger-plot-formatter_linux_386
|
137
138
|
- lib/exec/perfmonger-plot-formatter_linux_amd64
|
138
139
|
- lib/exec/perfmonger-recorder_darwin_amd64
|
139
|
-
- lib/exec/perfmonger-recorder_linux_386
|
140
140
|
- lib/exec/perfmonger-recorder_linux_amd64
|
141
141
|
- lib/exec/perfmonger-summarizer_darwin_amd64
|
142
|
-
- lib/exec/perfmonger-summarizer_linux_386
|
143
142
|
- lib/exec/perfmonger-summarizer_linux_amd64
|
143
|
+
- lib/exec/perfmonger-viewer_darwin_amd64
|
144
|
+
- lib/exec/perfmonger-viewer_linux_amd64
|
144
145
|
- lib/perfmonger.rb
|
145
146
|
- lib/perfmonger/cli.rb
|
146
147
|
- lib/perfmonger/command/base_command.rb
|
@@ -163,6 +164,8 @@ files:
|
|
163
164
|
- misc/release-howto.txt
|
164
165
|
- misc/sample-cpu.png
|
165
166
|
- misc/sample-read-iops.png
|
167
|
+
- misc/werker-box/Dockerfile
|
168
|
+
- misc/werker-box/build-push.sh
|
166
169
|
- perfmonger.gemspec
|
167
170
|
- spec/data/busy100.pgr
|
168
171
|
- spec/data/busy100.pgr.gz
|
@@ -214,8 +217,25 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
214
217
|
version: '0'
|
215
218
|
requirements: []
|
216
219
|
rubyforge_project:
|
217
|
-
rubygems_version: 2.
|
220
|
+
rubygems_version: 2.7.6
|
218
221
|
signing_key:
|
219
222
|
specification_version: 4
|
220
223
|
summary: yet anothor performance measurement/monitoring tool
|
221
|
-
test_files:
|
224
|
+
test_files:
|
225
|
+
- spec/data/busy100.pgr
|
226
|
+
- spec/data/busy100.pgr.gz
|
227
|
+
- spec/data/busy100.pgr.played
|
228
|
+
- spec/data/busy100.pgr.plot-formatted.cpu.dat
|
229
|
+
- spec/data/busy100.pgr.plot-formatted.disk.dat
|
230
|
+
- spec/data/busy100.pgr.summary
|
231
|
+
- spec/data/busy100.pgr.summary.json
|
232
|
+
- spec/fingerprint_spec.rb
|
233
|
+
- spec/live_spec.rb
|
234
|
+
- spec/perfmonger_spec.rb
|
235
|
+
- spec/play_spec.rb
|
236
|
+
- spec/plot_spec.rb
|
237
|
+
- spec/record_spec.rb
|
238
|
+
- spec/spec_helper.rb
|
239
|
+
- spec/stat_spec.rb
|
240
|
+
- spec/summary_spec.rb
|
241
|
+
- spec/support/aruba.rb
|
data/core/perfmonger-player.go
DELETED
@@ -1,196 +0,0 @@
|
|
1
|
-
//usr/bin/env go run $0 $@ ; exit
|
2
|
-
|
3
|
-
package main
|
4
|
-
|
5
|
-
import (
|
6
|
-
"bufio"
|
7
|
-
"bytes"
|
8
|
-
"encoding/gob"
|
9
|
-
"fmt"
|
10
|
-
"io"
|
11
|
-
"os"
|
12
|
-
|
13
|
-
ss "github.com/hayamiz/perfmonger/core/subsystem"
|
14
|
-
)
|
15
|
-
|
16
|
-
func showCpuStat(buffer *bytes.Buffer, prev_rec *ss.StatRecord, cur_rec *ss.StatRecord) error {
|
17
|
-
cusage, err := ss.GetCpuUsage(prev_rec.Cpu, cur_rec.Cpu)
|
18
|
-
if err != nil {
|
19
|
-
return err
|
20
|
-
}
|
21
|
-
buffer.WriteString(`,"cpu":`)
|
22
|
-
cusage.WriteJsonTo(buffer)
|
23
|
-
|
24
|
-
return nil
|
25
|
-
}
|
26
|
-
|
27
|
-
func showInterruptStat(buffer *bytes.Buffer, prev_rec *ss.StatRecord, cur_rec *ss.StatRecord) error {
|
28
|
-
// intr_usage, err := ss.GetInterruptUsage(
|
29
|
-
// prev_rec.Time, prev_rec.Interrupt,
|
30
|
-
// cur_rec.Time, cur_rec.Interrupt)
|
31
|
-
// if err != nil {
|
32
|
-
// return err
|
33
|
-
// }
|
34
|
-
//
|
35
|
-
// buffer.WriteString(`,"intr":`)
|
36
|
-
// intr_usage.WriteJsonTo(buffer)
|
37
|
-
//
|
38
|
-
// return nil
|
39
|
-
|
40
|
-
intr_usage, err := ss.GetInterruptUsage(
|
41
|
-
prev_rec.Time, prev_rec.Interrupt,
|
42
|
-
cur_rec.Time, cur_rec.Interrupt)
|
43
|
-
if err != nil {
|
44
|
-
return err
|
45
|
-
}
|
46
|
-
|
47
|
-
buffer.WriteString(`,"intr":`)
|
48
|
-
intr_usage.WriteJsonTo(buffer)
|
49
|
-
|
50
|
-
return nil
|
51
|
-
}
|
52
|
-
|
53
|
-
func showDiskStat(buffer *bytes.Buffer, prev_rec *ss.StatRecord, cur_rec *ss.StatRecord) error {
|
54
|
-
dusage, err := ss.GetDiskUsage(
|
55
|
-
prev_rec.Time, prev_rec.Disk,
|
56
|
-
cur_rec.Time, cur_rec.Disk)
|
57
|
-
if err != nil {
|
58
|
-
return err
|
59
|
-
}
|
60
|
-
|
61
|
-
buffer.WriteString(`,"disk":`)
|
62
|
-
dusage.WriteJsonTo(buffer)
|
63
|
-
|
64
|
-
return nil
|
65
|
-
}
|
66
|
-
|
67
|
-
func showNetStat(buffer *bytes.Buffer, prev_rec *ss.StatRecord, cur_rec *ss.StatRecord) error {
|
68
|
-
dusage, err := ss.GetNetUsage(
|
69
|
-
prev_rec.Time, prev_rec.Net,
|
70
|
-
cur_rec.Time, cur_rec.Net,
|
71
|
-
)
|
72
|
-
if err != nil {
|
73
|
-
return err
|
74
|
-
}
|
75
|
-
|
76
|
-
buffer.WriteString(`,"net":`)
|
77
|
-
dusage.WriteJsonTo(buffer)
|
78
|
-
|
79
|
-
return nil
|
80
|
-
}
|
81
|
-
|
82
|
-
func showStat(buffer *bytes.Buffer, prev_rec *ss.StatRecord, cur_rec *ss.StatRecord) error {
|
83
|
-
buffer.WriteString(fmt.Sprintf(`{"time":%.3f`, float64(cur_rec.Time.UnixNano())/1e9))
|
84
|
-
if cur_rec.Cpu != nil {
|
85
|
-
err := showCpuStat(buffer, prev_rec, cur_rec)
|
86
|
-
if err != nil {
|
87
|
-
return err
|
88
|
-
}
|
89
|
-
}
|
90
|
-
if cur_rec.Interrupt != nil {
|
91
|
-
err := showInterruptStat(buffer, prev_rec, cur_rec)
|
92
|
-
if err != nil {
|
93
|
-
return err
|
94
|
-
}
|
95
|
-
}
|
96
|
-
if cur_rec.Disk != nil {
|
97
|
-
err := showDiskStat(buffer, prev_rec, cur_rec)
|
98
|
-
if err != nil {
|
99
|
-
return err
|
100
|
-
}
|
101
|
-
}
|
102
|
-
if cur_rec.Net != nil {
|
103
|
-
err := showNetStat(buffer, prev_rec, cur_rec)
|
104
|
-
if err != nil {
|
105
|
-
return err
|
106
|
-
}
|
107
|
-
}
|
108
|
-
buffer.WriteString("}\n")
|
109
|
-
|
110
|
-
return nil
|
111
|
-
}
|
112
|
-
|
113
|
-
func main() {
|
114
|
-
args := os.Args
|
115
|
-
var in *os.File
|
116
|
-
var out *bufio.Writer
|
117
|
-
|
118
|
-
if len(args) < 2 {
|
119
|
-
in = os.Stdin
|
120
|
-
} else {
|
121
|
-
f, err := os.Open(args[1])
|
122
|
-
if err != nil {
|
123
|
-
panic(err)
|
124
|
-
}
|
125
|
-
in = f
|
126
|
-
defer f.Close()
|
127
|
-
}
|
128
|
-
input_reader := newPerfmongerLogReader(in)
|
129
|
-
dec := gob.NewDecoder(input_reader)
|
130
|
-
|
131
|
-
out = bufio.NewWriter(os.Stdout)
|
132
|
-
|
133
|
-
var cheader ss.CommonHeader
|
134
|
-
var pheader ss.PlatformHeader
|
135
|
-
var records = make([]ss.StatRecord, 2)
|
136
|
-
curr := 0
|
137
|
-
|
138
|
-
var err error
|
139
|
-
|
140
|
-
err = dec.Decode(&cheader)
|
141
|
-
if err == io.EOF {
|
142
|
-
return
|
143
|
-
}
|
144
|
-
if err != nil {
|
145
|
-
panic(err)
|
146
|
-
}
|
147
|
-
err = dec.Decode(&pheader)
|
148
|
-
if err == io.EOF {
|
149
|
-
return
|
150
|
-
}
|
151
|
-
if err != nil {
|
152
|
-
panic(err)
|
153
|
-
}
|
154
|
-
|
155
|
-
// read first record
|
156
|
-
err = dec.Decode(&records[curr])
|
157
|
-
if err == io.EOF {
|
158
|
-
return
|
159
|
-
} else if err != nil {
|
160
|
-
panic(err)
|
161
|
-
}
|
162
|
-
curr ^= 1
|
163
|
-
|
164
|
-
buffer := bytes.NewBuffer([]byte{})
|
165
|
-
for {
|
166
|
-
prev_rec := &records[curr^1]
|
167
|
-
cur_rec := &records[curr]
|
168
|
-
|
169
|
-
err = dec.Decode(cur_rec)
|
170
|
-
if err == io.EOF {
|
171
|
-
break
|
172
|
-
} else if err != nil {
|
173
|
-
panic(err)
|
174
|
-
}
|
175
|
-
|
176
|
-
err = showStat(buffer, prev_rec, cur_rec)
|
177
|
-
if err != nil {
|
178
|
-
buffer.Reset()
|
179
|
-
fmt.Fprintln(os.Stderr, "skip by err")
|
180
|
-
continue
|
181
|
-
}
|
182
|
-
|
183
|
-
_, err = out.WriteString(buffer.String())
|
184
|
-
err = out.Flush()
|
185
|
-
if err != nil {
|
186
|
-
// stdout is closed
|
187
|
-
break
|
188
|
-
}
|
189
|
-
|
190
|
-
buffer.Reset()
|
191
|
-
|
192
|
-
curr ^= 1
|
193
|
-
}
|
194
|
-
|
195
|
-
return
|
196
|
-
}
|