Opened 9 years ago

Last modified 8 years ago

#666 assigned enhancement

i2ptunnel uses un-buffered socket streams

Reported by: Zlatin Balevsky Owned by: sponge
Priority: trivial Milestone:
Component: apps/i2ptunnel Version: 0.9
Keywords: performance profiling Cc:
Parent Tickets: Sensitive: no


When using SocketInputStream? every read, even if it's for a single byte will issue a system call. This can increase cpu usage a lot.

KillYourTV profiled his busy router with jvisualvm and looking through the results here http://killyourtv.i2p/tmp/zab/1342955097788.nps.gz

One of the low-hanging fruits that can be picked without side effects is suggested below. I'm not wrapping the output stream because that can have side-effects of delaying small writes.

# old_revision [0c106e0035abfbeb930e77608666b9ce971d152d]
# patch "apps/i2ptunnel/java/src/net/i2p/i2ptunnel/"
#  from [8e4c0e7830ef6086e24779a7cd43dcde95b87276]
#    to [d0dccc96cb89e49d065bf691ca063854d09316e0]
--- apps/i2ptunnel/java/src/net/i2p/i2ptunnel/      8e4c0e7830ef6086e24779a7cd43dcde95b87276
+++ apps/i2ptunnel/java/src/net/i2p/i2ptunnel/      d0dccc96cb89e49d065bf691ca063854d09316e0
@@ -3,6 +3,7 @@ package net.i2p.i2ptunnel;
 package net.i2p.i2ptunnel;
@@ -130,7 +131,7 @@ public class I2PTunnelRunner extends I2P
         return startedOn;
-    protected InputStream getSocketIn() throws IOException { return s.getInputStream(); }
+    protected InputStream getSocketIn() throws IOException { return new BufferedInputStream(s.getInputStream()); }
     protected OutputStream getSocketOut() throws IOException { return s.getOutputStream(); }


Change History (6)

comment:1 Changed 9 years ago by Zlatin Balevsky

Priority: minortrivial

comment:2 Changed 9 years ago by zzz

Milestone: 0.9.2
Owner: set to zzz
Status: newaccepted

Yes, needs to be fixed, but can't do it quite like that. I'll go through and fix up a few places where this is needed - including I2CP.

I probably won't fix BOB and SAM though.

comment:3 Changed 9 years ago by zzz

more info and .nps howto from irc:

<zab_> visualvm will start a gui, just type jvisualvm
<zab_> then the top left icon "load snapshot"
<zab_> then in the drop-down menu "Profiler Snapshots (*.nps, *.npss)"
<KillYourTV> <+zab_> I think he was having lots of client tunnels because of seedless/snark or some other client app, and the cpu usage was caused by system calls to blocking i/o ←- yes, this
<zab_> with me so far? when the snapshot loads, click on the "Hot Spots" tab
<zab_> sort in descending order the "Self Time (CPU)" column
<zab_> the top line will be SocketInputStream?.read()
<zab_> right-click on that and "show backtraces"
<zab_> then drill down the trace with the highest # of invocations which will expand to something from neodatis (seedless?)
<zab_> looking through the i2pclient tunnel code it does a blocking read into a 4k buffer, whereas the default size for the BufferedInputStream? buffer is 8k
<zab_> so wrapping just cuts the number of system calls in half, hence this ticket is nothing special

comment:4 Changed 9 years ago by zzz

Owner: changed from zzz to sponge
Status: acceptedassigned

EepGet?, SSLEepGet, I2CP (both sides), I2PTunnelRunner, and I2PTunnelHTTPServer.CompressedRequestor? fixed in 0.9.1-3.

Reassigning to sponge to fix BOB's

comment:5 Changed 9 years ago by sponge already uses 8192 byte reads. What would the advantage be, if any?

comment:6 Changed 8 years ago by str4d

Milestone: 0.9.2
Note: See TracTickets for help on using tickets.