diff options
author | Kazuki Yamaguchi <k@rhe.jp> | 2015-10-25 18:42:29 +0900 |
---|---|---|
committer | Kazuki Yamaguchi <k@rhe.jp> | 2015-10-25 18:42:29 +0900 |
commit | 302eb02fd9b97361b44c66c14827bdd82b46bc71 (patch) | |
tree | 814b53cb98bd2e5019752ace816c34c81d5a1390 | |
parent | 4d5d63bc80e13b0449799f721df768bff2088c44 (diff) | |
download | plum-302eb02fd9b97361b44c66c14827bdd82b46bc71.tar.gz |
improve performance
-rw-r--r-- | lib/plum/binary_string.rb | 2 | ||||
-rw-r--r-- | lib/plum/connection.rb | 2 | ||||
-rw-r--r-- | lib/plum/connection_utils.rb | 2 | ||||
-rw-r--r-- | lib/plum/event_emitter.rb | 6 | ||||
-rw-r--r-- | lib/plum/flow_control.rb | 25 | ||||
-rw-r--r-- | lib/plum/frame.rb | 17 | ||||
-rw-r--r-- | lib/plum/hpack/constants.rb | 92 | ||||
-rw-r--r-- | lib/plum/hpack/decoder.rb | 10 | ||||
-rw-r--r-- | lib/plum/hpack/encoder.rb | 2 | ||||
-rw-r--r-- | lib/plum/stream.rb | 38 |
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 |