[Last Call] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1461
  • Last Modified:

ServerSocket.accept() and SocketInputStream.read() consuming lots of cpu

      I am having performance problems with a server socket application. When I profile it I got the following strange result:

      java.net.SocketInputStream.socketRead0  55 s (49 %)  
      java.net.PlainSocketImpl.socketAccept  53 s     (46 %)
      and less than 5% for the rest of my code (~1200 java classes).

      I profile the application with only ONE connection and about 1Kbps of transmition between the server and the client.

      Why is this happening?  Is this a bug? Aren´t those functions supposed to do nothing if there are nothing to execute? The accept() function only do something useful ONE time!

       Below is the code for NetworkServer.run() that contains the accept() function:

          while(bInitialized)
          {
                try
                {
                      NetWorkServerClient client=null;
                      Socket clientSocket = socket.accept();
                      client = new NetWorkServerClient(this,clientSocket);
                      
                      if(iClientsLimit > 0 && clients.size() >= iClientsLimit)
                      {
                                      client.stopListening();
                            client = null;
                           
                            continue;
                      }
                      else
                      {
                            client.start();
                            clients.add(client);
                      }
               
                      manager.onConnect(client);
                }
                catch(InterruptedIOException e)
                {
      
                }
          }
      }

     and NetworkServerClient.run() that contains the read() function:
      while(bInitialized)
      {
            int iBytesFilled = 0;
          try
          {
                iBytesFilled = in.read(btInBuffer,0,NetWorkUtils.getMaxPacketSize());
               
                if (iBytesFilled == 0)
                      continue;
               
          }
          catch(Exception e)
          {
                logConn();
                break;
          }
          
          if(iBytesFilled>0)
          {
                byte []btData = new byte[iBytesFilled];
                for(int i=0; i<iBytesFilled; i++)
                      btData[i]=btInBuffer[i];

               
                try
                {      
                      decode(btData);
                }
                catch(Exception e)
                {
                  logConn();
                             break;
                }
          }
          else if(iBytesFilled == -1)
          {
            logConn();
                break;
          }
            
      }
      bStopped = true;

      try
      {
            notifyAll();
      }
      catch(Exception e)
      {
      }

      stopListening();
}

   Thanks for any help.
0
Binder
Asked:
Binder
  • 5
  • 5
  • 3
  • +1
1 Solution
 
Tommy BraasCommented:
It means that of the time spent in your application executing code is spent the way described in the output. I.e. you probably ran your application for 2 minutes. Of that 2 minutes 55 seconds was spent blocking on input, and 53 seconds was spent waiting for a connection. Unless it is multi-threaded, in which case you probably ran the application for one minute.
0
 
Mayank SAssociate Director - Product EngineeringCommented:
You can try the JProfiler to see the Java performance:

http://www.javaperformancetuning.com/tools/jprofiler/index.shtml

http://www.ej-technologies.com/products/jprofiler/overview.html

Make sure you are closing all sockets, streams, files, etc after you are using them.
0
 
BinderAuthor Commented:
  I know what it means, the read is inside a thread, I am using JProfiler and I close everything. My question is: is this behavior acceptable? The most part of my applicattion is taken by read and accept methods? I am losing performance!  I think that there is something wrong here, this can´t be the standard behaviour or my code is completely wrong.
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
Mayank SAssociate Director - Product EngineeringCommented:
>> is this behavior acceptable?

No.

>> The most part of my applicattion is taken by read and accept methods?

How long is your code? Can you post it?
0
 
BinderAuthor Commented:
  You mean the other classes? About 400.000 lines. No, i can´t post, sorry. But if the problem is read and accept (that are called ONLY on the code shown above) why do you want the other classes?
0
 
Tommy BraasCommented:
Increase the load on your server and see what the profiling results are, you should see an increase in time in your application code and less in the blocking calls. Have you profiled your test client?

 >> is this behavior acceptable?
>> No.
We don't know enough to make that determination yet
0
 
BinderAuthor Commented:
 I have already done this. With 100 connections the result is the same. The read and accept threads block the cpu in the same way that one connection does.
0
 
Mayank SAssociate Director - Product EngineeringCommented:
>> We don't know enough to make that determination yet

Well, but it is slow from a user's point of view, which makes it slightly unacceptable for him.
0
 
Tommy BraasCommented:
>>  I have already done this. With 100 connections the result is the same. The read and accept threads block the cpu in the same way that one connection does.
So it does behave the way it is supposed to (assuming that you mean that you get the same times distributed over 49%,46%,5%).
0
 
WebstormCommented:
Hi Binder,

Which performance results do you get if you run the server and wait for 5 minutes before making a connection with a client ? and for 10 minutes ?
If you get about 5 and 10 minutes (300 & 1200 s) for accept(), then it means that with Jperform you get the delay before the accept() method returns which is not the cpu time used.
0
 
BinderAuthor Commented:
 Yes, you are correct. But how can I profile the application if it gives me delays instead of cpu time?
0
 
Tommy BraasCommented:
>> But how can I profile the application if it gives me delays instead of cpu time?
One manual way of doing (not the best way) would be to have a running tally of how long time is spent blocking on the blocking calls and assume that no time is spent there at all.

Another way, more applicable to your case would be to ignore the time spent in the blocking state on accept(), and compare time spent in the client read() method minus the time spent in  java.net.SocketInputStream.socketRead0.
0
 
BinderAuthor Commented:
  Ok, thanks Webstorm.
0
 
Tommy BraasCommented:
:-(
0

Featured Post

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

  • 5
  • 5
  • 3
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now