fwd 0.3.1 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile.lock +1 -1
- data/benchmark/performance.rb +31 -25
- data/fwd.gemspec +1 -1
- data/lib/fwd/buffer.rb +5 -6
- data/lib/fwd/cli.rb +8 -5
- data/lib/fwd.rb +5 -3
- data/spec/fwd/buffer_spec.rb +5 -5
- data/spec/fwd/cli_spec.rb +1 -2
- data/spec/spec_helper.rb +1 -1
- metadata +1 -1
data/Gemfile.lock
CHANGED
data/benchmark/performance.rb
CHANGED
@@ -1,40 +1,46 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
require 'bundler/setup'
|
3
|
+
require 'pathname'
|
6
4
|
require 'benchmark'
|
7
|
-
require '
|
8
|
-
require '
|
5
|
+
require 'socket'
|
6
|
+
require 'fileutils'
|
9
7
|
|
10
8
|
root = Pathname.new(File.expand_path('../..', __FILE__))
|
11
|
-
|
12
|
-
FileUtils.
|
9
|
+
tmp = root.join("tmp/benchmark")
|
10
|
+
FileUtils.rm_rf tmp
|
11
|
+
FileUtils.mkdir_p tmp
|
13
12
|
|
14
|
-
|
15
|
-
|
16
|
-
|
13
|
+
OUT = tmp.join('out.txt')
|
14
|
+
FWD = fork { exec "#{root}/bin/fwd-rb --flush 10000:2 -F tcp://0.0.0.0:7291 --path #{tmp} -v" }
|
15
|
+
NCC = fork { exec "nc -vlp 7291 > #{OUT}" }
|
17
16
|
|
18
|
-
|
19
|
-
|
20
|
-
|
17
|
+
at_exit do
|
18
|
+
Process.kill(:TERM, FWD)
|
19
|
+
Process.kill(:TERM, NCC)
|
21
20
|
end
|
22
|
-
|
21
|
+
|
22
|
+
sleep(3)
|
23
|
+
|
24
|
+
EVENTS = 10_000_000
|
25
|
+
LENGTH = 100
|
26
|
+
DATA = "A" * LENGTH
|
27
|
+
|
28
|
+
ds = Benchmark.realtime do
|
23
29
|
sock = TCPSocket.new "127.0.0.1", 7289
|
24
30
|
EVENTS.times { sock.write DATA }
|
25
31
|
sock.close
|
26
32
|
end
|
27
33
|
|
28
|
-
|
29
|
-
|
30
|
-
|
34
|
+
rs = Benchmark.realtime do
|
35
|
+
while OUT.size < EVENTS * LENGTH
|
36
|
+
sleep(1)
|
37
|
+
puts "--> Written : #{(OUT.size / 1024.0 / 1024.0).round(1)}M of #{(EVENTS * LENGTH / 1024.0 / 1024.0).round(1)}M"
|
38
|
+
end
|
31
39
|
end
|
32
40
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
puts "Written #{(OUTF.size / 1024.0 / 1024.0).round(1)}M"
|
40
|
-
end
|
41
|
+
sleep(3)
|
42
|
+
puts "--> Dispatched in : #{ds.round(1)}s"
|
43
|
+
puts "--> Completed in : #{(ds + rs).round(1)}s"
|
44
|
+
puts "--> FWD RSS : #{(`ps -o rss= -p #{FWD}`.to_f / 1024).round(1)}M"
|
45
|
+
puts "--> Processed : #{EVENTS} events"
|
46
|
+
puts "--> Written : #{(OUT.size / 1024.0 / 1024.0).round(1)}M"
|
data/fwd.gemspec
CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |s|
|
|
9
9
|
s.name = File.basename(__FILE__, '.gemspec')
|
10
10
|
s.summary = "fwd >>"
|
11
11
|
s.description = "The minimalistic stream forwarder"
|
12
|
-
s.version = "0.3.
|
12
|
+
s.version = "0.3.2"
|
13
13
|
|
14
14
|
s.authors = ["Black Square Media"]
|
15
15
|
s.email = "info@blacksquaremedia.com"
|
data/lib/fwd/buffer.rb
CHANGED
@@ -2,7 +2,7 @@ class Fwd::Buffer
|
|
2
2
|
extend Forwardable
|
3
3
|
def_delegators :core, :root, :prefix, :logger
|
4
4
|
|
5
|
-
|
5
|
+
MAX_LIMIT = 64 * 1024 * 1024 # 64M
|
6
6
|
attr_reader :core, :interval, :rate, :count, :limit, :timer, :fd
|
7
7
|
|
8
8
|
# Constructor
|
@@ -11,7 +11,7 @@ class Fwd::Buffer
|
|
11
11
|
@core = core
|
12
12
|
@interval = (core.opts[:flush_interval] || 60).to_i
|
13
13
|
@rate = (core.opts[:flush_rate] || 10_000).to_i
|
14
|
-
@limit =
|
14
|
+
@limit = [core.opts[:buffer_limit].to_i, MAX_LIMIT].reject(&:zero?).min
|
15
15
|
@count = 0
|
16
16
|
|
17
17
|
reschedule!
|
@@ -37,8 +37,7 @@ class Fwd::Buffer
|
|
37
37
|
|
38
38
|
# @return [Boolean] true if flush is due
|
39
39
|
def flush?
|
40
|
-
|
41
|
-
(@rate > 0 && @count >= @rate) || (@limit > 0 && @fd.size >= @limit)
|
40
|
+
@rate > 0 && @count >= @rate
|
42
41
|
end
|
43
42
|
|
44
43
|
# (Force) rotate buffer file
|
@@ -46,7 +45,7 @@ class Fwd::Buffer
|
|
46
45
|
return if @fd && @fd.size.zero?
|
47
46
|
|
48
47
|
if @fd
|
49
|
-
logger.debug { "
|
48
|
+
logger.debug { "Rotating #{File.basename(@fd.path)}, #{@fd.size / 1024} kB" }
|
50
49
|
FileUtils.mv(@fd.path, @fd.path.sub(/\.open$/, ".closed"))
|
51
50
|
end
|
52
51
|
|
@@ -56,7 +55,7 @@ class Fwd::Buffer
|
|
56
55
|
|
57
56
|
# @return [Boolean] true if rotation is due
|
58
57
|
def rotate?
|
59
|
-
@fd.nil? || @fd.size
|
58
|
+
@fd.nil? || @fd.size >= @limit
|
60
59
|
rescue Errno::ENOENT
|
61
60
|
false
|
62
61
|
end
|
data/lib/fwd/cli.rb
CHANGED
@@ -32,13 +32,12 @@ class Fwd::CLI < Hash
|
|
32
32
|
update forward: uris.map {|uri| URI.parse(uri).to_s }
|
33
33
|
end
|
34
34
|
|
35
|
-
o.on("-f", "--flush
|
35
|
+
o.on("-f", "--flush M:N",
|
36
36
|
"Flush after an interval of N seconds, " <<
|
37
37
|
"or after receiving M messages, " <<
|
38
|
-
"
|
39
|
-
"
|
40
|
-
|
41
|
-
update flush_limit: l.to_i, flush_rate: m.to_i, flush_interval: n.to_i
|
38
|
+
"Default: 10000:60") do |values|
|
39
|
+
m,n = values.split(":").map(&:to_i)
|
40
|
+
update flush_rate: m.to_i, flush_interval: n.to_i
|
42
41
|
end
|
43
42
|
|
44
43
|
o.on("--path PATH", "Root path for storage. Default: ./tmp") do |path|
|
@@ -49,6 +48,10 @@ class Fwd::CLI < Hash
|
|
49
48
|
update prefix: prefix
|
50
49
|
end
|
51
50
|
|
51
|
+
o.on("-v", "--verbose", "Enable verbose logging.") do |_|
|
52
|
+
Fwd.logger.level = Logger::DEBUG
|
53
|
+
end
|
54
|
+
|
52
55
|
o.separator ""
|
53
56
|
o.on_tail("-h", "--help", "Show this message") do
|
54
57
|
puts o
|
data/lib/fwd.rb
CHANGED
@@ -17,7 +17,9 @@ class Fwd
|
|
17
17
|
|
18
18
|
# [Logger] logger instance
|
19
19
|
def logger
|
20
|
-
@logger ||= ::Logger.new(STDOUT)
|
20
|
+
@logger ||= ::Logger.new(STDOUT).tap do |l|
|
21
|
+
l.level = ::Logger::INFO
|
22
|
+
end
|
21
23
|
end
|
22
24
|
|
23
25
|
end
|
@@ -43,8 +45,8 @@ class Fwd
|
|
43
45
|
# @option opts [String] prefix buffer file prefix
|
44
46
|
# @option opts [URI] bind the endpoint to listen to
|
45
47
|
# @option opts [Array<URI>] forward the endpoints to forward to
|
46
|
-
# @option opts [Integer]
|
47
|
-
# @option opts [Integer] flush_rate flush after
|
48
|
+
# @option opts [Integer] buffer_limit limit buffer files to N bytes
|
49
|
+
# @option opts [Integer] flush_rate flush after N messages
|
48
50
|
# @option opts [Integer] flush_interval flush after N seconds
|
49
51
|
def initialize(opts = {})
|
50
52
|
@bind = URI.parse(opts[:bind] || "tcp://0.0.0.0:7289")
|
data/spec/fwd/buffer_spec.rb
CHANGED
@@ -39,6 +39,11 @@ describe Fwd::Buffer do
|
|
39
39
|
before { buffer }
|
40
40
|
subject { lambda { buffer.rotate! } }
|
41
41
|
|
42
|
+
it 'should trigger when buffer limit is reached' do
|
43
|
+
lambda { buffer.concat("x" * 2048) }.should_not change { buffer.fd.path }
|
44
|
+
lambda { buffer.concat("x") }.should change { buffer.fd.path }
|
45
|
+
end
|
46
|
+
|
42
47
|
describe "when changed" do
|
43
48
|
before { buffer.concat("x" * 1024) }
|
44
49
|
|
@@ -67,11 +72,6 @@ describe Fwd::Buffer do
|
|
67
72
|
lambda { subject.concat("x") }.should change { subject.count }.from(19).to(0)
|
68
73
|
end
|
69
74
|
|
70
|
-
it 'should trigger when flush limit is reached' do
|
71
|
-
subject.concat("x" * 1024)
|
72
|
-
lambda { subject.concat("x" * 1024) }.should change { subject.count }.from(1).to(0)
|
73
|
-
end
|
74
|
-
|
75
75
|
it 'should reset count' do
|
76
76
|
3.times { subject.concat("x") }
|
77
77
|
lambda { subject.flush! }.should change { subject.count }.from(3).to(0)
|
data/spec/fwd/cli_spec.rb
CHANGED
@@ -8,7 +8,7 @@ describe Fwd::CLI do
|
|
8
8
|
"--prefix", "prefix",
|
9
9
|
"--bind", "tcp://127.0.0.1:7289",
|
10
10
|
"--forward", "tcp://1.2.3.4:1234,tcp://1.2.3.5:1235",
|
11
|
-
"--flush", "
|
11
|
+
"--flush", "1200:90",
|
12
12
|
]
|
13
13
|
end
|
14
14
|
|
@@ -17,7 +17,6 @@ describe Fwd::CLI do
|
|
17
17
|
its([:prefix]) { should == "prefix" }
|
18
18
|
its([:bind]) { should == "tcp://127.0.0.1:7289" }
|
19
19
|
its([:forward]) { should == ["tcp://1.2.3.4:1234", "tcp://1.2.3.5:1235"] }
|
20
|
-
its([:flush_limit]) { should == 30 }
|
21
20
|
its([:flush_rate]) { should == 1200 }
|
22
21
|
its([:flush_interval]) { should == 90 }
|
23
22
|
its(:core) { should be_instance_of(Fwd) }
|
data/spec/spec_helper.rb
CHANGED