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