Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

maxBytesPerRead channel configuration #3885

Closed
wants to merge 1 commit into from

Conversation

Scottmitch
Copy link
Member

Motiviation:
The current read loops don't fascilitate reading a maximum amount of bytes. This capability is useful to have more fine grain control over how much data is injested.

Modifications:

  • Add a setMaxBytesPerRead(int) and getMaxBytesPerRead() to ChannelConfig
  • Add a setMaxBytesPerIndividualRead(int) and getMaxBytesPerIndividualRead to ChannelConfig
  • Add methods to RecvByteBufAllocator so that a pluggable scheme can be used to control the behavior of the read loop.
  • Modify read loop for all transport types to respect the new RecvByteBufAllocator API

Result:
The ability to control how many bytes are read for each read operation/loop, and a more extensible read loop.

@Scottmitch Scottmitch self-assigned this Jun 12, 2015
@Scottmitch Scottmitch modified the milestones: 4.1.0.Final, 4.1.0.Beta6 Jun 12, 2015
@Scottmitch
Copy link
Member Author

@trustin - Would you mind reviewing this one?

@Scottmitch Scottmitch force-pushed the read_max_bytes branch 5 times, most recently from 1bd0235 to e818942 Compare June 12, 2015 23:13
} else if (option == MAX_BYTES_PER_READ_PAIR) {
@SuppressWarnings("unchecked")
Entry<Integer, Integer> pair = (Entry<Integer, Integer>) value;
setMaxBytesPerReadPair(pair.getKey(), pair.getValue());
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think something similar can be done to resolve #3806.

* A DNS client that queries a server and checks if query information and
* responses are valid to ensure codec is correct.
*/
package io.netty.handler.codec.dns;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

???

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe doesn't belong in this PR, but this is a duplicate of the package-info.java in the main directory tree. Was (and has been) causing an issue in eclipse IDE for quite some time now...resolved to make "real" errors I introduced during interface updates easier to see.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, nevermind, then.

@trustin
Copy link
Member

trustin commented Jun 15, 2015

@Scottmitch Sorry for a delay. Will review some time this week.

@Scottmitch
Copy link
Member Author

@netkins build

@Scottmitch
Copy link
Member Author

@trustin - Bump.

@trustin
Copy link
Member

trustin commented Jun 30, 2015

Do the new configuration properties work only when the RecvByteBufAllocator is aware of them? If so, why don't we move them to the RecvByteBufAllocator implementation?

@Scottmitch Scottmitch force-pushed the read_max_bytes branch 2 times, most recently from a22a712 to c184d89 Compare June 30, 2015 23:27
@Scottmitch
Copy link
Member Author

Yes. Currently MaxBytesRecvByteBufAllocator is the only consumer of the new properties. The RecvByteBufAllocator implementations have also encapsulated the responsibility of the existing getMaxMessagesPerRead(). I think if we move the new parameters it may make sense to also move getMaxMessagesPerRead() into the respective implementation that uses it (this change is only for 4.1 and 5.0). WDYT?

@Scottmitch
Copy link
Member Author

@trustin - Another thing to consider is moving these configuration options from ChannelConfig to an implementation of RecvByteBufAllocator may make it a bit more cumbersome to change on the fly. For example this may require conditionals based upon the run time type of the RecvByteBufAllocator. For example:

RecvByteBufAllocator recvAlloc = channel.config().getRecvByteBufAllocator();
if (recvAlloc instanceof MaxBytesRecvByteBufAllocator) {
  MaxBytesRecvByteBufAllocator maxRecvAlloc = (MaxBytesRecvByteBufAllocator) recvAlloc;
  maxRecvAlloc.setMaxMessagesPerRead(...);
  maxRecvAlloc.setMaxBytesPerIndividualRead(...);
} else if (recvAlloc instanceof ...) {
}

At least you can be sure what your are setting will actually be respected though...

@trustin
Copy link
Member

trustin commented Jul 1, 2015

I think if we move the new parameters it may make sense to also move getMaxMessagesPerRead() into the respective implementation that uses it (this change is only for 4.1 and 5.0). WDYT?

Sounds good to me!

Another thing to consider is moving these configuration options from ChannelConfig to an implementation of RecvByteBufAllocator may make it a bit more cumbersome to change on the fly.

Yeah, how about using the type parameter for the return type for loose typing to lessen the burden?

interface ChannelConfig {
    <T extends RecvByteBufAllocator> T getRecvByteBufAllocator();
}

MaxBytesRecvByteBufAllocator alloc = ch.config().getRecvByteBufAllocator();
...

This won't work when a user is not sure about the type of the current RecvByteBufAllocator, though...

@Scottmitch
Copy link
Member Author

@trustin - Thanks for the feedback. I will move forward with these updates and ping you when ready.

@Scottmitch Scottmitch force-pushed the read_max_bytes branch 2 times, most recently from 6b8da06 to ebcdd88 Compare July 1, 2015 18:55
@@ -184,8 +185,8 @@ protected int doReadMessages(List<Object> msgs) throws Exception {

Set<SelectionKey> reableKeys = readSelector.selectedKeys();
try {
for (SelectionKey ignored : reableKeys) {
RecvByteBufAllocator.Handle allocHandle = unsafe().recvBufAllocHandle();
for (@SuppressWarnings("unused") SelectionKey ignored : reableKeys) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure why this loop is necessary...see #3884

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure, either. Could you explain, @jestan ?

@Scottmitch
Copy link
Member Author

@trustin @normanmaurer - PTAL.

@trustin
Copy link
Member

trustin commented Jul 7, 2015

@Scottmitch LGTM. @normanmaurer, any comments?

@@ -58,11 +58,6 @@

return true;
}
@Override
public EpollDomainSocketChannelConfig setMaxMessagesPerRead(int maxMessagesPerRead) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm right that we only want this for 4.1 and master ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm still not 100 % convinced that we can do this change in 4.1 in terms of API breakage. @trustin WDYT ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@normanmaurer Yeah, we can't just remove it. How about deprecating it and delegate to Max*Allocator if the current recv allocator is of compatible type, or throw an exception if it's incompatible?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@normanmaurer
Copy link
Member

@Scottmitch a few more comments and questions. Good work!

@Scottmitch
Copy link
Member Author

@trustin - I would like to merge this but there are just a few followup discussion items above. Would you mind weighing in?

@Scottmitch
Copy link
Member Author

@trustin @normanmaurer - PTAL.

if (metadata == null) {
throw new NullPointerException("metadata");
}
MaxMessagesRecvByteBufAllocator maxMsgAllocator = (MaxMessagesRecvByteBufAllocator) allocator;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@trustin - This is how I am preserving the 16 max messages for ServerSockets/NioByteStream and 1 max message otherwise. WDYT?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thank you for your patience.

@Scottmitch
Copy link
Member Author

@trustin - I guess now that this doesn't break any APIs we could also consider putting this in 4.0. It would be nice to be consistent between 4.0 and 4.1...WDYT?

Nvm...forgot about changes to RecvByteBufAllocator.Handle

Motiviation:
The current read loops don't fascilitate reading a maximum amount of bytes. This capability is useful to have more fine grain control over how much data is injested.

Modifications:
- Add a setMaxBytesPerRead(int) and getMaxBytesPerRead() to ChannelConfig
- Add a setMaxBytesPerIndividualRead(int) and getMaxBytesPerIndividualRead to ChannelConfig
- Add methods to RecvByteBufAllocator so that a pluggable scheme can be used to control the behavior of the read loop.
- Modify read loop for all transport types to respect the new RecvByteBufAllocator API

Result:
The ability to control how many bytes are read for each read operation/loop, and a more extensible read loop.
@Scottmitch
Copy link
Member Author

Ran some quick perf tests on the before and after for this PR just to make sure there was no regression, and things look good (using NIO):

before

  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    22.07ms   33.58ms   1.11s    85.72%
    Req/Sec   132.23k    33.88k  241.31k    66.05%
  251377804 requests in 2.00m, 33.24GB read
Requests/sec: 2093223.99
Transfer/sec:    283.47MB

this PR

  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    21.36ms   34.33ms   1.28s    85.67%
    Req/Sec   136.39k    29.18k  231.36k    67.75%
  259304381 requests in 2.00m, 34.29GB read
Requests/sec: 2159239.24
Transfer/sec:    292.41MB

@Scottmitch
Copy link
Member Author

Cherry-picked 4.1 (cf171ff) master (a48e5c7)

@Scottmitch Scottmitch closed this Aug 6, 2015
@Scottmitch Scottmitch deleted the read_max_bytes branch August 6, 2015 07:00
@trustin
Copy link
Member

trustin commented Aug 6, 2015

👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants