Find the answer to your Linux question:
Results 1 to 3 of 3
I am implementing a proxy server in c++. It is multithreaded(posix). Used CPU : Xeon(8core) Thread number : 8 One main thread, and other 7 thread created by the main ...
Enjoy an ad free experience by logging in. Not a member yet? Register.
  1. #1
    Just Joined!
    Join Date
    Apr 2011
    Posts
    1

    How to increase Multi Threaded Server Proficiency


    I am implementing a proxy server in c++. It is multithreaded(posix).

    Used CPU : Xeon(8core)

    Thread number : 8

    One main thread, and other 7 thread created by the main thread.

    The main thread always listen to ports. When the main thread gets a client data it push the request in a queue[there are one queue(total 7) for each thread] based on ip and then give a signal to the appropriate thread. Then that thread gets the request from it's queue and process data and then forward the data to a appropriate destination. There is another important thing, I assign each thread excluding the main thread to individual core by using affinity.The main thread listens to 5 ports.



    Test environment: We run the server. The client sends audio data at a particular rate.



    Problems:

    1. The main thread CPU usage gets overloaded (above 80%) after a certain load from client.

    2. Other cores remain about 0-10%.


    The thing is that we want to distribute the load among all the cores equally by multithreading. But how can we do this ? Can the listening task of ports also be distributed ? I need an efficient algorithm for load balancing among threads.


    The data sent and receive rate of server is about 8.5MB/s. How can we improve this ?

    We are using gigabit LAN card.

    When the server only receive data from client it can receive data above 80MB/s. But when it both receives and sends data simultaneously it only manage upto 8.5MB/s. Why is this happening ?


    Help needed badly

    Thanks

  2. #2
    Linux Newbie
    Join Date
    Dec 2010
    Posts
    146
    I suggest you try the 'portage and programming' category of Gentoo forums.

  3. #3
    Just Joined!
    Join Date
    Mar 2011
    Location
    NH
    Posts
    14

    Why are you using so many threads

    Please take this as constructive, which is how I intend it

    One uses threads when it is expected that processing will have to stop and wait and you want to do other processing in the meantime. For a proxy server, your design doesn't really compute.

    In the "bad old days" (the mid 90s), people built TCP servers (which is really all a proxy server is) and spun a thread for every connection. This simply won't scale. To service 500 connections you need 500 threads.

    Your design doesn't make any sense to me. Seven queues with 7 threads? For what purpose? Some suggestions;

    1) You don't need a "queue". You just need to keep an array of socket descriptors.
    2) You only need 2 threads; 1 to listen for connections via "select" and "accept" them. This thread should then lock the array of socket descriptors as it adds the new connection.
    3) The 2nd thread should use "select" on readfds, writefds (and exceptfds for OOB data, which is doubtful). It then can sit on "select" and check the fds and service I/O for any sockets that require it.

    That's it. 1 gigabit, even if saturated, will not overwhelm a single thread running at full speed.

    As for your main thread taking so much CPU, set the timeout value in "select" to something like 1 second. Then use FDISSET to see if you have a connection. If someone does connect, it won't timeout so don't worry about it. I suspect your timeout value is NULL.

    Something like this:

    Code:
     
        SOCKET hTemp;
        struct sockaddr sAddr;
        socklen_t iLen;
        fd_set readsets;
        int nReturn;
    
        struct timeval sTv;
        long iTOSec = 1;
    
        while(TRUE)
        { // Accept a connection
            iLen = sizeof (sAddr);
            // Clear sets
            FD_ZERO(&readsets);
            FD_SET(sSocket, &readsets);
            sTv.tv_sec = iTOSec;
            sTv.tv_usec = 0;
            try
            {
                nReturn = ::select(sSocket + 1, &readsets, NULL, NULL, &sTv);
            }
            catch(...)
            {
                nReturn = SOCKET_ERROR;
            }
    
            if (nReturn == SOCKET_ERROR)
                return (FALSE);
    
            nReturn = FD_ISSET(sSocket, &readsets);
    
            // We have data
            if (!nReturn)
                continue;
    
            try
            {
                hTemp = ::accept(sSocket, &sAddr, &iLen);
            }
            catch(...)
            {
                hTemp = INVALID_SOCKET;
            }
    
            if (INVALID_SOCKET == hTemp)
                return (FALSE);
    
            PASS THE SOCKET TO THE CONNECTION THREAD HERE.  PROTECT WITH A MUTEX
            // Start the socket servicing the client
            ServiceConnection(hTemp);
    
    
            hTemp = INVALID_SOCKET; // Reset
        };
    Last edited by rabinnh; 04-30-2011 at 10:04 PM. Reason: Spelling

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •