From 54b367b153942d25c5b380343f5aed99c0919305 Mon Sep 17 00:00:00 2001
From: zzz <zzz@mail.i2p>
Date: Thu, 23 Aug 2012 19:08:45 +0000
Subject: [PATCH]  * NTCP: Reduce lock contention

---
 .../net/i2p/router/transport/ntcp/Reader.java | 12 ++++++---
 .../net/i2p/router/transport/ntcp/Writer.java | 26 ++++++++++++-------
 2 files changed, 24 insertions(+), 14 deletions(-)

diff --git a/router/java/src/net/i2p/router/transport/ntcp/Reader.java b/router/java/src/net/i2p/router/transport/ntcp/Reader.java
index 963f6b8f63..68480538aa 100644
--- a/router/java/src/net/i2p/router/transport/ntcp/Reader.java
+++ b/router/java/src/net/i2p/router/transport/ntcp/Reader.java
@@ -3,6 +3,8 @@ package net.i2p.router.transport.ntcp;
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Set;
 
@@ -20,7 +22,7 @@ class Reader {
     private final RouterContext _context;
     private final Log _log;
     // TODO change to LBQ ??
-    private final List<NTCPConnection> _pendingConnections;
+    private final Set<NTCPConnection> _pendingConnections;
     private final Set<NTCPConnection> _liveReads;
     private final Set<NTCPConnection> _readAfterLive;
     private final List<Runner> _runners;
@@ -28,7 +30,7 @@ class Reader {
     public Reader(RouterContext ctx) {
         _context = ctx;
         _log = ctx.logManager().getLog(getClass());
-        _pendingConnections = new ArrayList(16);
+        _pendingConnections = new LinkedHashSet(16);
         _runners = new ArrayList(8);
         _liveReads = new HashSet(8);
         _readAfterLive = new HashSet(8);
@@ -60,7 +62,7 @@ class Reader {
             if (_liveReads.contains(con)) {
                 _readAfterLive.add(con);
                 already = true;
-            } else if (!_pendingConnections.contains(con)) {
+            } else {
                 _pendingConnections.add(con);
             }
             _pendingConnections.notifyAll();
@@ -99,7 +101,9 @@ class Reader {
                             if (_pendingConnections.isEmpty()) {
                                 _pendingConnections.wait();
                             } else {
-                                con = _pendingConnections.remove(0);
+                                Iterator<NTCPConnection> iter = _pendingConnections.iterator();
+                                con = iter.next();
+                                iter.remove();
                                 _liveReads.add(con);
                             }
                         }
diff --git a/router/java/src/net/i2p/router/transport/ntcp/Writer.java b/router/java/src/net/i2p/router/transport/ntcp/Writer.java
index c414d80de8..521b41a0f8 100644
--- a/router/java/src/net/i2p/router/transport/ntcp/Writer.java
+++ b/router/java/src/net/i2p/router/transport/ntcp/Writer.java
@@ -1,7 +1,11 @@
 package net.i2p.router.transport.ntcp;
 
 import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
 import java.util.List;
+import java.util.Set;
 
 import net.i2p.router.RouterContext;
 import net.i2p.util.I2PThread;
@@ -15,17 +19,17 @@ import net.i2p.util.Log;
  */
 class Writer {
     private final Log _log;
-    private final List<NTCPConnection> _pendingConnections;
-    private final List<NTCPConnection> _liveWrites;
-    private final List<NTCPConnection> _writeAfterLive;
+    private final Set<NTCPConnection> _pendingConnections;
+    private final Set<NTCPConnection> _liveWrites;
+    private final Set<NTCPConnection> _writeAfterLive;
     private final List<Runner> _runners;
     
     public Writer(RouterContext ctx) {
         _log = ctx.logManager().getLog(getClass());
-        _pendingConnections = new ArrayList(16);
+        _pendingConnections = new LinkedHashSet(16);
         _runners = new ArrayList(5);
-        _liveWrites = new ArrayList(5);
-        _writeAfterLive = new ArrayList(5);
+        _liveWrites = new HashSet(5);
+        _writeAfterLive = new HashSet(5);
     }
     
     public void startWriting(int numWriters) {
@@ -58,15 +62,15 @@ class Writer {
                     _writeAfterLive.add(con);
                 }
                 already = true;
-            } else if (!_pendingConnections.contains(con)) {
-                _pendingConnections.add(con);
-                pending = true;
+            } else {
+                pending = _pendingConnections.add(con);
             }
             _pendingConnections.notifyAll();
         }
         if (_log.shouldLog(Log.DEBUG))
             _log.debug("wantsWrite: " + con + " already live? " + already + " added to pending? " + pending + ": " + source);
     }
+
     public void connectionClosed(NTCPConnection con) {
         synchronized (_pendingConnections) {
             _writeAfterLive.remove(con);
@@ -98,7 +102,9 @@ class Writer {
                                     _log.debug("Done writing, but nothing pending, so wait");
                                 _pendingConnections.wait();
                             } else {
-                                con = _pendingConnections.remove(0);
+                                Iterator<NTCPConnection> iter = _pendingConnections.iterator();
+                                con = iter.next();
+                                iter.remove();
                                 _liveWrites.add(con);
                                 if (_log.shouldLog(Log.DEBUG))
                                     _log.debug("Switch to writing on: " + con);
-- 
GitLab