Commit Graph

923 Commits

Author SHA1 Message Date
Norman Maurer
5a08dc0d9a
Add fastpath implementation for Unpooled.copiedBuffer(CharSequence, Charset) when UTF-8 or US-ASCII is used (#10206)
Motivation:

We can make use of our optimized implementations for UTF-8 and US-ASCII if the user request a copy of a sequence for these charsets

Modifications:

- Add fastpath implementation
- Add unit tests

Result:

Fixes https://github.com/netty/netty/issues/10205
2020-04-23 17:47:16 +02:00
root
9c5008b109 [maven-release-plugin] prepare for next development iteration 2020-04-22 09:57:54 +00:00
root
d0ec961cce [maven-release-plugin] prepare release netty-4.1.49.Final 2020-04-22 09:57:26 +00:00
Norman Maurer
232c669fa4
Guard against overflow when calling CompositeByteBuf.addComponent(...) (#10197)
Motivation:

We need to ensure we not overflow when adding buffers to a CompositeByteBuf

Modifications:

- Correctly validate overflow before adding to the internal storage
- Add testcase

Result:

Fixes https://github.com/netty/netty/issues/10194
2020-04-21 12:04:25 +02:00
Linas Medžiūnas
fb5e2cd3aa
Efficient BytBuf search algorithms (#9914) (#9955)
Motivation:

We have found out that ByteBufUtil.indexOf can be inefficient for substring search on
ByteBuf, both in terms of algorithm complexity (worst case O(needle.readableBytes *
haystack.readableBytes)), and in constant factor (esp. on Composite buffers).
With implementation of more performant search algorithms we have seen improvements on
the order of magnitude.

Modifications:

This change introduces three search algorithms:
1. Knuth Morris Pratt - classical textbook algorithm, a good default choice.
2. Bit mask based algorithm - stable performance on any input, but limited to maximum
search substring (the needle) length of 64 bytes.
3. Aho–Corasick - worse performance and higher memory consumption than [1] and [2], but
it supports multiple substring (the needles) search simultaneously, by inspecting every
byte of the haystack only once.

Each algorithm processes every byte of underlying buffer only once, they are implemented
as ByteProcessor.

Result:

Efficient search algorithms with linear time complexity available in Netty (I will share
benchmark results in a comment on a PR).
2020-04-15 10:21:24 +02:00
时无两丶
ff6d2e4949
Remove duplicate code in PoolArena. (#10174)
Motivation:

Remove duplicate code in PoolArena.

Modification:

Replace duplicate code with `tinyIdx` and `smallIdx`.

Result:

Clean code.
2020-04-15 09:29:23 +02:00
Dmitry Konstantinov
05b7af7ae4
Propagate ref to pool thread cache down in the allocation stack to avoid extra thread local lookup (#10166)
Motivation:
PoolChunk requires a link to a PoolThreadCache to init ByteBuf. Currently the link is retrieved from a thread local: arena.parent.threadCache().
It has some performance cost. At the beginning of the allocation call the PoolThreadCache is already retrieved from the thread local. The reference can be propagated through the calls and used.

Modifications:
Replace second lookup of PoolThreadCache during ByteBuf init by propagation of a reference to PoolThreadCache down in the allocation stack explicitly

Result:
Improve performance of ByteBuf allocation
--Before--
Benchmark                                            (size)  (tokens)  (useThreadCache)  Mode  Cnt    Score   Error  Units
SimpleByteBufPooledAllocatorBenchmark.getAndRelease     123         0              true  avgt   20   57.112 ± 1.004  ns/op
SimpleByteBufPooledAllocatorBenchmark.getAndRelease     123       100              true  avgt   20  222.827 ± 1.307  ns/op

--After--
Benchmark                                            (size)  (tokens)  (useThreadCache)  Mode  Cnt    Score   Error  Units
SimpleByteBufPooledAllocatorBenchmark.getAndRelease     123         0              true  avgt   20   50.732 ± 1.321  ns/op
SimpleByteBufPooledAllocatorBenchmark.getAndRelease     123       100              true  avgt   20  216.892 ± 3.806  ns/op
2020-04-06 08:01:01 +02:00
Dmitry Konstantinov
ea31b59037
Replace usage() with freeBytes() in thresholds within hot paths of PoolChunkList (#10141)
Motivation:
PoolChunk.usage() method has non-trivial computations. It is used currently in hot path methods invoked when an allocation and de-allocation are happened.
The idea is to replace usage() output comparison against percent thresholds by Chunk.freeBytes plain comparison against absolute thresholds. In such way the majority of computations from the threshold conditions are moved to init logic.

Modifications:
Replace PoolChunk.usage() conditions in PoolChunkList with equivalent conditions for PoolChunk.freeBytes()

Result:
Improve performance of allocation and de-allocation of ByteBuf from normal size cache pool
2020-03-31 22:11:16 +02:00
Dmitry Konstantinov
913cae6fef
Optimize log2 in PoolThreadCache (#10128)
Motivation:
The current implementation of log2 in PoolThreadCache uses a loop and less efficient than an version based on Integer.numberOfLeadingZeros (intrinsic).

Modifications:
Replace the current log2 implementation in PoolThreadCache with a version based on Integer.numberOfLeadingZeros

Result:
It can improve performance slightly during allocation and de-allocation of ByteBuf using pooled allocator.
2020-03-24 11:13:52 +01:00
root
14e4afeba2 [maven-release-plugin] prepare for next development iteration 2020-03-17 09:20:54 +00:00
root
c10c697e5b [maven-release-plugin] prepare release netty-4.1.48.Final 2020-03-17 09:18:28 +00:00
root
c623a50d19 [maven-release-plugin] prepare for next development iteration 2020-03-09 12:13:56 +00:00
root
a401b2ac92 [maven-release-plugin] prepare release netty-4.1.47.Final 2020-03-09 12:13:26 +00:00
root
e0d73bca4d [maven-release-plugin] prepare for next development iteration 2020-02-28 06:37:33 +00:00
root
ebe7af5102 [maven-release-plugin] prepare release netty-4.1.46.Final 2020-02-28 06:36:45 +00:00
Norman Maurer
a3e5e4876c
FixedCompositeByteBuf.isDirect() may return wrong value when constructed with empty array (#10005)
Motivation:

FixedCompositeByteBuf.isDirect() should return the same value as EMPTY_BUFFER.isDirect() when constructed via an empty array

Modifications:

- Return correct value when constructed via empty array.
- Add unit test

Result:

FixedCompositeByteBuf.isDirect() returns correct value
2020-02-08 17:05:26 +01:00
Norman Maurer
07149729cc
Use correct system property name in PooledByteBufAllocator (io.netty.allocator.cacheTrimIntervalMillis) (#9994)
Motivation:

We had a typo in the system property name that was used to lookup the cache trime interval. We should ensure we use the correct naming when lookup the property

Modifications:

- Support the old and the new (correct) naming of the property when configure the cache trim interval.
- Log something if someone uses the old (deprecated) name

Result:

Fixes https://github.com/netty/netty/issues/9981
2020-02-05 14:39:23 +01:00
root
9b1ea10a12 [maven-release-plugin] prepare for next development iteration 2020-01-13 09:13:53 +00:00
root
136db8680a [maven-release-plugin] prepare release netty-4.1.45.Final 2020-01-13 09:13:30 +00:00
Nick Hill
607bc05a2c Fix BufferOverflowException during non-Unsafe PooledDirectByteBuf resize (#9912)
Motivation

Recent optimization #9765 introduced a bug where the native indices of
the internal reused duplicate nio buffer are not properly reset prior to
using it to copy data during a reallocation operation. This can result
in BufferOverflowExceptions thrown during ByteBuf capacity changes.

The code path in question applies only to pooled direct buffers when
Unsafe is disabled or not available.

Modification

Ensure ByteBuffer#clear() is always called on the reused internal nio
buffer prior to returning it from PooledByteBuf#internalNioBuffer()
(protected method); add unit test that exposes the bug.

Result

Fixes #9911
2020-01-11 06:04:32 +01:00
root
79d4e74019 [maven-release-plugin] prepare for next development iteration 2019-12-18 08:32:54 +00:00
root
5ddf45a2d5 [maven-release-plugin] prepare release netty-4.1.44.Final 2019-12-18 08:31:43 +00:00
Norman Maurer
9a0ccf24f3
Add unit test for leak aware CompositeByteBuf that proves that there is no NPE (#9875)
Motivation:

https://github.com/netty/netty/issues/9873 reported a NPE in previous version of netty. We should add a unit test to verify there is no more NPE

Modifications:

Add a unit test

Result:

Prove that https://github.com/netty/netty/issues/9873 is fixed
2019-12-12 16:18:27 +01:00
Sergey Skrobotov
84547029d9 Change DefaultByteBufHolder.equals() to treat instances of different classes as not equal (#9855)
# Motivation:
`DefaultByteBufHolder.equals()` considers another object equal if it's an instance of `ByteBufferHolder` and if the contents of two objects are equal. However, the behavior of `equals` method is not a part of the `ByteBufHolder` contract so `DefaultByteBufHolder`'s version may be causing violation of the symmetric property if other classes have different logic.
There are already a few classes that are affected by this: `DefaultHttp2GoAwayFrame`, `DefaultHttp2UnknownFrame`, and `SctpMessage` are all overriding `equals` method breaking the symmetric property.
Another effect of this behavior is that all instances with empty data are considered equal. That may not be desireable in the situations when instances are created for predefined constants, e.g. `FullBulkStringRedisMessage.NULL_INSTANCE` and `FullBulkStringRedisMessage.EMPTY_INSTANCE` in `codec-redis`. 

# Modification:
Make `DefaultByteBufHolder.equals()` implementation only work for the objects of the same class.

# Result:
- The symmetric property of the `equals` method is restored for the classes in question.
- Instances of different classes are not considered equal even if the content of the data they hold are the same.
2019-12-10 11:29:44 +01:00
时无两丶
0cde4d9cb4 Uniform null pointer check. (#9840)
Motivation:
Uniform null pointer check.

Modifications:

Use ObjectUtil.checkNonNull(...)

Result:
Less code, same result.
2019-12-09 09:47:35 +01:00
Nick Hill
63d33b390a Minor simplifications/optimizations to AbstractByteBuf methods (#9845)
Motivation

While working on other changes I noticed some opportunities to
streamline a few things in AbstractByteBuf.

Modifications

- Avoid duplicate ensureAccessible() checks in discard(Some)ReadBytes()
and ensureWritable0(int) methods
- Simplify ensureWritable0(int) logic
- Make some conditional checks more concise

Result

Cleaner, possibly faster code
2019-12-05 11:32:21 +01:00
Nick Hill
b0feb5a81f Reduce ByteBuffer duplication when resizing pooled direct ByteBufs (#9765)
Motivation:

Currently when use of Unsafe is disabled and an internal reallocation is
performed for a direct PooledByteBuf, a one-off temporary duplicate is
made of the source and destination backing nio buffers so that the
copy can be done in a threadsafe manner.

The need for this can be reduced by sharing the temporary duplicate
buffer that is already stored in the corresponding destination
PooledByteBuf instance.

Modifications:

Have PoolArena#memoryCopy(...) take the destination PooledByteBuf
instead of the underlying mem reference and offset, and use
internalNioBuffer() to obtain/initialize a reusable duplicate of the
backing nio buffer.

Result:

Fewer temporary allocations when resizing direct pooled ByteBufs in the
non-Unsafe case
2019-11-16 11:26:02 -08:00
Nick Hill
535d598492 Introduce ByteBuf#isContiguous() method (#9735)
Motivation

There's currently no way to determine whether an arbitrary ByteBuf
behaves internally like a "singluar" buffer or a composite one, and this
can be important to know when making decisions about how to manipulate
it in an efficient way.

An example of this is the ByteBuf#discardReadBytes() method which
increases the writable bytes for a contiguous buffer (by readerIndex)
but does not for a composite one.

Unfortunately !(buf instanceof CompositeByteBuf) is not reliable, since
for example this will be true in the case of a sliced CompositeByteBuf
or some third-party composite implementation.

isContiguous was chosen over isComposite since we want to assume "not
contiguous" in the unknown/default case - the doc will it clear that
false does not imply composite.

Modifications

- Add ByteBuf#isContiguous() which returns true by default
- Override the "concrete" ByteBuf impls to return true and ensure
wrapped/derived impls delegate it appropriately
- Include some basic unit tests

Result

Better assumptions/decisions possible when manipulating arbitrary
ByteBufs, for example when combining/cumulating them.
2019-11-06 12:06:25 +01:00
Norman Maurer
6c061abc49
Hide Recycler implemention to allow experimenting with different implementions of an Object pool (#9715)
Motivation:

At the moment we directly extend the Recycler base class in our code which makes it hard to experiment with different Object pool implementation. It would be nice to be able to switch from one to another by using a system property in the future. This would also allow to more easily test things like https://github.com/netty/netty/pull/8052.

Modifications:

- Introduce ObjectPool class with static method that we now use internally to obtain an ObjectPool implementation.
- Wrap the Recycler into an ObjectPool and return it for now

Result:

Preparation for different ObjectPool implementations
2019-10-26 00:34:30 -07:00
Nick Hill
f4b4a44c7c Change javadoc of ByteBuf#indexOf(...) to match its behaviour (#9679)
Motivation

Currently doc != code and so one needs to change. Though behaviour as
currently documented might be more intuitive, we don't want to break
anyone so will adjust the doc instead. See #9503 for discussion.

Modifications

Correct the javadoc of indexOf(...) method in ByteBuf abstract class.

Results

Correct javadoc
2019-10-24 23:42:30 -07:00
root
844b82b986 [maven-release-plugin] prepare for next development iteration 2019-10-24 12:57:00 +00:00
root
d066f163d7 [maven-release-plugin] prepare release netty-4.1.43.Final 2019-10-24 12:56:30 +00:00
root
92941cdcac [maven-release-plugin] prepare for next development iteration 2019-09-25 06:15:31 +00:00
root
bd907c3b3a [maven-release-plugin] prepare release netty-4.1.42.Final 2019-09-25 06:14:31 +00:00
root
01d805bb76 [maven-release-plugin] prepare for next development iteration 2019-09-12 16:09:55 +00:00
root
7cf69022d4 [maven-release-plugin] prepare release netty-4.1.41.Final 2019-09-12 16:09:00 +00:00
root
aef47bec7f [maven-release-plugin] prepare for next development iteration 2019-09-12 05:38:11 +00:00
root
267e5da481 [maven-release-plugin] prepare release netty-4.1.40.Final 2019-09-12 05:37:30 +00:00
Nick Hill
1039f69e53 Fix for incorrect values from CompositeByteBuf#component(int) (#9525)
Motivation

This is a "simpler" alternative to #9416 which fixes the same
CompositeByteBuf bugs described there, originally reported by @jingene
in #9398.

Modifications
- Add fields to Component class for the original buffer along with its
adjustment, which may be different to the already-stored unwrapped
buffer. Use it in appropriate places to ensure correctness and
equivalent behaviour to that prior to the earlier optimizations
- Add comments explaining purpose of each of the Component fields
- Unwrap more kinds of buffers in newComponent method to extend scope of
the existing indirection-reduction optimization
- De-duplicate common buffer consolidation logic
- Unit test for the original bug provided by @jingene

Result
- Correct behaviour / fixed bugs
- Some code deduplication / simplification
- Unwrapping optimization applied to more types of buffers

The downside is increased mem footprint from the two new fields, and
additional allocations in some specific cases, though those should be
rare.


Co-authored-by: jingene <jingene0206@gmail.com>
2019-09-02 13:52:17 +02:00
Codrut Stancu
b7e9829a49 Update GraalVM Native Image configuration. (#9515)
Motivation:

The Netty classes are initialized at build time by default for GraalVM Native Image compilation. This is configured via the `--initialize-at-build-time=io.netty` option. While this reduces start-up time it can lead to some problems:

 - The class initializer of `io.netty.buffer.PooledByteBufAllocator` looks at the maximum memory size to compute the size of internal buffers. If the class initializer runs during image generation, then the buffers are sized according to the very large heap size that the image generator uses, and Netty allocates several arrays that are 16 MByte. The fix is to initialize the following 3 classes at run time: `io.netty.buffer.PooledByteBufAllocator,io.netty.buffer.ByteBufAllocator,io.netty.buffer.ByteBufUtil`. This fix was dependent on a GraalVM Native Image fix that was included in 19.2.0.

 - The class initializer of `io.netty.handler.ssl.util.ThreadLocalInsecureRandom` needs to be initialized at runtime to ensure that the generated values are trully random and not fixed for each generated image.

 - The class initializers of `io.netty.buffer.AbstractReferenceCountedByteBuf` and `io.netty.util.AbstractReferenceCounted` compute field offsets. While the field offset recomputation is necessary for correct execution as a native image these initializers also have logic that depends on the presence/absence of `sun.misc.Unsafe`, e.g., via the `-Dio.netty.noUnsafe=true` flag. The fix is to push these initializers to runtime so that the field offset lookups (and the logic depending on them) run at run time. This way no manual substitutions are necessary either.
 
Modifications:

Add `META-INF/native-image` configuration files that correctly trigger the inialization of the above classes at run time via `--initialize-at-run-time=...` flags.
 
Result:

Fixes the initialisation issues described above for Netty executables built with GraalVM.
2019-08-30 09:21:11 +02:00
Norman Maurer
da2aba5742
Reduce GC produced by AbstractByteBuf.indexOf(..) implementation (#9502)
Motivation:

AbstractByteBuf.indexOf(...) currently delegates to ByteBufUtils.indexOf(...) which will create a new ByteBufProcessor on each call. This is done to reduce overhead of bounds-checks. Unfortunally while this reduces bounds checks it produces a lot of GC. We can just implement our own version in AbstractByteBuf which makes use of _getByte(...) and so does no bound checks as well but also not need to create any garbage.

Modifications:

Write optimized implementation of indexOf(...) for AbstractByteBuf

Result:

Fixes https://github.com/netty/netty/issues/9499.
2019-08-24 13:46:28 +02:00
Norman Maurer
d8e59ca638
Avoid creating FileInputStream and FileOutputStream for obtaining Fil… (#8110)
Motivation:

If all we need is the FileChannel we should better use RandomAccessFile as FileInputStream and FileOutputStream use a finalizer.

Modifications:

Replace FileInputStream and FileOutputStream with RandomAccessFile when possible.

Result:

Fixes https://github.com/netty/netty/issues/8078.
2019-08-17 09:43:01 +02:00
Nick Hill
4db38b4e0c Don't zero non-readable buffer regions when capacity is decreased (#9427)
Motivation

#1802 fixed ByteBuf implementations to ensure that the whole buffer
region is preserved when capacity is increased, not just the readable
part. The behaviour is still different however when the capacity is
_decreased_ - data outside the currently-readable region is zeroed.

Modifications

Update ByteBuf capacity(int) implementations to also copy the whole
buffer region when the new capacity is less than the current capacity.

Result

Consistent behaviour of ByteBuf#capacity(int) regardless of whether the
new capacity is greater than or less than the current capacity.
2019-08-16 08:18:09 +02:00
root
d45a4ce01b [maven-release-plugin] prepare for next development iteration 2019-08-13 17:16:42 +00:00
root
88c2a4cab5 [maven-release-plugin] prepare release netty-4.1.39.Final 2019-08-13 17:15:20 +00:00
Nick Hill
695aa0959d Use alloc().heapBuffer(...) to allocate new heap buffer.
Motivation

Underlying array allocations in UnpooledHeapByteBuf are intended be done
via the protected allocateArray(int) method, so that they can be tracked
and/or overridden by subclasses, for example
UnpooledByteBufAllocator$InstrumentedUnpooledHeapByteBuf or #8015. But
it looks like an explicit allocation was missed in the copy(int,int)
method.

Modification

Just use alloc().heapBuffer(...) for the allocation

Result

No possibility of "missing" array allocations when ByteBuf#copy is used.
2019-08-13 10:52:11 +02:00
Nick Hill
fedcc40196 Fix ByteBufUtil#writeUtf8 subsequence split surrogate edge-case bug (#9437)
Motivation:

#9224 introduced overrides of ByteBufUtil#writeUtf8(...) and related
methods to operate on a sub-CharSequence directly to save having to
allocate substrings, but it missed an edge case where the subsequence
does not extend to the end of the CharSequence and the last char in the
sequence is a high surrogate.

Due to the catch-IndexOutOfBoundsException optimization that avoids an
additional bounds check, it would be possible to read past the specified
end char index and successfully decode a surrogate pair which would
otherwise result in a '?' byte being written.

Modifications:

- Check for end-of-subsequence before reading next char after a high
surrogate is encountered in the
writeUtf8(AbstractByteBuf,int,CharSequence,int,int) and
utf8BytesNonAscii methods
- Add unit test for this edge case

Result:

Bug is fixed.

This removes the bounds-check-avoidance optimization but it does not
appear to have a measurable impact on benchmark results, including when
the char sequence contains many surrogate pairs (which should be rare in
any case).
2019-08-10 20:54:04 +02:00
root
718b7626e6 [maven-release-plugin] prepare for next development iteration 2019-07-24 09:05:57 +00:00
root
465c900c04 [maven-release-plugin] prepare release netty-4.1.38.Final 2019-07-24 09:05:23 +00:00
Norman Maurer
131be58f48
Correctly take length of ByteBufInputStream into account for readLine… (#9310)
* Correctly take length of ByteBufInputStream into account for readLine() / readByte()

Motivation:

ByteBufInputStream did not correctly take the length into account when validate bounds for readLine() / readByte() which could lead to read more then allowed.

Modifications:

- Correctly take length into account
- Add unit tests
- Fix existing unit test

Result:

Correctly take length of ByteBufInputStream into account.
Related to https://github.com/netty/netty/pull/9306.
2019-07-01 20:55:23 +02:00