Commit Graph

25 Commits

Author SHA1 Message Date
Scott Mitchell
94deea409e Fix Native EPOLL Build Failure
Motiviation:
If sendmmsg is already defined then the native epoll module failed to build because of conflicting definitions.
The mmsghdr type was also redefined on systems that already supported this structure.

Modifications:
Provide a way so that systems which already define sendmmsg and mmsghdr can build
Provide a way so that systems which don't define sendmmsg and mmsghdr can build

Result:
The native EPOLL module can build in more environments
2014-09-17 20:56:12 +02:00
Norman Maurer
d5b9f58f1f Add support for sendmmsg(...) and so allow to write multiple DatagramPackets with one syscall. Related to [#2719]
Motivation:

On linux with glibc >= 2.14 it is possible to send multiple DatagramPackets with one syscall. This can be a huge performance win and so we should support it in our native transport.

Modification:

- Add support for sendmmsg by reuse IovArray
- Factor out ThreadLocal support of IovArray to IovArrayThreadLocal for better separation as we use IovArray also without ThreadLocal in NativeDatagramPacketArray now
- Introduce NativeDatagramPacketArray which is used for sendmmsg(...)
- Implement sendmmsg(...) via jni
- Expand DatagramUnicastTest to test also sendmmsg(...)

Result:

Netty now automatically use sendmmsg(...) if it is supported and we have more then 1 DatagramPacket in the ChannelOutboundBuffer and flush() is called.
2014-09-09 10:03:17 +02:00
Norman Maurer
f1f14f524a Allow to write CompositeByteBuf directly via EpollDatagramChannel. Related to [#2719]
Motivation:

On linux it is possible to use the sendMsg(...) system call to write multiple buffers with one system call when using datagram/udp.

Modifications:

- Implement the needed changes and make use of sendMsg(...) if possible for max performance
- Add tests that test sending datagram packets with all kind of different ByteBuf implementations.

Result:

Performance improvement when using CompoisteByteBuf and EpollDatagramChannel.
2014-09-09 09:50:42 +02:00
Norman Maurer
7e48801f71 [#2867] Workaround performance issue with IPv4-mapped-on-IPv6 addresses
Motivation:

InetAddress.getByName(...) uses exceptions for control flow when try to parse IPv4-mapped-on-IPv6 addresses. This is quite expensive.

Modifications:

Detect IPv4-mapped-on-IPv6 addresses in the JNI level and convert to IPv4 addresses before pass to InetAddress.getByName(...) (via InetSocketAddress constructor).

Result:

Eliminate performance problem causes by exception creation when parsing IPv4-mapped-on-IPv6 addresses.
2014-09-09 07:24:17 +02:00
Trustin Lee
2ded0dd6fe Fix data corruption in FileRegion transfer with epoll transport
Related issue: #2764

Motivation:

EpollSocketChannel.writeFileRegion() does not handle the case where the
position of a FileRegion is non-zero properly.

Modifications:

- Improve SocketFileRegionTest so that it tests the cases where the file
  transfer begins from the middle of the file
- Add another jlong parameter named 'base_off' so that we can take the
  position of a FileRegion into account

Result:

Improved test passes. Corruption is gone.
2014-08-13 16:58:35 -07:00
Norman Maurer
410b5623ff Use correct exception message when throw exception from native code
Motivation:

We sometimes not use the correct exception message when throw it from the native code.

Modifications:

Fixed the message.

Result:

Correct message in exception
2014-07-28 13:34:09 -07:00
Norman Maurer
ca0571cc9d Optimize native transport for gathering writes
Motivation:

While benchmarking the native transport with gathering writes I noticed that it is quite slow. This is due the fact that we need to do a lot of array copies to get the buffers into the iov array.

Modification:

Introduce a new class calles IovArray which allows to fill buffers directly in a iov array that can be passed over to JNI without any array copies. This gives a nice optimization in terms of speed when doing gathering writes.

Result:

Big performance improvement when doing gathering writes. See the included benchmark...

Before:
[nmaurer@xxx]~% wrk/wrk -H 'Host: localhost' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' -H 'Connection: keep-alive' -d 120 -c 256 -t 16 --pipeline 256  http://xxx:8080/plaintext
Running 2m test @ http://xxx:8080/plaintext
  16 threads and 256 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    23.44ms   16.37ms 259.57ms   91.77%
    Req/Sec   181.99k    31.69k  304.60k    78.12%
  346544071 requests in 2.00m, 46.48GB read
Requests/sec: 2887885.09
Transfer/sec:    396.59MB

With this change:
[nmaurer@xxx]~% wrk/wrk -H 'Host: localhost' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' -H 'Connection: keep-alive' -d 120 -c 256 -t 16 --pipeline 256  http://xxx:8080/plaintext
Running 2m test @ http://xxx:8080/plaintext
  16 threads and 256 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    21.93ms   16.33ms 305.73ms   92.34%
    Req/Sec   194.56k    33.75k  309.33k    77.04%
  369617503 requests in 2.00m, 49.57GB read
Requests/sec: 3080169.65
Transfer/sec:    423.00MB
2014-07-25 09:54:41 +02:00
Norman Maurer
860e475a18 [#2685] Epoll transport should use GetPrimitiveArrayCritical / ReleasePrimitiveArrayCritical
Motivation:

At the moment we use Get*ArrayElement all the time in the epoll transport which may be wasteful as the JVM may do a memory copy for this. For code-path that will get executed fast (without blocking) we should better make use of GetPrimitiveArrayCritical and ReleasePrimitiveArrayCritical as this signal the JVM that we not want to do any memory copy if not really needed. It is important to only do this on non-blocking code-path as this may even suspend the GC to disallow the JVM to move the arrays around.

See also http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html#GetPrimitiveArrayCritical

Modification:

Make use of GetPrimitiveArrayCritical / ReleasePrimitiveArrayCritical as replacement for Get*ArrayElement / Release*ArrayElement where possible.

Result:

Better performance due less memory copies.
2014-07-21 07:13:41 +02:00
Norman Maurer
3ca19af2f8 [#2667] Write until EAGAIN in native transport
Motivation:

We need to continue write until we hit EAGAIN to make sure we not see an starvation

Modification:

Write until EAGAIN is returned

Result:

No starvation when using native transport with ET.
2014-07-18 11:26:32 +02:00
Norman Maurer
dfa00508d9 [#2647] Handle IOV_MAX in java code
Motivation:

The handling of IOV_MAX was done in JNI code base which makes stuff really complicated to maintain etc.

Modifications:

Move handling of IOV_MAX to java code to simplify stuff

Result:

Cleaner code.
2014-07-18 07:00:02 +02:00
Norman Maurer
6b71089373 Fix JVM segfault during JNI call. Part of [#2647]
Motivation:
Currently when Native.writev(...) is used it is possible to see a JVM segfault because the offset is updated to early.

Modification:
Only update the offset once it is safe to do so.

Result:
No more segfault
2014-07-09 13:36:15 +02:00
Norman Maurer
578068c7e6 [#2647] Respect IOV_MAX when call writev in native transport
Motivation:

epoll transport fails on gathering write of more then 1024 buffers. As linux supports max. 1024 iov entries when calling writev(...) the epoll transport throws an exception.

Thanks again to @blucas to provide me with a reproducer and so helped me to understand what the issue is.

Modifications:

Make sure we break down the writes if to many buffers are uses for gathering writes.

Result:

Gathering writes work with any number of buffers
2014-07-09 12:18:48 +02:00
Norman Maurer
750f023ced [#2558] Define SO_REUSEPORT if not defined
Motivation:

Currently it is impossible to build netty on linux system that not define SO_REUSEPORT even if it is supported.

Modification:

Define SO_REUSEPORT if not defined.

Result:

Possible to build on more linux dists.
2014-07-02 09:40:36 +02:00
Norman Maurer
5a6719406c [#2623] Release local references to guard against StackOverflow in JNI
Motivation:

When we do a (env*)->GetObjectArrayElement(...) call we may created many local references which will only be cleaned up once we exist the native method. Thus a lot of memory can be used and so a StackOverFlow may be triggered. Beside this the JNI specification only say that an implementation must cope with 16 local references.

Modification:

Call (env*)->ReleaseLocalRef(...) to release the resource once not needed anymore.

Result:

Less memory usage and guard against StackOverflow
2014-06-30 09:53:13 +02:00
Norman Maurer
98d2abc5cc [#2396] Allow to set TCP_KEEPIDLE, TCP_KEEPINTVL and TCP_KEEPCNT in native transport
Motivation:
Allow to set TCP_KEEPIDLE, TCP_KEEPINTVL and TCP_KEEPCNT in native transport to offer the user with more flexibility.

Modifications:
Expose methods to set these options and write the JNI implementation.

Result:
User can now use TCP_KEEPIDLE, TCP_KEEPINTVL and TCP_KEEPCNT.
2014-04-18 11:33:00 +02:00
Norman Maurer
8683e1ef3e [#2377] Implement epoll based DatagramChannel
Motivation:
There is currently no epoll based DatagramChannel. We should add one to make the set of provided channels complete and also to be able to offer better performance compared to the NioDatagramChannel once SO_REUSEPORT is implemented.

Modifications:
Add implementation of DatagramChannel which uses epoll. This implementation does currently not support multicast yet which will me implemented later on. As most users will not use multicast anyway I think it is fair to just add the EpollDatagramChannel without the support for now. We shipped NioDatagramChannel without support earlier too ...

Result:
Be able to use EpollDatagramChannel for max. performance on linux
2014-04-16 15:15:32 +02:00
Norman Maurer
d1d8a6b6cd [#2376] Add support for SO_REUSEPORT in native transport
Motivation:
In linux kernel 3.9 a new featured named SO_REUSEPORT was introduced which allows to have multiple sockets bind to the same port and so handle the accept() of new connections with multiple threads. This can greatly improve the performance when you not to accept a lot of connections.

Modifications:
Implement SO_REUSEPORT via JNI

Result:
Be able to use the SO_REUSEPORT feature when using the EpollServerSocketChannel
2014-04-16 14:38:26 +02:00
Norman Maurer
c71e9e485e [#2371] Fix Potential data corruption in EpollSocketChannel when writing to the Channel
Motivation:
We sometimes see data corruption when writing to the EpollSocketChannel.

Modifications:
Correctly update the position of the ByteBuffer after something was written.

Result:
Fix data-corruption which could happen on partial writes
2014-04-09 14:26:04 +02:00
Norman Maurer
3019f6db55 [#2361] Native.epollCreate(...) fails on systems using a kernel < 2.6.27 / glibc < 2.9
Motivation:
Native.epollCreate(...) fails on systems using a kernel < 2.6.27 / glibc < 2.9 because it uses epoll_create1(...) without checking if it is present

Modifications:
Check if epoll_create1(...) exists abd if not fall back to use epoll_create(...)

Result:
Works even on systems with kernel < 2.6.27 / glibc < 2.9
2014-04-04 07:56:11 +02:00
Aaron Riekenberg
be90418c91 [#2280] Correct logic in Native.finishConnect. Fix use of optval parameter in c getOption function. In epoll event loop, check that channel is open before processing event. 2014-03-09 19:38:57 +01:00
Norman Maurer
60b830ba89 Directly use memory addresses for gathering writes to reduce gc pressure. Part of [#2239]
This also does factor out some logic of ChannelOutboundBuffer. Mainly we not need nioBuffers() for many
transports and also not need to copy from heap to direct buffer. So this functionality was moved to
NioSocketChannelOutboundBuffer. Also introduce a EpollChannelOutboundBuffer which makes use of
memory addresses for all the writes to reduce GC pressure
2014-02-21 14:16:37 +01:00
Norman Maurer
55d0f36a61 Use optimized write and read calls if memoryAddress is present. Part of [#2239] 2014-02-17 17:29:11 +01:00
Norman Maurer
52050796e7 [#2238] Fix bug which caused a SIGSEGV when calling remoteAddress() or localAddress() 2014-02-17 12:00:12 +01:00
Norman Maurer
e0669522a3 Correctly update the ByteBuffers position on write and writev 2014-02-17 07:29:33 +01:00
Norman Maurer
e0299e1222 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:42:07 +01:00