Why does Java's socket.connect() consume 100% cpu resources?
I created a threadpool and gave it 50 tasks to connect to a server. So once it was done connecting, sending some data over, then disconnecting. It also has a read timeout set at 5 seconds (5000 long of course). I even set the thread pool to a max size of 1. I then fire this up, on linux, and ran htop (a better version of top) to check the CPU usage. I consistently saw one of my cores (2 core machine) at 100% the entire time. I profiled this with hprof (-agentlib:hprof=cpu=samples,interval=20,depth=3
) and had socket.connect() at 99%.
Here is what i find weird, isn't the point of blocking IO to block (hence wait) ? My JDK is (from java -version
):
Open开发者_如何学CJDK Runtime Environment (IcedTea6 1.6.1) (6b16-1.6.1-3ubuntu3)
OpenJDK Server VM (build 14.0-b16, mixed mode)
Update1: this same problem occurs on Sun's JVM too:
java -version
Java version "1.6.0_20"
Update2: This is due to the doConnect method which is native. Anyone know how I can view the source for this native/C code?
Update3: I logged into windows to write the code and test it. It worked fine, no CPU resources being hosed. I log back into linux, and now the problem is still here, but not as sever as to hose the entire CPU core at 100% for just 1 connect.... Here is the code:
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Vector;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class SocketTest {
public static void main(String[] args) {
new SocketTest();
}
public SocketTest() {
ThreadPoolExecutor tpe = (ThreadPoolExecutor) Executors.newFixedThreadPool(40);
Vector<Callable<Object>> tasks = new Vector<Callable<Object>>();
for (int i = 0; i < 1500; i++)
tpe.submit(new Thread() {
public void run() {
byte[] ip = { 74, 125, 19, (byte)((Math.random()*253)+1)};
Socket socket = new Socket();
try {
System.out.println("new thread: "+ip[3]);
socket.connect(new InetSocketAddress(InetAddress.getByAddress(ip), 80), 3000);
socket.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
//no need to print
}
}
});
try {
tpe.invokeAll(tasks);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System.out.println("test");
try {
//too lazy to write actual code to wait for task completness...
tpe.awaitTermination(9001, TimeUnit.DAYS);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("test2");
}
}
I just wanted to comment that it looks like you are abusing the thread-pool, since you actually instantiate new objects of type Thread 1500 times, only to pass them to a thread-pool that instantiates more threads in order to run your tasks. What you should normally do is instantiate a Runnable and let the thread-pool do it's job. I'm not saying this is what causes the CPU to choke, but it surly is a problem.
Putting aside the design issues with the code (for example, tasks
is never really used), I could not reproduce the high CPU usage on either Windows or Ubuntu (12.04.2 LTS
).
Can you please upgrade your JDK
to 1.7 (sudo apt-get install openjdk-7-jdk
) and let me know which version of the JDK
you are using? Mine is javac 1.7.0_25
, for example (got using javac -version
)
I will try to dig up further after that...
精彩评论