Removing unnecessary sort in remote flow controller.

Motivation:

The DefaultHttp2RemoteFlowController's priority algorithm doesn't really need to sort the children by weight since it already fairly distributes data based on weight.

Modifications:

Removing the sorting in the priority algorithm and updating one test to allow a small bit of variability in the results.

Result:

Slight improvement on the performance of the priority algorithm.
This commit is contained in:
nmittler 2015-03-30 09:41:28 -07:00
parent a2428c7e47
commit cb63e34bda
2 changed files with 19 additions and 23 deletions

View File

@ -26,26 +26,13 @@ import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http2.Http2Stream.State; import io.netty.handler.codec.http2.Http2Stream.State;
import java.util.ArrayDeque; import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Comparator;
import java.util.Deque; import java.util.Deque;
/** /**
* Basic implementation of {@link Http2RemoteFlowController}. * Basic implementation of {@link Http2RemoteFlowController}.
*/ */
public class DefaultHttp2RemoteFlowController implements Http2RemoteFlowController { public class DefaultHttp2RemoteFlowController implements Http2RemoteFlowController {
/**
* A {@link Comparator} that sorts streams in ascending order the amount of streamable data.
*/
private static final Comparator<Http2Stream> WEIGHT_ORDER = new Comparator<Http2Stream>() {
@Override
public int compare(Http2Stream o1, Http2Stream o2) {
return o2.weight() - o1.weight();
}
};
private final Http2Connection connection; private final Http2Connection connection;
private int initialWindowSize = DEFAULT_WINDOW_SIZE; private int initialWindowSize = DEFAULT_WINDOW_SIZE;
private ChannelHandlerContext ctx; private ChannelHandlerContext ctx;
@ -283,7 +270,6 @@ public class DefaultHttp2RemoteFlowController implements Http2RemoteFlowControll
// This is the priority algorithm which will divide the available bytes based // This is the priority algorithm which will divide the available bytes based
// upon stream weight relative to its peers // upon stream weight relative to its peers
Http2Stream[] children = parent.children().toArray(new Http2Stream[parent.numChildren()]); Http2Stream[] children = parent.children().toArray(new Http2Stream[parent.numChildren()]);
Arrays.sort(children, WEIGHT_ORDER);
int totalWeight = parent.totalChildWeights(); int totalWeight = parent.totalChildWeights();
for (int tail = children.length; tail > 0;) { for (int tail = children.length; tail > 0;) {
int head = 0; int head = 0;

View File

@ -659,16 +659,18 @@ public class DefaultHttp2RemoteFlowControllerTest {
incrementWindowSize(CONNECTION_STREAM_ID, 1000); incrementWindowSize(CONNECTION_STREAM_ID, 1000);
// All writes sum == 1000 // All writes sum == 1000
dataA.assertPartiallyWritten(109); assertEquals(1000, dataA.written() + dataB.written() + dataC.written() + dataD.written());
dataB.assertPartiallyWritten(445); int allowedError = 10;
dataC.assertPartiallyWritten(223); dataA.assertPartiallyWritten(109, allowedError);
dataD.assertPartiallyWritten(223); dataB.assertPartiallyWritten(445, allowedError);
dataC.assertPartiallyWritten(223, allowedError);
dataD.assertPartiallyWritten(223, allowedError);
assertEquals(0, window(CONNECTION_STREAM_ID)); assertEquals(0, window(CONNECTION_STREAM_ID));
assertEquals(DEFAULT_WINDOW_SIZE - 109, window(STREAM_A)); assertEquals(DEFAULT_WINDOW_SIZE - dataA.written(), window(STREAM_A));
assertEquals(DEFAULT_WINDOW_SIZE - 445, window(STREAM_B)); assertEquals(DEFAULT_WINDOW_SIZE - dataB.written(), window(STREAM_B));
assertEquals(DEFAULT_WINDOW_SIZE - 223, window(STREAM_C)); assertEquals(DEFAULT_WINDOW_SIZE - dataC.written(), window(STREAM_C));
assertEquals(DEFAULT_WINDOW_SIZE - 223, window(STREAM_D)); assertEquals(DEFAULT_WINDOW_SIZE - dataD.written(), window(STREAM_D));
} }
/** /**
@ -1215,13 +1217,21 @@ public class DefaultHttp2RemoteFlowControllerTest {
return true; return true;
} }
public int written() {
return originalSize - currentSize;
}
public void assertNotWritten() { public void assertNotWritten() {
assertFalse(writeCalled); assertFalse(writeCalled);
} }
public void assertPartiallyWritten(int expectedWritten) { public void assertPartiallyWritten(int expectedWritten) {
assertPartiallyWritten(expectedWritten, 0);
}
public void assertPartiallyWritten(int expectedWritten, int delta) {
assertTrue(writeCalled); assertTrue(writeCalled);
assertEquals(expectedWritten, originalSize - currentSize); assertEquals(expectedWritten, written(), delta);
} }
public void assertFullyWritten() { public void assertFullyWritten() {