Commit Graph

328 Commits

Author SHA1 Message Date
Norman Maurer
2d9e0f53a5 Better implementation of AttributeMap and also add hasAttr(...). SeeĀ [#2439]
Motivation:
The old DefaultAttributeMap impl did more synchronization then needed and also did not expose a efficient way to check if an attribute exists with a specific key.

Modifications:
* Rewrite DefaultAttributeMap to not use IdentityHashMap and synchronization on the map directly. The new impl uses a combination of AtomicReferenceArray and synchronization per chain (linked-list). Also access the first Attribute per bucket can be done without any synchronization at all and just uses atomic operations. This should fit for most use-cases pretty weel.
* Add hasAttr(...) implementation

Result:
It's now possible to check for the existence of a attribute without create one. Synchronization is per linked-list and the first entry can even be added via atomic operation.
2014-05-15 06:47:42 +02:00
Norman Maurer
2f7d60f234 Minimize memory footprint of HashedWheelTimer and context-switching
Motivation:
At the moment there are two issues with HashedWheelTimer:
* the memory footprint of it is pretty heavy (250kb fon an empty instance)
* the way how added Timeouts are handled is inefficient in terms of how locks etc are used and so a lot of context-switching / condition can happen.

Modification:
Rewrite HashedWheelTimer to use an optimized bucket implementation to store the submitted Timeouts and a MPSC queue to handover the timeouts.  So volatile writes are reduced to a minimum and also the memory foot-print of the buckets itself is reduced a lot as the bucket uses a double-linked-list. Beside this we use Atomic*FieldUpdater where-ever possible to improve the memory foot-print and performance.

Result:
Lower memory-footprint and better performance
2014-05-11 15:12:29 +02:00
Trustin Lee
d69ad2f85c More robust native library discovery in Mac OS X
Motivation:

Some JDK versions of Mac OS X generates a JNI dynamic library with '.jnilib' extension rather than with '.dynlib' extension.  However, System.mapLibraryName() always returns 'lib<name>.dynlib'. As a result, NativeLibraryLoader fails to load the native library whose extension is .jnilib.

Modification:

Try to find both '.jnilib' and '.dynlib' resources on OS X.

Result:

Dynamic libraries are loaded correctly in Mac OS X, and thus we can continue the OpenSslEngine work.
2014-05-11 18:53:43 +09:00
Trustin Lee
6c1af9036f Simplify native library resolution using os-maven-plugin
Motivation:

So far, we used a very simple platform string such as linux64 and
linux32.  However, this is far from perfection because it does not
include anything about the CPU architecture.

Also, the current build tries to put multiple versions of .so files into
a single JAR.  This doesn't work very well when we have to ship for many
different platforms.  Think about shipping .so/.dynlib files for both
Linux and Mac OS X.

Modification:

- Use os-maven-plugin as an extension to determine the current OS and
  CPU architecture reliable at build time
- Use Maven classifier instead of trying to put all shared libraries
  into a single JAR
- NativeLibraryLoader does not guess the OS and bit mode anymore and it
  always looks for the same location regardless of platform, because the
  Maven classifier does the job instead.

Result:

Better scalable native library deployment and retrieval
2014-05-02 04:21:47 +09:00
Trustin Lee
1492b32da7 Code clean-up
Motivation:

It is less confusing not to spread Thread.interrupt() calls.

Modification:

- Comments
- Move generatorThread.interrupt() to where currentThread.interrupt() is
  triggered

Result:

Code that is easier to read
2014-04-25 17:44:04 +09:00
Trustin Lee
b9039eaa82 Synchronized between 4.1 and master again (part 2)
Motivation:
4 and 5 were diverged long time ago and we recently reverted some of the
early commits in master.  We must make sure 4.1 and master are not very
different now.

Modification:
Remove ChannelHandlerInvoker.writeAndFlush(...) and the related
implementations.

Result:
4.1 and master got closer.
2014-04-25 15:06:26 +09:00
Trustin Lee
db3709e652 Synchronized between 4.1 and master
Motivation:

4 and 5 were diverged long time ago and we recently reverted some of the
early commits in master.  We must make sure 4.1 and master are not very
different now.

Modification:

Fix found differences

Result:

4.1 and master got closer.
2014-04-25 00:38:02 +09:00
Trustin Lee
a31f36d933 Stop ThreadLocalRandom's initial seed generation immediately on interruption
Motivation:

ThreadLocalRandomTest reveals that ThreadLocalRandom's initial seed generation loop becomes tight if the thread is interrupted.
We currently interrupt ourselves inside the wait loop, which will raise an InterruptedException again in the next iteration, resulting in infinite (up to 3 seconds) exception construction and thread interruptions.

Modification:

- When the initial seed generator thread is interrupted, break out of the wait loop immediately.
- Log properly when the initial seed generation failed due to interruption.
- When failed to generate the initial seed, interrupt the generator thread just in case the SecureRandom implementation handles it properly.
- Make the initial seed generator thread daemon and handle potential exceptions raised due to the interruption.

Result:

No more tight loop on interruption.  More robust generator thread termination. Fixes #2412
2014-04-20 17:55:25 +09:00
Norman Maurer
88481131be [#2353] Use a privileged block to get ClassLoader and System property if needed
Motivation:
When using System.getProperty(...) and various methods to get a ClassLoader it will fail when a SecurityManager is in place.

Modifications:
Use a priveled block if needed. This work is based in the PR #2353 done by @anilsaldhana .

Result:
Code works also when SecurityManager is present
2014-04-08 14:12:25 +02:00
Trustin Lee
7dc63ccd95 Add EventExecutor.children() in favor of iterator()
Motivation:

EventExecutor.iterator() is fixed to return Iterator<EventExecutor> and there's no way to change that as long as we don't extend Iterable.  However, a user should have a way to cast the returned set of executors painlessly.  Currently, it is only possible with an explicit cast like (Iterator<NioEventLoop>).

Modifications:

Instead, I added a new method called 'children()' which returns an immutable collection of child executors whose method signature looks like the following:

    <E extends EventExecutor> Set<E> children();

Result:

A user can now do this:

    Set<NioEventLoop> loops = group.children();
    for (NioEventLoop l: loops) { ... }

Unfortunately, this is not possible:

    for (NioEventLoop l: group.children()) { ... }

However, it's still a gain that a user doesn't need to down-cast explicitly and to add the '@SuppressWarnings` annotation.
2014-03-24 12:32:55 +09:00
Trustin Lee
924113ce8c Make DefaultEventExecutor usable by users.
Motivation:

There's no reason to keep our users from using DefaultEventExecutor directly.  It should be actually very useful to them.

Modifications:

Make DefaultEventExecutor public and add useful public constructors.

Result:

DefaultEventExecutor got usable by anyone, yielding more value as a generic library.
2014-03-24 11:18:03 +09:00
Trustin Lee
4332821e6f Use common non-magic number for shutdown timeout
Motivation:

AbstractEventExecutor and AbstractEventExecutorGroup have hard-coded magic timeout numbers.  They should have the same timeout numbers, but it's easy to break that rule because they are hard-coded in each place.

Modifications:

Add package private constants to AbstractEventExecutor and let AbstractEventExecutorGroup use them.

Result:

Single timeout change affects two classes.
2014-03-24 11:12:17 +09:00
Trustin Lee
007694b963 Implement EventExecutor.parent() in AbstractEventExecutor
Motivation:

EventExecutor.parent() and EventLoop.parent() almost always return a constant parent executor.  There's not much reason to let it implemented in subclasses.

Modifications:

- Implement AbstractEventExecutor.parent() with an additional contructor
- Add AbstractEventLoop so that subclasses extend AbstractEventLoop, which implements parent() appropriately
- Remove redundant parent() implementations in the subclasses
- Fix inspector warnings

Result:

Less duplication.
2014-03-24 11:05:51 +09:00
Trustin Lee
2215ed0a35 Use SecureRandom.generateSeed() to generate ThreadLocalRandom's initialSeedUniquifier
Motivation:

Previously, we used SecureRandom.nextLong() to generate the initialSeedUniquifier.  This required more entrophy than necessary because it has to 1) generate the seed of SecureRandom first and then 2) generate a random long integer.  Instead, we can use generateSeed() to skip the step (2)

Modifications:

Use generateSeed() instead of nextLong()

Result:

ThreadLocalRandom requires less amount of entrphy to start up
2014-03-21 13:43:15 +09:00
Trustin Lee
ff179c3430 Reduce the time taken by NetUtil and DefaultChannelId class initialization
Motivation:

As reported in #2331, some query operations in NetworkInterface takes much longer time than we expected.  For example, specifying -Djava.net.preferIPv4Stack=true option in Window increases the execution time by more than 4 times.  Some Windows systems have more than 20 network interfaces, and this problem gets bigger as the number of unused (virtual) NICs increases.

Modification:

Use NetworkInterface.getInetAddresses() wherever possible.
Before iterating over all NICs reported by NetworkInterface, filter the NICs without proper InetAddresses.  This reduces the number of candidates quite a lot.
NetUtil does not query hardware address of NIC in the first place but uses InetAddress.isLoopbackAddress().
Do not call unnecessary query operations on NetworkInterface.  Just get hardware address and compare.

Result:

Significantly reduced class initialization time, which should fix #2331.
2014-03-21 11:39:41 +09:00
Trustin Lee
19422972e3 Fix and simplify freeing a direct buffer / Fix Android support
Motivation:

6e8ba291cf introduced a regression in Android because Android does not have sun.nio.ch.DirectBuffer (see #2330.)  I also found PlatformDependent0.freeDirectBuffer() and freeDirectBufferUnsafe() are pretty much same after the commit and the unsafe version should be removed.

Modifications:

- Do not use the pooled allocator in Android because it's too resource hungry for Androids.
- Merge PlatformDependent0.freeDirectBuffer() and freeDirectBufferUnsafe() into one method.
- Make the Unsafe unavailable when sun.nio.ch.DirectBuffer is unavailable.  We could keep the Unsafe available and handle the sun.nio.ch.DirectBuffer case separately, but I don't want to complicate our code just because of that.  All supported JDK versions have sun.nio.ch.DirectBuffer if the Unsafe is available.

Result:

Simpler code. Fixes Android support (#2330)
2014-03-20 11:11:07 +09:00
Trustin Lee
9fe9710315 Rename "io.netty.recycler.maxCapacity.default" to "io.netty.recycler.maxCapacity"
Motivation:

'io.netty.recycler.maxCapacity.default' is the only property for recycler's default maximum capacity, so having the 'default' suffix only increases the length of the property name.

Modifications:

Rename "io.netty.recycler.maxCapacity.default" to "io.netty.recycler.maxCapacity"

Result:

Shorter system property name. The future addition of system properties, such as io.netty.recycler.maxCapacity.outboundBuffer, are not confusing either.
2014-03-18 16:26:16 +09:00
Norman Maurer
16a85e6cca [#2307] Remove synchronized bottleneck in SingleThreadEventExecutor.execute(...)
Motivation:
Remove the synchronization bottleneck in startThread() which is called by each execute(..) call from outside the EventLoop.

Modifications:
Replace the synchronized block with the use of AtomicInteger and compareAndSet loops.

Result:
Less conditions during SingleThreadEventExecutor.execute(...)
2014-03-13 10:08:01 +01:00
Norman Maurer
50e95383a3 Fix checkstyle errors introduced by f0d1bbd63e 2014-03-12 12:41:06 +01:00
Trustin Lee
e57cf9d201 Add capacity limit to Recycler / Optimize when assertion is off
Motivation:

- As reported recently [1], Recycler's thread-local object pool has unbounded capacity which is a potential problem.
- It accesses a hash table on each push and pop for debugging purposes.  We don't really need it besides debugging Netty itself.

Modifications:

- Introduced the maxCapacity constructor parameter to Recycler.  The default default maxCapacity is retrieved from the system property whose default is 256K, which should be plenty for most cases.
- Recycler.Stack.map is now created and accessed only when assertion is enabled for Recycler.

Result:

- Recycler does not grow infinitely anymore.
- If assertion is disabled, Recycler should be much faster.

[1] https://github.com/netty/netty/issues/1841
2014-03-12 18:16:53 +09:00
Norman Maurer
722f6c5e1a Use bitwise operations to choose next EventExecutor if number of EventExecutors is power of two 2014-03-10 20:48:20 +01:00
Jatinder
8afc2cd378 [#2252] Fix bug where AppendableCharSequence private constructor does not set correct position 2014-03-03 20:03:24 +01:00
Andrew Gaul
1f5b74762b Correct ConcurrentHashMapV8 bitwise arithmetic
Previously ConcurrentHashMapV8 evaulated ((x | 1) == 0), an expression
that always returned false.  This commit brings Netty closer to the
Java 8 implementation.
2014-03-03 06:44:45 +01:00
Norman Maurer
d3ffa1b02b [#1259] Add optimized queue for SCMP pattern and use it in NIO and native transport
This queue also produces less GC then CLQ when make use of OneTimeTask
2014-02-27 13:28:37 +01:00
Norman Maurer
dbb2198839 Fix a regression which could lead to GenericFutureListeners never been notifed. Part of [#2186].
This regression was introduced by commit c97f2d2de00ad74835067cb6f5a62cd4651d1161
2014-02-20 15:13:25 +01:00
Norman Maurer
9330172f80 Introduce a native transport for linux using epoll ET
This transport use JNI (C) to directly make use of epoll in Edge-Triggered mode for maximal performance on Linux. Beside this it also support using TCP_CORK and produce less GC then the NIO transport using JDK NIO.
It only builds on linux and skip the build if linux is not used. The transport produce a jar which contains all needed .so files for 32bit and 64 bit. The user only need to include the jar as dependency as usually
to make use of it and use the correct classes.

This includes also some cleanup of @trustin
2014-02-15 22:44:56 +01:00
Trustin Lee
f0127ec991 Do not warn about Unsafe in Android 2014-02-14 12:06:24 -08:00
Trustin Lee
8837afddf8 Enable a user specify an arbitrary information with ReferenceCounted.touch()
- Related: #2163
- Add ResourceLeakHint to allow a user to provide a meaningful information about the leak when touching it
- DefaultChannelHandlerContext now implements ResourceLeakHint to tell where the message is going.
- Cleaner resource leak report by excluding noisy stack trace elements
2014-02-13 18:16:25 -08:00
Trustin Lee
45e70d9935 Add ReferenceCounted.touch() / Add missing retain() overrides
- Fixes #2163
- Inspector warnings
2014-02-13 18:10:11 -08:00
Trustin Lee
2b84314fdd Add Recycler.Handle.recycle() so that it's possible to recycle an object without an explicit reference to Recycler 2014-02-13 17:24:37 -08:00
Trustin Lee
6e23cf8c92 Fix checkstyle 2014-02-13 17:08:22 -08:00
Trustin Lee
516795fcfb Add convenient logging methods for logging exceptions quickly
.. Mainly useful for writing tests or ad-hoc debugging
2014-02-13 17:08:14 -08:00
Vladimir Krivosheev
eb308cfff6 ability to use Executor instead of ThreadFactory 2014-02-13 16:14:41 -08:00
Trustin Lee
ebc78dab1d Add a getter method for accessing the ClassPool of JavassistTypeParameterMatcherGenerator
.. so that a user can even manipulate the class pool as they wish.
2014-02-13 15:25:55 -08:00
Trustin Lee
499033d44f Add a shortcut method for collision-free naming 2014-02-13 15:17:09 -08:00
Trustin Lee
b533a1361b Replace UniqueName with Constant and ConstantPool
- Proposed fix for #1824

UniqueName and its subtypes do not allow getting the previously registered instance.  For example, let's assume that a user is running his/her application in an OSGi container with Netty bundles and his server bundle.  Whenever the server bundle is reloaded, the server will try to create a new AttributeKey instance with the same name.  However, Netty bundles were not reloaded at all, so AttributeKey will complain that the name is taken already (by the previously loaded bundle.)

To fix this problem:

- Replaced UniqueName with Constant, AbstractConstant, and ConstantPool.  Better name and better design.

- Sctp/Udt/RxtxChannelOption is not a ChannelOption anymore.  They are just constant providers and ChannelOption is final now.  It's because caching anything that's from outside of netty-transport will lead to ClassCastException on reload, because ChannelOption's constant pool will keep all option objects for reuse.

- Signal implements Constant because we can't ensure its uniqueness anymore by relying on the exception raised by UniqueName's constructor.
2014-02-13 15:14:34 -08:00
Trustin Lee
0e71da3082 Fix a bug where DefaultPromise.setUncancellable() returns a wrong value
- Fixes #2220 - again
- Missing negation
2014-02-10 11:48:20 -08:00
Trustin Lee
7e0e4c6325 Fix a bug where DefaultPromise.setUncancellable() returns a wrong value
- Fixes #2220
- Its Javadoc says it returns true when the promise is done (but not cancelled) or the promise is uncancellable, but it returns false when the promise is done.
2014-02-10 11:40:04 -08:00
Trustin Lee
e592d06364 Fix the compilation error in ConcurrentHashMapV8 + JDK8 2014-02-08 08:56:17 -08:00
Trustin Lee
78cf0e37e2 Log the rejected listener notification task under a dedicated logger name.
- Fixes #2166
- Some user applications are fine with the failure of notification
2014-02-07 10:22:37 -08:00
Norman Maurer
f23d68b42f [#2187] Always do a volatile read on the refCnt 2014-02-07 09:23:16 +01:00
Trustin Lee
103a08e6c6 Reduce code duplication in DefaultPromise 2014-02-06 22:30:10 -08:00
Trustin Lee
309ee68c21 Fix a race condition in DefaultPromise
.. which occurs when a user adds a listener from different threads after the promise is done and the notifications for the listeners, that were added before the promise is done, is in progress.  For instance:

   Thread-1: p.addListener(listenerA);
   Thread-1: p.setSuccess(null);
   Thread-2: p.addListener(listenerB);
   Thread-2: p.executor.execute(taskNotifyListenerB);
   Thread-1: p.executor.execute(taskNotifyListenerA);

taskNotifyListenerB should not really notify listenerB until taskNotifyListenerA is finished.

To fix this issue:

- Change the semantic of (listeners == null) to determine if the early
  listeners [1] were notified
- If a late listener is added before the early listeners are notified,
  the notification of the late listener is deferred until the early
  listeners are notified (i.e. until listeners == null)
- The late listeners with deferred notifications are stored in a lazily
  instantiated queue to preserve ordering, and then are notified once
  the early listeners are notified.

[1] the listeners that were added before the promise is done
[2] the listeners that were added after the promise is done
2014-02-06 22:05:24 -08:00
Trustin Lee
c4c71e6d28 Fix the potential copyright issue in SocksCommonUtils
- Add StringUtil.toHexString() methods which are based on LoggingHandler's lookup table implementation, and use it wherever possible
2014-02-06 15:00:06 -08:00
Norman Maurer
9bee78f91c Provide an optimized AtomicIntegerFieldUpdater, AtomicLongFieldUpdater and AtomicReferenceFieldUpdater 2014-02-06 20:08:45 +01:00
Valentin Kovalenko
40f4b5c9db Restore of interrupt status after catch of InterruptedException was added 2014-02-03 06:58:15 +01:00
Norman Maurer
64c3f58279 Not wakeup the EventLoop for writes as they will not cause a flush anyway 2014-02-01 13:45:27 +01:00
Trustin Lee
9f7a9077d6 Remove code duplication 2014-01-29 12:13:11 +09:00
MiddleBen
6e8ba291cf Simplify the acquisition of Cleaner 2014-01-29 11:55:06 +09:00
Trustin Lee
0bf5ca22cb Cleaner resource leak report by excluding noisy stack trace elements 2014-01-29 11:53:23 +09:00