www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Socket server + thread: cpu usage

reply "Tim" <timvol ymail.com> writes:
Hi guys,

I've the following snipped:

TcpSocket oSocket = new TcpSocket(AddressFamily.INET);
oSocket.bind(new InternetAddress("127.0.0.1", 12345));
oSocket.blocking(false);
oSocket.listen(0);

while(true)
{
	try
	{
		Socket oRequestSocket = oSocket.accept();

		Request oRequest = new Request(oRequestSocket);
		oRequest.start(); // Start request thread
	}
	catch (SocketAcceptException oException)
	{
		Thread.yield();
	}
}

When I execute the code above, the while(true)-loop uses nearly 
100% (1 complete cpu). When I connect to the server multiple 
times (note that each Request-Thread has it's own 
while(oRequestSocket.isAlive)-loop) the cpu usage easily reaches 
120, 130... 200 and more cpu usage.

Is there anything I'm doing wrong? I don't want use blocking 
sockets... how to handle 100 or 1000 connections when the main 
server thread already consumes 1 cpu?
Apr 29 2014
next sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Tuesday, 29 April 2014 at 17:16:33 UTC, Tim wrote:
 Is there anything I'm doing wrong?
You should be using a blocking socket. With them, the operating system will put your thread on hold until a new connection comes in. Without them, it will endlessly loop doing absolutely nothing except checking if a new connection is there yet. Horribly, horribly inefficient.
Apr 29 2014
next sibling parent reply "Tim" <timvol ymail.com> writes:
On Tuesday, 29 April 2014 at 17:19:41 UTC, Adam D. Ruppe wrote:
 On Tuesday, 29 April 2014 at 17:16:33 UTC, Tim wrote:
 Is there anything I'm doing wrong?
You should be using a blocking socket. With them, the operating system will put your thread on hold until a new connection comes in. Without them, it will endlessly loop doing absolutely nothing except checking if a new connection is there yet. Horribly, horribly inefficient.
Alright, this would solve the server-cpu-usage-problem. But what about incoming connections? When I create a new thread and use non-blocking socket I've exactly the same problem. I can also solve this problem by using blocking sockets, but what happens if I do the following: while(oMyBlockingSocket.isAlive) { oMyBlockingSocket.receive(...); } ... and close the connection on the client side? I would never receive anything and receive() waits never comes back or would this throw an exception or similar?
Apr 29 2014
parent reply "Tim" <timvol ymail.com> writes:
On Tuesday, 29 April 2014 at 17:35:08 UTC, Tim wrote:
 On Tuesday, 29 April 2014 at 17:19:41 UTC, Adam D. Ruppe wrote:
 On Tuesday, 29 April 2014 at 17:16:33 UTC, Tim wrote:
 Is there anything I'm doing wrong?
You should be using a blocking socket. With them, the operating system will put your thread on hold until a new connection comes in. Without them, it will endlessly loop doing absolutely nothing except checking if a new connection is there yet. Horribly, horribly inefficient.
Alright, this would solve the server-cpu-usage-problem. But what about incoming connections? When I create a new thread and use non-blocking socket I've exactly the same problem. I can also solve this problem by using blocking sockets, but what happens if I do the following: while(oMyBlockingSocket.isAlive) { oMyBlockingSocket.receive(...); } ... and close the connection on the client side? I would never receive anything and receive() waits never comes back or would this throw an exception or similar?
Sorry... I totally forgot... I can use SocketSet's as I already asked: http://forum.dlang.org/thread/ogghezngzrvvoqaoddbh forum.dlang.org#post-kivp3e:24jif:241:40digitalmars.com ... but I thought it's also possible using non blocking sockets by using Thread.yield().
Apr 29 2014
parent reply "Damian Day" <damianroyday gmail.com> writes:
On Tuesday, 29 April 2014 at 17:44:21 UTC, Tim wrote:
 On Tuesday, 29 April 2014 at 17:35:08 UTC, Tim wrote:
 On Tuesday, 29 April 2014 at 17:19:41 UTC, Adam D. Ruppe wrote:
 On Tuesday, 29 April 2014 at 17:16:33 UTC, Tim wrote:
 Is there anything I'm doing wrong?
You should be using a blocking socket. With them, the operating system will put your thread on hold until a new connection comes in. Without them, it will endlessly loop doing absolutely nothing except checking if a new connection is there yet. Horribly, horribly inefficient.
Alright, this would solve the server-cpu-usage-problem. But what about incoming connections? When I create a new thread and use non-blocking socket I've exactly the same problem. I can also solve this problem by using blocking sockets, but what happens if I do the following: while(oMyBlockingSocket.isAlive) { oMyBlockingSocket.receive(...); } ... and close the connection on the client side? I would never receive anything and receive() waits never comes back or would this throw an exception or similar?
Sorry... I totally forgot... I can use SocketSet's as I already asked: http://forum.dlang.org/thread/ogghezngzrvvoqaoddbh forum.dlang.org#post-kivp3e:24jif:241:40digitalmars.com ... but I thought it's also possible using non blocking sockets by using Thread.yield().
You want to add something like this to your while loop: Thread.sleep( dur!("msecs")( 20 ) ); That will give back some time to the CPU.
Apr 30 2014
parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 04/30/2014 04:24 PM, Damian Day wrote:

 Thread.sleep( dur!("msecs")( 20 ) );
Going off topic, the UFCS syntax makes that code much more readable. :) Thread.sleep(20.msecs); Ali
Apr 30 2014
prev sibling parent reply "Tim" <timvol ymail.com> writes:
On Tuesday, 29 April 2014 at 17:19:41 UTC, Adam D. Ruppe wrote:
 On Tuesday, 29 April 2014 at 17:16:33 UTC, Tim wrote:
 Is there anything I'm doing wrong?
You should be using a blocking socket. With them, the operating system will put your thread on hold until a new connection comes in. Without them, it will endlessly loop doing absolutely nothing except checking if a new connection is there yet. Horribly, horribly inefficient.
Blocking sockets are now working as expected, but I've one problem. When I do the following in my server-accept-thread: while (m_oSocket.isAlive) { oSocketSet.reset(); oSocketSet.add(m_oSocket); nAcceptedSockets = Socket.select(oSocketSet, null, null, 25.msecs); if (nAcceptedSockets > 0) { // Do something... } } ... and the following in my client: void connect() { m_oSocket = new TcpSocket(AddressFamily.INET); m_oSocket.connect(new InternetAddress("127.0.0.1", 12345)); } The CPU usage is low as long as my connect is connected. When I disconnect the client using the following few lines: void disconnect() { m_oSocket.shutdown(SocketShutdown.BOTH); m_oSocket.close(); } ... the CPU usage goes up. I think that SocketShutdown.BOTH causes Socket.select to fail which results in an endless loop. Any suggestions how to handle that problem? Ali Çehreli: Thanks, didn't know that UFCS can also handle such constructs :)
May 01 2014
next sibling parent "Tim" <timvol ymail.com> writes:
On Thursday, 1 May 2014 at 08:08:37 UTC, Tim wrote:
 On Tuesday, 29 April 2014 at 17:19:41 UTC, Adam D. Ruppe wrote:
 On Tuesday, 29 April 2014 at 17:16:33 UTC, Tim wrote:
 Is there anything I'm doing wrong?
You should be using a blocking socket. With them, the operating system will put your thread on hold until a new connection comes in. Without them, it will endlessly loop doing absolutely nothing except checking if a new connection is there yet. Horribly, horribly inefficient.
Blocking sockets are now working as expected, but I've one problem. When I do the following in my server-accept-thread: while (m_oSocket.isAlive) { oSocketSet.reset(); oSocketSet.add(m_oSocket); nAcceptedSockets = Socket.select(oSocketSet, null, null, 25.msecs); if (nAcceptedSockets > 0) { // Do something... } } ... and the following in my client: void connect() { m_oSocket = new TcpSocket(AddressFamily.INET); m_oSocket.connect(new InternetAddress("127.0.0.1", 12345)); } The CPU usage is low as long as my connect is connected. When I disconnect the client using the following few lines: void disconnect() { m_oSocket.shutdown(SocketShutdown.BOTH); m_oSocket.close(); } ... the CPU usage goes up. I think that SocketShutdown.BOTH causes Socket.select to fail which results in an endless loop. Any suggestions how to handle that problem? Ali Çehreli: Thanks, didn't know that UFCS can also handle such constructs :)
Small correction: "The CPU usage is low as long as my client is connected. When I disconnect the client using the following few lines:"
May 01 2014
prev sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Thursday, 1 May 2014 at 08:08:37 UTC, Tim wrote:
 ... the CPU usage goes up. I think that SocketShutdown.BOTH 
 causes Socket.select to fail which results in an endless loop. 
 Any suggestions how to handle that problem?
It shouldn't be here, disconnect would affect the new socket, and you're calling select on the accepting socket, which is still good to accept a new connection. What's your code look like for handing a socket returned by accept?
May 01 2014
prev sibling parent Justin Whear <justin economicmodeling.com> writes:
On Tue, 29 Apr 2014 17:16:32 +0000, Tim wrote:

 Hi guys,
 
 I've the following snipped:
 
 TcpSocket oSocket = new TcpSocket(AddressFamily.INET); oSocket.bind(new
 InternetAddress("127.0.0.1", 12345)); oSocket.blocking(false);
 oSocket.listen(0);
 
 while(true)
 {
 	try {
 		Socket oRequestSocket = oSocket.accept();
 
 		Request oRequest = new Request(oRequestSocket);
 		oRequest.start(); // Start request thread
 	}
 	catch (SocketAcceptException oException)
 	{
 		Thread.yield();
 	}
 }
 
 When I execute the code above, the while(true)-loop uses nearly 100% (1
 complete cpu). When I connect to the server multiple times (note that
 each Request-Thread has it's own while(oRequestSocket.isAlive)-loop) the
 cpu usage easily reaches 120, 130... 200 and more cpu usage.
 
 Is there anything I'm doing wrong? I don't want use blocking sockets...
 how to handle 100 or 1000 connections when the main server thread
 already consumes 1 cpu?
If you use blocking sockets, you should probably spawn a new thread for each client. If you use non-blocking sockets, you need to use poll or select to wait for incoming connections or data.
Apr 29 2014