From 593d9bf35a8c0ea3789136224480a1ac320b853e Mon Sep 17 00:00:00 2001 From: "PSp..om" Date: Sat, 16 Apr 2011 03:51:43 +0000 Subject: [PATCH] UDP-based kernel now does its writes on a background thread. Most of the time UDP packets go right out but not always... depending on the network layer it can take a couple of milliseconds. And that's alot when you're blasting packets out to a dozen users 20 times a second. git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@7245 75d07b2b-3a1a-0410-a2c5-0572b91ccdca --- .../jme3/network/kernel/udp/UdpEndpoint.java | 9 +++- .../jme3/network/kernel/udp/UdpKernel.java | 48 ++++++++++++++++++- 2 files changed, 54 insertions(+), 3 deletions(-) diff --git a/engine/src/networking/com/jme3/network/kernel/udp/UdpEndpoint.java b/engine/src/networking/com/jme3/network/kernel/udp/UdpEndpoint.java index 872a7cb92..7a99c57ba 100644 --- a/engine/src/networking/com/jme3/network/kernel/udp/UdpEndpoint.java +++ b/engine/src/networking/com/jme3/network/kernel/udp/UdpEndpoint.java @@ -114,10 +114,17 @@ public class UdpEndpoint implements Endpoint if( !isConnected() ) { throw new KernelException( "Endpoint is not connected:" + this ); } + + try { DatagramPacket p = new DatagramPacket( data.array(), data.position(), data.remaining(), address ); - socket.send(p); + + // Just queue it up for the kernel threads to write + // out + kernel.enqueueWrite( this, p ); + + //socket.send(p); } catch( IOException e ) { throw new KernelException( "Error sending datagram to:" + address, e ); } diff --git a/engine/src/networking/com/jme3/network/kernel/udp/UdpKernel.java b/engine/src/networking/com/jme3/network/kernel/udp/UdpKernel.java index 728d4c171..1ed8fbc2b 100644 --- a/engine/src/networking/com/jme3/network/kernel/udp/UdpKernel.java +++ b/engine/src/networking/com/jme3/network/kernel/udp/UdpKernel.java @@ -37,6 +37,8 @@ import java.net.*; import java.nio.ByteBuffer; import java.util.*; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Executors; +import java.util.concurrent.ExecutorService; import java.util.concurrent.atomic.AtomicBoolean; import java.util.logging.Level; import java.util.logging.Logger; @@ -57,6 +59,8 @@ public class UdpKernel extends AbstractKernel private InetSocketAddress address; private HostThread thread; + private ExecutorService writer = Executors.newFixedThreadPool(2); + // The nature of UDP means that even through a firewall, // a user would have to have a unique address+port since UDP // can't really be NAT'ed. @@ -104,6 +108,7 @@ public class UdpKernel extends AbstractKernel try { thread.close(); + writer.shutdown(); thread = null; } catch( IOException e ) { throw new KernelException( "Error closing host connection:" + address, e ); @@ -120,8 +125,13 @@ public class UdpKernel extends AbstractKernel if( reliable ) throw new UnsupportedOperationException( "Reliable send not supported by this kernel." ); - // We ignore the copy flag because we know all outbound traffic - // goes instantly. + if( copy ) + { + // Copy the data just once + byte[] temp = new byte[data.remaining()]; + System.arraycopy(data.array(), data.position(), temp, 0, data.remaining()); + data = ByteBuffer.wrap(temp); + } // Hand it to all of the endpoints that match our routing for( UdpEndpoint p : socketEndpoints.values() ) { @@ -177,6 +187,40 @@ public class UdpKernel extends AbstractKernel addEnvelope( env ); } + protected void enqueueWrite( Endpoint endpoint, DatagramPacket packet ) + { + writer.execute( new MessageWriter(endpoint, packet) ); + } + + protected class MessageWriter implements Runnable + { + private Endpoint endpoint; + private DatagramPacket packet; + + public MessageWriter( Endpoint endpoint, DatagramPacket packet ) + { + this.endpoint = endpoint; + this.packet = packet; + } + + public void run() + { + // Not guaranteed to always work but an extra datagram + // to a dead connection isn't so big of a deal. + if( !endpoint.isConnected() ) { + return; + } + + try { + thread.getSocket().send(packet); + } catch( Exception e ) { + KernelException exc = new KernelException( "Error sending datagram to:" + address, e ); + exc.fillInStackTrace(); + reportError(exc); + } + } + } + protected class HostThread extends Thread { private DatagramSocket socket;