Package io.netty.handler.codec.http2
Class WeightedFairQueueByteDistributor
java.lang.Object
io.netty.handler.codec.http2.WeightedFairQueueByteDistributor
- All Implemented Interfaces:
StreamByteDistributor
@UnstableApi
public final class WeightedFairQueueByteDistributor
extends Object
implements StreamByteDistributor
A
StreamByteDistributor
that is sensitive to stream priority and uses
Weighted Fair Queueing approach for distributing
bytes.
Inspiration for this distributor was taken from Linux's Completely Fair Scheduler to model the distribution of bytes to simulate an "ideal multi-tasking CPU", but in this case we are simulating an "ideal multi-tasking NIC".
Each write operation will use the allocationQuantum(int)
to know how many more bytes should be allocated
relative to the next stream which wants to write. This is to balance fairness while also considering goodput.
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionprivate static final class
Allows a correlation to be made between a stream and its old parent before a parent change occurs.private final class
The remote flow control state for a single stream.private static final class
A comparator forWeightedFairQueueByteDistributor.State
which has no associatedHttp2Stream
object.private static final class
Nested classes/interfaces inherited from interface io.netty.handler.codec.http2.StreamByteDistributor
StreamByteDistributor.StreamState, StreamByteDistributor.Writer
-
Field Summary
FieldsModifier and TypeFieldDescriptionprivate int
The minimum number of bytes that we will attempt to allocate to a stream.private final Http2Connection
private final WeightedFairQueueByteDistributor.State
private static final int
FireFox currently uses 5 streams to establish QoS classes.(package private) static final int
The initial size of the children map is chosen to be conservative on initial memory allocations under the assumption that most streams will have a small number of children.private final int
private final Http2Connection.PropertyKey
private final IntObjectMap
<WeightedFairQueueByteDistributor.State> If there is no Http2Stream object, but we still persist priority information then this is where the state will reside.private final PriorityQueue
<WeightedFairQueueByteDistributor.State> This queue will hold streams that are not active and provides the capability to retain priority for streams which have noHttp2Stream
object. -
Constructor Summary
ConstructorsConstructorDescriptionWeightedFairQueueByteDistributor
(Http2Connection connection) WeightedFairQueueByteDistributor
(Http2Connection connection, int maxStateOnlySize) -
Method Summary
Modifier and TypeMethodDescriptionvoid
allocationQuantum
(int allocationQuantum) Sets the amount of bytes that will be allocated to each stream.boolean
distribute
(int maxBytes, StreamByteDistributor.Writer writer) Distributes up tomaxBytes
to those streams containing streamable bytes and iterates across those streams to write the appropriate bytes.private int
distribute
(int maxBytes, StreamByteDistributor.Writer writer, WeightedFairQueueByteDistributor.State state) private int
distributeToChildren
(int maxBytes, StreamByteDistributor.Writer writer, WeightedFairQueueByteDistributor.State state) It is a pre-condition thatstate.poll()
returns a non-null
value.(package private) boolean
isChild
(int childId, int parentId, short weight) For testing only!(package private) void
Notify all listeners of the priority tree change events (in ascending order)(package private) int
numChildren
(int streamId) For testing only!state
(int streamId) state
(Http2Stream stream) void
updateDependencyTree
(int childStreamId, int parentStreamId, short weight, boolean exclusive) Explicitly update the dependency tree.void
Called when the streamable bytes for a stream has changed.
-
Field Details
-
INITIAL_CHILDREN_MAP_SIZE
static final int INITIAL_CHILDREN_MAP_SIZEThe initial size of the children map is chosen to be conservative on initial memory allocations under the assumption that most streams will have a small number of children. This choice may be sub-optimal if when children are present there are many children (i.e. a web page which has many dependencies to load). Visible only for testing! -
DEFAULT_MAX_STATE_ONLY_SIZE
private static final int DEFAULT_MAX_STATE_ONLY_SIZEFireFox currently uses 5 streams to establish QoS classes.- See Also:
-
stateKey
-
stateOnlyMap
If there is no Http2Stream object, but we still persist priority information then this is where the state will reside. -
stateOnlyRemovalQueue
This queue will hold streams that are not active and provides the capability to retain priority for streams which have noHttp2Stream
object. SeeWeightedFairQueueByteDistributor.StateOnlyComparator
for the priority comparator. -
connection
-
connectionState
-
allocationQuantum
private int allocationQuantumThe minimum number of bytes that we will attempt to allocate to a stream. This is to help improve goodput on a per-stream basis. -
maxStateOnlySize
private final int maxStateOnlySize
-
-
Constructor Details
-
WeightedFairQueueByteDistributor
-
WeightedFairQueueByteDistributor
-
-
Method Details
-
updateStreamableBytes
Description copied from interface:StreamByteDistributor
Called when the streamable bytes for a stream has changed. Until this method is called for the first time for a give stream, the stream is assumed to have no streamable bytes.- Specified by:
updateStreamableBytes
in interfaceStreamByteDistributor
-
updateDependencyTree
public void updateDependencyTree(int childStreamId, int parentStreamId, short weight, boolean exclusive) Description copied from interface:StreamByteDistributor
Explicitly update the dependency tree. This method is called independently of stream state changes.- Specified by:
updateDependencyTree
in interfaceStreamByteDistributor
- Parameters:
childStreamId
- The stream identifier associated with the child stream.parentStreamId
- The stream identifier associated with the parent stream. May be0
, to makechildStreamId
and immediate child of the connection.weight
- The weight which is used relative to other child streams forparentStreamId
. This value must be between 1 and 256 (inclusive).exclusive
- IfchildStreamId
should be the exclusive dependency ofparentStreamId
.
-
distribute
Description copied from interface:StreamByteDistributor
Distributes up tomaxBytes
to those streams containing streamable bytes and iterates across those streams to write the appropriate bytes. Criteria for traversing streams is undefined and it is up to the implementation to determine when to stop at a given stream.The streamable bytes are not automatically updated by calling this method. It is up to the caller to indicate the number of bytes streamable after the write by calling
StreamByteDistributor.updateStreamableBytes(StreamState)
.- Specified by:
distribute
in interfaceStreamByteDistributor
- Parameters:
maxBytes
- the maximum number of bytes to write.- Returns:
true
if there are still streamable bytes that have not yet been written, otherwisefalse
.- Throws:
Http2Exception
- If an internal exception occurs and internal connection state would otherwise be corrupted.
-
allocationQuantum
public void allocationQuantum(int allocationQuantum) Sets the amount of bytes that will be allocated to each stream. Defaults to 1KiB.- Parameters:
allocationQuantum
- the amount of bytes that will be allocated to each stream. Must be > 0.
-
distribute
private int distribute(int maxBytes, StreamByteDistributor.Writer writer, WeightedFairQueueByteDistributor.State state) throws Http2Exception - Throws:
Http2Exception
-
distributeToChildren
private int distributeToChildren(int maxBytes, StreamByteDistributor.Writer writer, WeightedFairQueueByteDistributor.State state) throws Http2Exception It is a pre-condition thatstate.poll()
returns a non-null
value. This is a result of the way the allocation algorithm is structured and can be explained in the following cases:For the recursive case
If a stream has no children (in the allocation tree) than that node must be active or it will not be in the allocation tree. If a node is active then it will not delegate to children and recursion ends.For the initial case
We check connectionState.activeCountForTree == 0 before any allocation is done. So if the connection stream has no active children we don't get into this method.- Throws:
Http2Exception
-
state
-
state
-
isChild
boolean isChild(int childId, int parentId, short weight) For testing only! -
numChildren
int numChildren(int streamId) For testing only! -
notifyParentChanged
Notify all listeners of the priority tree change events (in ascending order)- Parameters:
events
- The events (top down order) which have changed
-