Commit Graph

6484 Commits

Author SHA1 Message Date
Norman Maurer
aa1e537de4 [#3373] Rename class to match naming scheme
Motivation:

The ReplayingDecoderBuffer does not match the naming scheme we use for ByteBuf types.

Modifications:

Rename to ReplayingDecoderByteBuf to match naming scheme

Result:

Consistent naming
2015-04-12 13:32:41 +02:00
Norman Maurer
d8e5d421e1 Revert "Dereference when calling PooledByteBuf.deallocate()"
This reverts commit 7094c7b797.
2015-04-11 06:44:32 +02:00
Norman Maurer
7094c7b797 Dereference when calling PooledByteBuf.deallocate()
Motivation:

We missed to dereference the chunk and tmpNioBuf when calling deallocate(). This means the GC can not collect these as we still hold a reference while have the PooledByteBuf in the recycler stack.

Modifications:

Dereference chunk and tmpNioBuf.

Result:

GC can collect things.
2015-04-10 21:47:14 +02:00
Norman Maurer
1e8a2e69db [#3592] Flush when writing HttpChunkedInput
Motivation:

We missed to flush the channel when using HttpChunkedInput (this is done when using SSL). This will result in a stale.

Modifications:

Replace ctx.write(...) with ctx.writeAndFlush(...)

Result:

Correctly working example.
2015-04-10 21:19:25 +02:00
Norman Maurer
3e42292d8b Change PoolThreadCache to use LIFO for better cache performance
Motiviation:

At the moment we use FIFO for the PoolThreadCache which is sub-optimal as this may reduce the changes to have the cached memory actual still in the cpu-cache.

Modification:

- Change to use LIFO as this increase the chance to be able to serve buffers from the cpu-cache

Results:

Faster allocation out of the ThreadLocal cache.

Before the commit:
[xxx wrk]$ ./wrk -H 'Connection: keep-alive' -d 120 -c 256 -t 16 -s scripts/pipeline-many.lua  http://xxx:8080/plaintext
Running 2m test @ http://xxx:8080/plaintext
  16 threads and 256 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    14.69ms   10.06ms 131.43ms   80.10%
    Req/Sec   283.89k    40.37k  433.69k    66.81%
  533859742 requests in 2.00m, 72.09GB read
Requests/sec: 4449510.51
Transfer/sec:    615.29MB

After the commit:
[xxx wrk]$ ./wrk -H 'Connection: keep-alive' -d 120 -c 256 -t 16 -s scripts/pipeline-many.lua  http://xxx:8080/plaintext
Running 2m test @ http://xxx:8080/plaintext
  16 threads and 256 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    16.38ms   26.32ms 734.06ms   97.38%
    Req/Sec   283.86k    39.31k  361.69k    83.38%
  540836511 requests in 2.00m, 73.04GB read
Requests/sec: 4508150.18
Transfer/sec:    623.40MB
2015-04-10 20:57:54 +02:00
nmittler
a87c86dc0d Change Http2Settings to use char keys.
Motivation:

Now that we have a CharObjectHashMap, we should change Http2Settings to use it.

Modifications:

Changed Http2Settings to extend CharObjectHashMap rather than IntObjectHashMap.

Result:

Http2Settings uses less memory to store keys.
2015-04-10 11:50:24 -07:00
Norman Maurer
aebbb862ac Add support for ALPN when using openssl + NPN client mode and support for CipherSuiteFilter
Motivation:

To support HTTP2 we need APLN support. This was not provided before when using OpenSslEngine, so SSLEngine (JDK one) was the only bet.
Beside this CipherSuiteFilter was not supported

Modifications:

- Upgrade netty-tcnative and make use of new features to support ALPN and NPN in server and client mode.
- Guard against segfaults after the ssl pointer is freed
- support correctly different failure behaviours
- add support for CipherSuiteFilter

Result:

Be able to use OpenSslEngine for ALPN / NPN for server and client.
2015-04-10 18:52:34 +02:00
nmittler
e3374e5b1d Removing direct access to HTTP/2 child streams.
Motivation:

We've removed access to the activeStreams collection, we should do the same for the children of a stream to provide a consistent interface.

Modifications:

Moved Http2StreamVisitor to a top-level interface. Removed unnecessary child operations from the Http2Stream interface so that we no longer require a map structure.

Result:

Cleaner and more consistent interface for iterating over child streams.
2015-04-10 08:52:26 -07:00
nmittler
3354296c9f Auto-generating primitive collections for int and char keys.
Motivation:

Currently we have IntObjectMap/HashMap, but it will be useful to support other primitive-based maps.

Modifications:

Moved the code int the current maps to template files and run Groovy code from  common/pom.xml to apply the templates.

Result:

Autogeneration of int and char-based hash maps.
2015-04-10 07:57:30 -07:00
Idel Pivnitskiy
c9adb41636 Refactor tests for compression codecs
Motivation:

Too many duplicated code of tests for different compression codecs.

Modifications:

- Added abstract classes AbstractCompressionTest, AbstractDecoderTest and AbstractEncoderTest which contains common variables and tests for any compression codec.
- Removed common tests which are implemented in AbstractDecoderTest and AbstractEncoderTest from current tests for compression codecs.
- Implemented abstract methods of AbstractDecoderTest and AbstractEncoderTest in current tests for compression codecs.
- Added additional checks for current tests.
- Renamed abstract class IntegrationTest to AbstractIntegrationTest.
- Used Theories to run tests with head and direct buffers.
- Removed code duplicates.

Result:

Removed duplicated code of tests for compression codecs and simplified an addition of tests for new compression codecs.
2015-04-10 15:50:41 +02:00
JongYoon Lim
6496d2dbc7 Motivation: If there are no readable bytes, it's unnecessary to go through javaChannel().write().
Modification:
If the readableBytes() is zero, then just return.

Result:
The logic can be easy to understand and a little faster than before.
2015-04-08 09:36:24 +02:00
Scott Mitchell
83ce8a9187 HTTP/2 Prevent modification of activeStreams while iterating
Motivation:
The Http2Connection interface exposes an activeStreams() method which allows direct iteration over the underlying collection. There are a few places that make copies of this collection to avoid modification while iterating, and a few places that do not make copies. The copy operation can be expensive on hot code paths and also we are not consistently iterating over the activeStreams collection.

Modifications:
- The Http2Connection interface should reduce the exposure of the underlying collection and just expose what is necessary for the interface to function.  This is just a means to iterate over the collection.
- The DefaultHttp2Connection should use this new interface and protect it's internal state while iteration is occurring.

Result:
Reduction in surface area of the Http2Connection interface.  Consistent iteration of the set of active streams.  Concurrent modification exceptions are handled in 1 encapsulated spot.
2015-04-07 20:55:48 -07:00
Jakob Buchgraber
d5d932a739 Fix GOAWAY logic in Http2Encoder and Http2Decoder.
Motivation:

1) The current implementation doesn't allow for HEADERS, DATA, PING, PRIORITY and SETTINGS
   frames to be sent after GOAWAY.

2) When receiving or sending a GOAWAY frame, all streams with ids greater than the lastStreamId
   of the GOAWAY frame should be closed. That's not happening.

Modifications:

1) Allow sending of HEADERS and DATA frames after GOAWAY for streams with ids < lastStreamId.
2) Always allow sending PING, PRIORITY AND SETTINGS frames.
3) Allow sending multiple GOAWAY frames with decreasing lastStreamIds.
4) After receiving or sending a GOAWAY frame, close all streams with ids > lastStreamId.

Result:

The GOAWAY handling is more correct.
2015-04-07 20:32:28 -07:00
Scott Mitchell
3ae343b768 HTTP/2 DefaultHttp2Connection recursive call fix
Motivation:
There are methods to manipulate the prioritzable count for streams which have the '0' postfix which are designed to be used during recursion.  However these methods are calling out to an external method without the '0' during the recursive process.  This is doing uneccessary conditional checks during recursion.

Modifications:
Change the decrementPrioritizableForTree to decrementPrioritizableForTree0 while in recursive method.
Change the incrementPrioritizableForTree to incrementPrioritizableForTree0 while in recursive method.

Result:
Less overhead during recursive calls.
2015-04-06 17:12:41 -07:00
Scott Mitchell
86edc88448 HTTP/2 LifecycleManager and Http2ConnectionHandler interface clarifications
Motiviation:
The interface provided by Http2LifecycleManager is not clear as to how the writeXXX methods should behave.  The implementation of this interface from the Http2ConnectionHandler's perspecitve is unclear what writeXXX means in this context.

Modifications:
- Method names in Http2LifecycleManager and Http2ConnectionHandler should be renamed and comments should clarify the interfaces.

Results:
Http2LifecycleManager is more clear and Http2ConnectionHandler's implementation makes sense w.r.t to return values.
2015-04-06 14:34:20 -07:00
Frederic Bregier
190cbf55e4 Fix incorrect null value check in TrafficCounter
In TrafficCounter, a recent change makes the contract of the API (the
constructor) wrong and lead to issue with GlobalChannelTrafficCounter
where executor must be null.

Motivation:
TrafficCounter executor argument in constructor might be null, as
explained in the API, for some particular cases where no executor are
needed (relevant tasks being taken by the caller as in
GlobalChannelTrafficCounter).
A null pointer exception is raised while it should not since it is
legal.

Modifications:
Remove the 2 null checking for this particular attribute.
Note that when null, the attribute is not reached nor used (a null
checking condition later on is applied).

Result:
No more null exception raized while it should not.

This shall be made also to 4.0, 4.1 (present) and master. 3.10 is not
concerned.
2015-04-06 18:27:56 +02:00
Scott Mitchell
609e065fcf HTTP/2 Headers Code Using String instead of AsciiString
Motivation:
The HTTP/2 headers code should be using binary string (currently AsciiString) objects instead of String objects. The DefaultHttp2HeadersEncoder was still using String for sensitiveHeaders.

Modifications:
- Remove the usage of String from DefaultHttp2HeadersEncoder.
- Introduce an interface to determine if a header name/value is sensitive or not to 1. prevent necessarily creating/copying sets. 2. Allow the name/value to be considered when checking if sensitive.

Result:
No more String in DefaultHttp2HeadersEncoder and less required set creation/operations.
2015-04-03 15:55:44 -07:00
Scott Mitchell
9517edd498 HTTP/2 RST_STREAM in IDLE
Motivation:
The spec requires that a RST_STREAM received on an IDLE stream results in a connection error. This is not happening.

Modifications:
Check for this condition when a RST_STREAM is received in DefaultHttp2ConnectionDecoder.

Result:
More spec compliant.  Fixes https://github.com/netty/netty/issues/3573.
2015-04-03 15:53:32 -07:00
Scott Mitchell
e5d01c4caf HTTP/2 HEADERS stream dependency fix
Motivation:
The DefaultHttp2ConnectionDecoder has the setPriority call after the Http2FrameListener is notified of the change. The setPriority call has additional verification logic and may even create the dependency stream and so it must be before the Http2FrameListener is notified.

Modifications:
The DefaultHttp2ConnectionDecoder should treat the setPriority call in the same for the HEADERS and PRIORITY frame (call it before notifying the listener).

Result:
Http2FrameListener should see correct state when a HEADERS frame has a stream dependency that has not yet been created yet.  Fixes https://github.com/netty/netty/issues/3572.
2015-04-03 15:50:30 -07:00
Jakob Buchgraber
e40c27d9ed Avoid object allocations for HTTP2 child streams.
Motivation:

We are allocating a hash map for every HTTP2 Stream to store it's children.
Most streams are leafs in the priority tree and don't have children.

Modification:

 - Only allocate children when we actually use them.
 - Make EmptyIntObjectMap not throw a UnsupportedOperationException on remove, but return null instead (as is stated in it's javadoc).

Result:

Fewer unnecessary allocations.
2015-04-03 11:57:31 -07:00
Scott Mitchell
330bc39d91 Backporting PrimitiveCollections class
Motivation:
PrimitiveCollections is not in the 4.1 branch.  It is needed by HTTP/2.

Modifications:
Backport this class.

Result:
PrimitiveCollections is in 4.1.
2015-04-03 11:57:09 -07:00
Jakob Buchgraber
35b9aa9302 Replace LinkedHashSet by ArrayList to avoid iterators.
Motivation:

In a simple load test that creates and closes several 10k streams per second
I have seen Iterator objects using roughly 1.6% of the total committed heap.

Modifications:

Use an ArrayList instead of a LinkedHashSet to store the connection listeners.
That way we can iterate over the list without creating an iterator every time.

Result:

Zero Iterator allocations due to notifying connection listeners.
2015-04-03 20:13:53 +02:00
nmittler
ef729e7021 Allow non-standard HTTP/2 settings
Motivation:

The Http2Settings class currently disallows setting non-standard settings, which violates the spec.

Modifications:

Updated Http2Settings to permit arbitrary settings. Also adjusting the default initial capacity to allow setting all of the standard settings without reallocation.

Result:

Fixes #3560
2015-04-02 11:10:47 -07:00
Trustin Lee
2e509f7bb7 Fix unbounded expansion of cumulative buffer in SslHandler
Related: #3567

Motivation:

SslHandler.channelReadComplete() forgets to call
super.channelReadComplete(), which discards read bytes from the
cumulative buffer.  As a result, the cumulative buffer can expand its
capacity unboundedly.

Modifications:

Call super.channelReadComplete() instead of calling
ctx.fireChannelReadComplete()

Result:

Fixes #3567
2015-04-02 14:54:29 +09:00
Scott Mitchell
7f2ddb2162 HTTP/2 Closed Streams Conditional Priority Tree Removal
Motivation:
The HTTP/2 specification allows for closed (and streams in any state) to exist in the priority tree. The current code removes streams from the priority tree as soon as they are closed (subject to the removal policy). This may lead to undesired distribution of resources from the peer's perspective.

Modifications:
- We should only remove streams from the priority tree when they have no descendant streams in a viable state.
- We should track when tree edges change or nodes are removed if inviable nodes can then be removed.

Result:
Priority tree doesn't remove closed streams until descendant are all closed, or there are no descendants.
2015-03-31 16:24:25 -07:00
nmittler
ba9f214303 Removing unnecessary use of Math.ceil in HTTP/2 priority algorithm.
Motivation:

We're currently using Math.ceil which isn't necessary. We should exchange for a lighter weight operation.

Modifications:

Changing the logic to just ensure that we allocate at least one byte to the child rather than always performing a ceil.

Result:

Slight performance improvement in the priority algorithm.
2015-03-31 11:03:16 -07:00
nmittler
9737cc6cc9 Include error code and message in GOAWAY events.
Motivation:

The Connection.Listener GOAWAY event handler currently provides no additional information, requiring applications to hack in other ways to get at the error code and debug message.

Modifications:

Modified the Connection.Listener interface to pass on the error code and message that triggered the GOAWAY.

Result:

Application can now use Connection.Listener for all GOAWAY processing.
2015-03-31 09:18:26 -07:00
Trustin Lee
44eeb5f6b4 Fix intermittent test failure in LoggingHandlerTest
Motivation:

LoggingHandlerTest sometimes failure due to unexpected log messages
logged due to the automatic reclaimation of thread-local objects.

  Expectation failure on verify:
    Appender.doAppend([DEBUG] Freed 3 thread-local buffer(s) from thread: nioEventLoopGroup-23-0): expected: 1, actual: 0
    Appender.doAppend([DEBUG] Freed 9 thread-local buffer(s) from thread: nioEventLoopGroup-23-1): expected: 1, actual: 0
    Appender.doAppend([DEBUG] Freed 2 thread-local buffer(s) from thread: nioEventLoopGroup-23-2): expected: 1, actual: 0
    Appender.doAppend([DEBUG] Freed 4 thread-local buffer(s) from thread: nioEventLoopGroup-26-0): expected: 1, actual: 0
    Appender.doAppend(matchesLog(expected: ".+CLOSE$", got: "[id: 0xembedded, embedded => embedded] CLOSE")): expected: 1, actual: 0

Modifications:

Add the mock appender to the related logger only

Result:

No more intermittent test failures
2015-03-31 15:08:52 +09:00
Trustin Lee
f4e527c64d Don't trigger IOException at ChunkedStream.isEndOfInput()
Related: #3368

Motivation:

ChunkedWriteHandler checks if the return value of
ChunkedInput.isEndOfInput() after calling ChunkedInput.close().

This makes ChunkedStream.isEndOfInput() trigger an IOException, which is
originally triggered by PushBackInputStream.read().

By contract, ChunkedInput.isEndOfInput() should not raise an IOException
even when the underlying stream is closed.

Modifications:

Add a boolean flag that keeps track of whether the underlying stream has
been closed or not, so that ChunkedStream.isEndOfInput() does not
propagate the IOException from PushBackInputStream.

Result:

Fixes #3368
2015-03-31 11:38:25 +09:00
nmittler
6fbca14f8a Cleaning up the initialization of Http2ConnectionHandler
Motivation:

It currently takes a builder for the encoder and decoder, which makes it difficult to decorate them.

Modifications:

Removed the builders from the interfaces entirely. Left the builder for the decoder impl but removed it from the encoder since it's constructor only takes 2 parameters. Also added decorator base classes for the encoder and decoder and made the CompressorHttp2ConnectionEncoder extend the decorator.

Result:

Fixes #3530
2015-03-30 11:23:02 -07:00
nmittler
cb63e34bda 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.
2015-03-30 09:55:03 -07:00
Norman Maurer
a2428c7e47 Add supported for X509ExtendedTrustManager when using OpenSslEngine
Motivation:

For some use cases X509ExtendedTrustManager is needed as it allows to also access the SslEngine during validation.

Modifications:

Add support for X509ExtendedTrustManager on java >= 7

Result:

It's now possible to use X509ExtendedTrustManager with OpenSslEngine
2015-03-30 09:05:18 +02:00
Trustin Lee
bdf0bddc85 Enforce a release is made with JDK 1.7 (and not w/ 1.8+)
Motivations:

JDK 1.8 adds default methods to collections classes that reference
classes that don't exist in JDK 7. That's binary compatible,
but not source compatible.

Modifications:

Enforce JDK version to be 1.7.* when releasing

Result:

Fixes #3548
2015-03-29 17:07:53 +09:00
Scott Mitchell
ab74dccd23 Http/2 Priority on CLOSED stream
Motivation:
The encoder/decoder currently do not handle streams which have previously existed but no longer exist because they were closed. The specification requires supporting this.

Modifications:
- encoder/decoder should tolerate the frame or the dependent frame not existing in the streams map due to the fact that it may have previously existed.

Result:
encoder/decoder are more compliant with the specification.
2015-03-28 19:10:43 -07:00
Scott Mitchell
0d3a6e0511 HTTP/2 Decoder reduce preface conditional checks
Motivation:
The DefaultHttp2ConnectionDecoder class is calling verifyPrefaceReceived() for almost every frame event at all times.
The Http2ConnectionHandler class is calling readClientPrefaceString() on every decode event.

Modifications:
- DefaultHttp2ConnectionDecoder should not have to continuously call verifyPrefaceReceived() because it transitions boolean state 1 time for each connection.
- Http2ConnectionHandler should not have to continuously call readClientPrefaceString() because it transitions boolean state 1 time for each connection.

Result:
- Less conditional checks for the mainstream usage of the connection.
2015-03-28 18:52:35 -07:00
Scott Mitchell
2bf592c50f Backport of HTTP/2 Microbenchmark fail.
Motivation:
The backport of a6c729bdf8 failed.

Modifications:
- Make sure the interfaces are correctly implemented when backporting.

Result:
Microbenchmark compiles and runs on 4.1 branch.
2015-03-28 18:41:09 -07:00
nmittler
bb059c070f Decoupling allocation from writing in HTTP/2 outbound flow control
Motivation:

The current DefaultHttp2RemoteFlowController's writePendingBytes currently operates in 2 passes. The first allocates bytes and optionally writes some frames. The second pass just loops across all active streams and writes all remaining bytes.

If streams can be removed/added as a side effect of writing (EOS or error) then we need to take more care when the write actually occurs. Moving all of the writes to the second loop (across active streams) is simpler since we can just make a copy of the list and not worry about any restructuring of the priority tree that may result.

Modifications:

Modified DefaultHttp2RemoteFlowController.writePendingBytes to only allocate bytes on the first pass and then write any allocated bytes on the second pass.

Result:

Side effects resulting from writing should no longer impact the flow control algorithm.
2015-03-28 14:19:37 -07:00
scottmitch
2dda917f27 Http2DefaultFrameWriter microbenchmark
Motivation:
A microbenchmark will be useful to get a baseline for performance.

Modifications:
- Introduce a new microbenchmark which tests the Http2DefaultFrameWriter.
- Allow benchmarks to run without thread context switching between JMH and Netty.

Result:
Microbenchmark exists to test performance.
2015-03-27 13:10:57 -07:00
Scott Mitchell
23f881b382 Comment punctuation cleanup
Motivation:
Commit d857b16d76 introduced some comments that had no punctuation.

Modifications:
Add punctuation.

Result:
Comments have punctuation.
2015-03-26 13:01:37 -07:00
Scott Mitchell
d857b16d76 Http/2 RST_STREAM frame robustness
Motivation:
The Http2ConnectionHandler writeRstStream method allows RST_STREAM frames to be sent when we do not know about the stream and after a RST_STREAM frame has already been sent.  This may lead to sending frames when we should not according to the HTTP/2 spec. There is also the potential to notify the closeListener multiple times if the closeStream method is called multiple times.

Modifications:
- Prevent RST_STREAM from being sent if we don't know about the stream, or if we already sent the RST_STREAM.
- Prevent the closeListener from being notified multiple times.

Result:
More robust writeRstStream logic in boundary conditions.
2015-03-26 11:47:00 -07:00
David Dossot
18abc6d893 Fix example in CookieDecoder Javadoc
- CookieDecoder.decode() is a static method.
2015-03-26 11:48:51 +09:00
Scott Mitchell
6dfa1f2d92 Http2 draft 17
Motivation:
There was a new draft for HTTP/2.  We should support the new draft.

Modifications:
- Review the HTTP/2 draft 17 specification, and update code to reflect changes.

Result:
Support for HTTP/2 draft 17.
2015-03-25 09:02:15 -07:00
Scott Mitchell
b0e7992c16 Jetty ALNPN and NPN updates plus backport
Motivation:
There are new versions of the ALPN and NPN dependencies.  There was also some backport misses in the pom file related to ALPN/NPN.

Modifications:
- Add new versions for ALPN/NPN dependencies.
- Backport missed pieces from pom.xml.

Result:
Updated version of ALPN/NPN versions.
2015-03-25 08:55:52 -07:00
Scott Mitchell
a24627aa36 HTTP/2 codec missing from all/pom.xml
Motivation:
The codec-http2 module was excluded from the all/pom.xml.

Modifications:
Include the codec-http2 dependency in the all/pom.xml.

Results:
Projects including the all dependency get codec-http2.
2015-03-23 16:29:28 -07:00
Scott Mitchell
d94eab76b6 HTTP/2 examples run script support
Motivation:
The example script has some changes that have not yet been backported.  These changes should be backported.

Modifications:
run-example.sh changes related to http/2 are backported

Result:
HTTP/2 examples can be run on the 4.1 branch.
2015-03-23 16:27:55 -07:00
Pierre DAL-PRA
2ebf07e622 Small typos fixes in Channel's Javadoc 2015-03-21 16:10:24 +01:00
Jakob Buchgraber
8e04d706de Have FlowState.cancel take a Throwable and code cleanup.
Motivation:

- In FlowState.write(...) we are currently swalloing an exception.
- In my previous commit I introduced a compiler warning by not making
  a local variabe final.

Modifications:

- Have FlowState.cancel() take a Throwable.
- Make the variable final.

Result:

No more swallowed exceptions and warnings.
2015-03-19 22:01:02 -07:00
Jakob Buchgraber
9bad408de5 HTTP2: Close encoder and decoder on channelInactive and initialize clientPrefaceString on handlerAdded.
Motivation:

- The encoder and decoder should be closed right after the handler releases its resources.
- The clientPrefaceString is allocated in the constructor but releases in handlerRemoved.
  If the handler is never added to the pipeline, the clientPrefaceString will never be
  released.

Modifications:

- Call encoder.close() and decoder.close() on channelInactive.
- Release the clientPrefaceString on handlerRemoved.

Result:

- The encoder and decoder get closed right after the handler's resources are freed.
- It's easier to verify that the clientPrefaceString will also get released.
2015-03-19 13:09:34 -07:00
JongYoonLim
3405aee2ab Returns after encoding each message not do check following instance types
Motivation:
Current AbstractMemcacheObjectEncoder does unnecessary message type checking if the message is MemcacheMessage type.

Modifications:
Returns after encoding MemcacheMessage message.

Result:
Small performance improvement for this encoder.
2015-03-19 20:43:59 +01:00
JongYoonLim
d5e67032b5 fix typo 2015-03-19 20:41:11 +01:00