我代码中的某个无限循环 [英] An infinite loop somewhere in my code

查看:108
本文介绍了我代码中的某个无限循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个Java游戏服务器,可处理多达3,000个tcp连接,每个播放器或每个tcp连接都有自己的线程,每个线程都是这样的:

I have this Java game server that handles up to 3,000 tcp connections, each player, or each tcp connection has its own thread, each thread goes something like this:

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

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

        kickPlayer();

    }catch(IOException e)
    {
        kickPlayer();
    }catch(Exception e)
    {
        kickPlayer();
    }
    finally
    {
        try{
            kickPlayer();
        }catch(Exception e){};

        MainServer.removeIP(ip);
    }
}

代码运行正常,我知道每个线程对于每个玩家来说都是一个坏主意,但我现在也会这样做。服务器在快速机器上运行良好(6cor x2,64bits,24GB RAM,Windows Server 2003)。

The code runs fine, and I know that each thread for each player is a bad idea, but I'll have too keep it this way for now. The server runs fine on a fast machine (6cor x2, 64bits, 24GB RAM, Windows Server 2003).

但在某些时候,在UpTime约12小时后,服务器开始在某个地方循环...我知道,因为java进程无限地占用了99%的CPU,直到下次重启。
而且我很难分析应用程序,因为我不想打扰玩家。我使用的探查器(visualvm)总是最终破坏服务器而不告诉我哪里出了问题。

But at some point, after about 12 hours of UpTime, the server starts to loop somewhere... I know that because the java process takes 99% of the CPU infinitely until the next reboot. And I'm having hard time to profile the application because I don't want to disturb the players. The profiler I use (visualvm) always end up chashing the server without telling me where's the problem.

无论如何,在上面那段代码中我想可能问题来自于:

Anyways, in that piece of code above I think maybe the problem comes from this:

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

_in 是客户端套接字的 BufferedReader )。

(the _in is a BufferedReader of the client's socket).

_in.read()是否有可能无限返回其他东西,这将使我的代码运行并占用99%的资源?我的代码有问题吗?我不明白一切,我只写了一半。

Is it possible that _in.read() can return something else infinitely that will keep my code runing and taking 99% of ressources? Is there something wrong with my code? I don't understand everything, I only wrote half of it.

推荐答案

一次读取一个字符几乎与使用+ =构建字符串一样慢。我无法告诉你哪个更糟糕。如果单个连接使用这种方法绑定整个核心,我不会感到惊讶。

Reading one char at a time is almost as slow as building a String with +=. I wouldn't be able to tell you which is worse. It wouldn't surprise me if a single connection tied an entire core using this approach.

最简单的修复是使用BufferedReader和StringBuilder。

The simplest "fix" to do would be to use a BufferedReader and a StringBuilder.

然而,读取数据的最有效方法是将字节读入ByteBuffer并解析行。我假设您正在接收ASCII文本。你可以编写解析器,以便能够在一个阶段处理内容和行尾(即一次传递数据)

However the most efficient way to read data is to read bytes, into a ByteBuffer and parse the "lines". I assume you are receiving ASCII text. You could write the parser to be able to process the content and the end of line in one stage (ie with one pass of the data)

使用最后一种方法,这里是我从套接字解析XML消息并以XML回复的示例(包括代码)。典型的延迟为16微秒,吞吐量为每秒264K。

Using the last approach, here is an example (including code) of where I am parsing an XML message from a socket and replying in XML. The typical latency was 16 micro-seconds and the throughput was 264K per second.

http://vanillajava.blogspot.com/2011/07/send-xml-over-socket-fast.html

你可以做类似以下的事情,这可能足够快

You can do something like the following which likely to be fast enough

BufferedReader br = new BufferedReader(_in);
for(String line; ((line = br.readline()) != null;) {
    if(line.indexOf('\0') >= 0)
       for(String part: line.split("\0"))
          parsePlayerPacket(part);
    else
       parsePlayerPacket(line);
}

如果你发现这个解决方案很简单并且熟悉ByteBuffer,你可以考虑使用它们。

If you find this solution dead simple and you are familiar with ByteBuffer you might consider using those.

这篇关于我代码中的某个无限循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆