Search code examples
javamultithreadingsocketsparsing

Optimizing a java multithreaded server that uses an inputstreamreader


I'm currently working on a project where I have to host a server which fetches an inputstream, parses the data and sends it to the database. Every client that connects to my server sends an inputstream which never stops once it is connected. Every client is assigned a socket and its own parser thread object so the server can deal with the datastream coming from the client. The parser object just deals with the incoming data and sends it to the database.

Server / parser generator:

public void generateParsers() {
    while (keepRunning) {
        try {
            Socket socket = s.accept();
            // new connection
            t = new Thread(new Parser(socket));
            t.start();
        } catch (IOException e) {
            appLog.severe(e.getMessage());
        }
    }
}

Parser thread:

   @Override
    public void run() {
        while (!socket.isClosed() && socket.isConnected()) {
            try {
                BufferedReader bufReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                String line = bufReader.readLine();
                String data = "";
                if (line == null) {
                    socket.close();
                } else if (Objects.equals(line, "<DATA")) {
                    while (!Objects.equals(line, "</DATA>")) {
                        data += line;
                        line = bufReader.readLine();
                    }
                    /*
                    Send the string that was build            
                    from the client's datastream to the database
                    using the parse() function.         
                    */
                    parse(data);
                    }
                }
            } catch (IOException e) {
                System.out.println("ERROR : " + e);
            }
        }
    }

My setup is functional but the problem is that it delivers too much stress on my server when too much clients are connected and thus too many threads are parsing data concurrently. The parsing of the incoming data and the sending of the data to the database is hardly effecting the performance at all. The bottleneck is mostly the concurrent reading of the client's datastreams from the connected clients.

Is there any way that I can optimize my current setup? I was thinking of capping the amount of connections and once a full datafile is received, parse it and move to the next client in the connection queue or something similar.


Solution

  • The bottleneck is mostly the concurrent reading

    No. The bottleneck is string concatenation. Use a StringBuffer or StringBuilder.

    And probably improper behaviour when a client disconnects. It's hard to believe this works at all. It shouldn't:

    • You should use the same BufferedReader for the life of the socket, otherwise you can lose data.
    • Socket.isClosed() and Socket.isConnected() don't do what you think they do: the correct loop termination condition is readLine() returning null, or throwing an IOException:

      while ((line = bufReader.readLine()) != null)
      

    Capping the number of concurrent connections can't possibly achieve anything if the clients never disconnect. All you'll accomplish is never listening to clients beyond the first N to connect, which can't possibly be what you want. 'Move to the next client' will never happen.