summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKazuki Yamaguchi <k@rhe.jp>2015-10-25 18:42:29 +0900
committerKazuki Yamaguchi <k@rhe.jp>2015-10-25 18:42:29 +0900
commit302eb02fd9b97361b44c66c14827bdd82b46bc71 (patch)
tree814b53cb98bd2e5019752ace816c34c81d5a1390
parent4d5d63bc80e13b0449799f721df768bff2088c44 (diff)
downloadplum-302eb02fd9b97361b44c66c14827bdd82b46bc71.tar.gz
improve performance
-rw-r--r--lib/plum/binary_string.rb2
-rw-r--r--lib/plum/connection.rb2
-rw-r--r--lib/plum/connection_utils.rb2
-rw-r--r--lib/plum/event_emitter.rb6
-rw-r--r--lib/plum/flow_control.rb25
-rw-r--r--lib/plum/frame.rb17
-rw-r--r--lib/plum/hpack/constants.rb92
-rw-r--r--lib/plum/hpack/decoder.rb10
-rw-r--r--lib/plum/hpack/encoder.rb2
-rw-r--r--lib/plum/stream.rb38
10 files changed, 105 insertions, 91 deletions
diff --git a/lib/plum/binary_string.rb b/lib/plum/binary_string.rb
index 053be05..8c98693 100644
--- a/lib/plum/binary_string.rb
+++ b/lib/plum/binary_string.rb
@@ -17,7 +17,7 @@ module Plum
# @param pos [Integer] The start position to read.
def uint24(pos = 0)
a, b = byteslice(pos, 3).unpack("nC")
- (a * 0x100) | b
+ (a * 0x100) + b
end
# Reads a 32-bit unsigned integer.
diff --git a/lib/plum/connection.rb b/lib/plum/connection.rb
index 5c2db93..507ef75 100644
--- a/lib/plum/connection.rb
+++ b/lib/plum/connection.rb
@@ -121,7 +121,7 @@ module Plum
end
end
- if [:headers].include?(frame.type)
+ if frame.type == :headers
if !frame.end_headers?
@state = :waiting_continuation
@continuation_id = frame.stream_id
diff --git a/lib/plum/connection_utils.rb b/lib/plum/connection_utils.rb
index da1781c..1f837dd 100644
--- a/lib/plum/connection_utils.rb
+++ b/lib/plum/connection_utils.rb
@@ -22,7 +22,7 @@ module Plum
#
# @param error_type [Symbol] The error type to be contained in the GOAWAY frame.
def goaway(error_type = :no_error)
- last_id = @streams.keys.max || 0
+ last_id = @max_odd_stream_id > @max_even_stream_id ? @max_odd_stream_id : @max_even_stream_id
send_immediately Frame.goaway(last_id, error_type)
end
diff --git a/lib/plum/event_emitter.rb b/lib/plum/event_emitter.rb
index 3aa8e87..90484fc 100644
--- a/lib/plum/event_emitter.rb
+++ b/lib/plum/event_emitter.rb
@@ -4,16 +4,16 @@ module Plum
# @param name [String] The name of event.
# @yield Gives event-specific parameters.
def on(name, &blk)
- callbacks[name] << blk
+ (callbacks[name] ||= []) << blk
end
def callback(name, *args)
- callbacks[name].each {|cb| cb.call(*args) }
+ (cbs = callbacks[name]) && cbs.each {|cb| cb.call(*args) }
end
private
def callbacks
- @callbacks ||= Hash.new {|hash, key| hash[key] = [] }
+ @callbacks ||= {}
end
end
end
diff --git a/lib/plum/flow_control.rb b/lib/plum/flow_control.rb
index d1903a7..251507d 100644
--- a/lib/plum/flow_control.rb
+++ b/lib/plum/flow_control.rb
@@ -8,11 +8,17 @@ module Plum
#
# @param frame [Frame] The frame to be sent.
def send(frame)
- case frame.type
- when :data
+ if frame.type == :data
@send_buffer << frame
- callback(:send_deferred, frame) if @send_remaining_window < frame.length
- consume_send_buffer
+ if @send_remaining_window < frame.length
+ if Stream === self
+ connection.callback(:send_deferred, self, frame)
+ else
+ callback(:send_deferred, self, frame)
+ end
+ else
+ consume_send_buffer
+ end
else
send_immediately frame
end
@@ -23,7 +29,7 @@ module Plum
# @param wsi [Integer] The amount to increase receiving window size. The legal range is 1 to 2^32-1.
def window_update(wsi)
@recv_remaining_window += wsi
- payload = "".push_uint32(wsi & ~(1 << 31))
+ payload = "".push_uint32(wsi)
sid = (Stream === self) ? self.id : 0
send_immediately Frame.new(type: :window_update, stream_id: sid, payload: payload)
end
@@ -57,8 +63,7 @@ module Plum
end
def consume_recv_window(frame)
- case frame.type
- when :data
+ if frame.type == :data
@recv_remaining_window -= frame.length
if @recv_remaining_window < 0
local_error = (Connection === self) ? ConnectionError : StreamError
@@ -90,7 +95,11 @@ module Plum
raise local_error.new(:protocol_error)
end
- callback(:window_update, wsi)
+ if Stream === self
+ connection.callback(:window_update, self, wsi)
+ else
+ callback(:window_update, self, wsi)
+ end
@send_remaining_window += wsi
consume_send_buffer
diff --git a/lib/plum/frame.rb b/lib/plum/frame.rb
index f54938a..72fc2b9 100644
--- a/lib/plum/frame.rb
+++ b/lib/plum/frame.rb
@@ -76,12 +76,13 @@ module Plum
# [Integer] Flags. 8-bit
attr_accessor :flags_value
# [Integer] Stream Identifier. unsigned 31-bit integer
- attr_accessor :stream_id
+ attr_reader :stream_id
# [String] The payload.
- attr_accessor :payload
+ attr_reader :payload
def initialize(type: nil, type_value: nil, flags: nil, flags_value: nil, stream_id: nil, payload: nil)
- @payload = payload.to_s
+ @payload = payload || ""
+ @length = @payload.bytesize
@type_value = type_value or self.type = type
@flags_value = flags_value or self.flags = flags
@stream_id = stream_id or raise ArgumentError.new("stream_id is necessary")
@@ -90,7 +91,7 @@ module Plum
# Returns the length of payload.
# @return [Integer] The length.
def length
- @payload.bytesize
+ @length
end
# Returns the type of the frame in Symbol.
@@ -157,17 +158,15 @@ module Plum
length = buffer.uint24
return nil if buffer.bytesize < 9 + length
- bhead = buffer.byteshift(9)
- payload = buffer.byteshift(length)
-
- type_value, flags_value, r_sid = bhead.byteslice(3, 6).unpack("CCN")
+ cur = buffer.byteshift(9 + length)
+ type_value, flags_value, r_sid = cur.byteslice(3, 6).unpack("CCN")
# r = r_sid >> 31 # currently not used
stream_id = r_sid # & ~(1 << 31)
self.new(type_value: type_value,
flags_value: flags_value,
stream_id: stream_id,
- payload: payload).freeze
+ payload: cur.byteslice(9, length)).freeze
end
end
end
diff --git a/lib/plum/hpack/constants.rb b/lib/plum/hpack/constants.rb
index 1cd3b2b..0fe4caa 100644
--- a/lib/plum/hpack/constants.rb
+++ b/lib/plum/hpack/constants.rb
@@ -3,7 +3,7 @@ module Plum
# RFC7541 Appendix A
# index is starting from 0
STATIC_TABLE = [
- [":authority"],
+ [":authority", ""],
[":method", "GET"],
[":method", "POST"],
[":path", "/"],
@@ -19,51 +19,51 @@ module Plum
[":status", "500"],
["accept-charset"],
["accept-encoding", "gzip, deflate"],
- ["accept-language"],
- ["accept-ranges"],
- ["accept"],
- ["access-control-allow-origin"],
- ["age"],
- ["allow"],
- ["authorization"],
- ["cache-control"],
- ["content-disposition"],
- ["content-encoding"],
- ["content-language"],
- ["content-length"],
- ["content-location"],
- ["content-range"],
- ["content-type"],
- ["cookie"],
- ["date"],
- ["etag"],
- ["expect"],
- ["expires"],
- ["from"],
- ["host"],
- ["if-match"],
- ["if-modified-since"],
- ["if-none-match"],
- ["if-range"],
- ["if-unmodified-since"],
- ["last-modified"],
- ["link"],
- ["location"],
- ["max-forwards"],
- ["proxy-authenticate"],
- ["proxy-authorization"],
- ["range"],
- ["referer"],
- ["refresh"],
- ["retry-after"],
- ["server"],
- ["set-cookie"],
- ["strict-transport-security"],
- ["transfer-encoding"],
- ["user-agent"],
- ["vary"],
- ["via"],
- ["www-authenticate"],
+ ["accept-language", ""],
+ ["accept-ranges", ""],
+ ["accept", ""],
+ ["access-control-allow-origin", ""],
+ ["age", ""],
+ ["allow", ""],
+ ["authorization", ""],
+ ["cache-control", ""],
+ ["content-disposition", ""],
+ ["content-encoding", ""],
+ ["content-language", ""],
+ ["content-length", ""],
+ ["content-location", ""],
+ ["content-range", ""],
+ ["content-type", ""],
+ ["cookie", ""],
+ ["date", ""],
+ ["etag", ""],
+ ["expect", ""],
+ ["expires", ""],
+ ["from", ""],
+ ["host", ""],
+ ["if-match", ""],
+ ["if-modified-since", ""],
+ ["if-none-match", ""],
+ ["if-range", ""],
+ ["if-unmodified-since", ""],
+ ["last-modified", ""],
+ ["link", ""],
+ ["location", ""],
+ ["max-forwards", ""],
+ ["proxy-authenticate", ""],
+ ["proxy-authorization", ""],
+ ["range", ""],
+ ["referer", ""],
+ ["refresh", ""],
+ ["retry-after", ""],
+ ["server", ""],
+ ["set-cookie", ""],
+ ["strict-transport-security", ""],
+ ["transfer-encoding", ""],
+ ["user-agent", ""],
+ ["vary", ""],
+ ["via", ""],
+ ["www-authenticate", ""],
].freeze
HUFFMAN_TABLE = [
diff --git a/lib/plum/hpack/decoder.rb b/lib/plum/hpack/decoder.rb
index b536123..2efa865 100644
--- a/lib/plum/hpack/decoder.rb
+++ b/lib/plum/hpack/decoder.rb
@@ -23,7 +23,7 @@ module Plum
private
def parse(str, pos)
- first_byte = str.uint8(pos)
+ first_byte = str.getbyte(pos)
if first_byte >= 0x80 # 0b1XXXXXXX
parse_indexed(str, pos)
elsif first_byte >= 0x40 # 0b01XXXXXX
@@ -38,11 +38,11 @@ module Plum
def read_integer(str, pos, prefix_length)
raise HPACKError.new("integer: end of buffer") if str.empty?
- first_byte = str.uint8(pos)
+ first_byte = str.getbyte(pos)
- mask = (1 << prefix_length) - 1
- ret = first_byte & mask
- return [ret, 1] if ret != mask
+ mask = 1 << prefix_length
+ ret = first_byte % mask
+ return [ret, 1] if ret != mask - 1
octets = 0
while next_value = str.uint8(pos + octets + 1)
diff --git a/lib/plum/hpack/encoder.rb b/lib/plum/hpack/encoder.rb
index d78f96e..152b0fe 100644
--- a/lib/plum/hpack/encoder.rb
+++ b/lib/plum/hpack/encoder.rb
@@ -101,7 +101,7 @@ module Plum
end
def encode_string_plain(str)
- encode_integer(str.bytesize, 7, 0b00000000) << str.force_encoding(Encoding::BINARY)
+ encode_integer(str.bytesize, 7, 0b00000000) << str
end
def encode_string_huffman(str)
diff --git a/lib/plum/stream.rb b/lib/plum/stream.rb
index 7987532..725505d 100644
--- a/lib/plum/stream.rb
+++ b/lib/plum/stream.rb
@@ -8,25 +8,21 @@ module Plum
attr_reader :id, :state, :connection
attr_reader :weight, :exclusive
attr_accessor :parent
+ # The child (depending on this stream) streams.
+ attr_reader :children
def initialize(con, id, state: :idle, weight: 16, parent: nil, exclusive: false)
@connection = con
@id = id
@state = state
@continuation = []
+ @children = Set.new
initialize_flow_control(send: @connection.remote_settings[:initial_window_size],
recv: @connection.local_settings[:initial_window_size])
update_dependency(weight: weight, parent: parent, exclusive: exclusive)
end
- # Returns the child (depending on this stream) streams.
- #
- # @return [Array<Stream>] The child streams.
- def children
- @connection.streams.values.select {|c| c.parent == self }.freeze
- end
-
# Processes received frames for this stream. Internal use.
# @private
def receive_frame(frame)
@@ -66,20 +62,30 @@ module Plum
private
def send_immediately(frame)
- callback(:send_frame, frame)
@connection.send(frame)
end
def update_dependency(weight: nil, parent: nil, exclusive: nil)
raise StreamError.new(:protocol_error, "A stream cannot depend on itself.") if parent == self
- @weight = weight unless weight.nil?
- @parent = parent unless parent.nil?
- @exclusive = exclusive unless exclusive.nil?
-
- if exclusive == true
- parent.children.each do |child|
- next if child == self
- child.parent = self
+
+ if weight
+ @weight = weight
+ end
+
+ if parent
+ @parent = parent
+ @parent.children << self
+ end
+
+ if exclusive != nil
+ @exclusive = exclusive
+ if @parent && exclusive
+ @parent.children.to_a.each do |child|
+ next if child == self
+ @parent.children.delete(child)
+ child.parent = self
+ @children << child
+ end
end
end
end