开发者

BufferedReader.read() eating 100% of CPU

开发者 https://www.devze.com 2023-04-02 03:52 出处:网络
I have a JAVA game server that uses 1 thread per TCP connection. (I know it\'s bad but i\'ll have to keep it this way for now). On a (3.2Ghz 6cor x2 machine, 24GB RAM, windows server 2003 64bits) and

I have a JAVA game server that uses 1 thread per TCP connection. (I know it's bad but i'll have to keep it this way for now). On a (3.2Ghz 6cor x2 machine, 24GB RAM, windows server 2003 64bits) and here is a piece of the code:

public void run()
{
    try
    {   
        String packet = "";
        char charCur[] = new char[1];

        while(_in.read(charCur, 0, 1)!=-1 && Server.isRunning)
        {
            if (charCur[0] != '\u0000' && charCur[0] != '\n' && charCur[0] != '\r')
            {
                packet += charCur[0];
            }else if(!packet.isEmpty())
            {
                parsePlayerPacket(packet);
                packet = "";
            }
        }

    }catch(Exception e)
    {
        e.printStackTrace();
    }
    finally
    {
        try{
            kickPlayer();
        }catch(Exception e){e.printStackTrace();};

        Server.removeIp(_ip);
    }
}

After about 12 hours or more of server upTime (and about 3.000 players connected) the server starts eating 100% of all the 12 CPUs for ever, until I manually reboot the JAVA application. So the game starts lagging verry bad and my players starts complaining.

I have tried profiling the application and here is what I came up with:

BufferedReader.read() eating 100% of CPU

So I am guessing that the problem is coming from here:

while(_in.read(charCur, 0, 1)!=-1 && Server.isRunning)

knowing that the variable "_in" is a reader of the socket input : (_in = new BufferedReader(new InputStreamReader(_socket.getInputS开发者_JAVA百科tream()))).

Why on earth _in.read() takes so much CPU after a long server upTime?

I have tried putting a Thread.sleep(1); and more inside the While loop, but doesn't do anything, I guess the problem is inside of the BufferedReader.read() method.

Does anyone have any idea of what can cause this?? And how to fix it?


This is a duplicate of your previous question: An infinite loop somewhere in my code. Please do not open up a new question, but instead use the editing functions.

That being said, 3000 threads is definitely a lot and would most likely cause excessive amounts of context switching. Instead of starting a new thread for each connection, consider using non-blocking IO facilities in Java. Examples can be found here: http://download.oracle.com/javase/1.4.2/docs/guide/nio/example/index.html


I don't know why the call is slow but I would never read one byte at a time in a tight loop. Who knows what kind of overhead the internal function has.

I would read all the data that is available currently in the stream and parse that. This would require a buffer and some extra bookkeeping but anyway faster than reading byte by byte from a stream.


'1 thread per TCP connection' 'about 3.000 players connected'

= 3.000 threads?!

My guess: the maximum amount of threads that can repeatedly copy one byte at a time is around 3.000. That doesn't sound so weird.

Solution: less threads and read more bytes in one go.

You could use a executorService. There is a simplistic example in the javadoc: http://download.oracle.com/javase/7/docs/api/java/util/concurrent/ExecutorService.html


It doesn't look like you ever close the BufferedReader either, unless you are attempting it in the kickPlayer() method.

Each reader may be living a lot longer than you realise.


I'm also stuck on this same problem, I have also tried many solutions but no luck with read(byte). But when I have tried with readLine(), it works well. @Reacen did you found any other answer please let me know too.

            public void run() {
            try {
                InputStream input = clientSocket.getInputStream();
                BufferedReader bf = new BufferedReader(new InputStreamReader(input));

                while (isRunning) {
                    if (mainServer.isStopped()) {
                        disconnect();
                    }
                    if (clientSocket.isClosed()) {
                        isRunning = false;
                        break;
                    }

                    // New Code Receive commands from device
                    String result = null;
                    try {
                        result = bf.readLine();
                        if (result == null) {
                            disconnect();
                        } else {
                            Pattern pattern = Pattern.compile("(?<=\\[).*(?=\\])");
                            Matcher matcher = pattern.matcher(result);
                            if (matcher.find()) {
                                result = matcher.group(0);
                            }
                        }
                    } catch (SocketTimeoutException e) {
                        logger.debug("Socket Read Timeout: " + remoteAddress);
                    } catch (SocketException e) {
                        isRunning = false;
                        break;
                    }
                    if (result == null || result.trim().length() == 0) {
                        continue;
                    }
0

精彩评论

暂无评论...
验证码 换一张
取 消