java - 一次读socket一个字节,如何改变这个,优化

标签 java sockets buffering

我需要一些有关优化的帮助。我正在尝试改进这个用JAVA制作的开源游戏服务器。每个玩家都有自己的线程,每个线程都是这样的:

BufferedReader _in = new BufferedReader(new InputStreamReader(_socket.getInputStream()));

String packet = "";
char charCur[] = new char[1];

while(_in.read(charCur, 0, 1)!=-1)
{
    if (charCur[0] != '\u0000' && charCur[0] != '\n' && charCur[0] != '\r')
    {
        packet += charCur[0];

    }else if(!packet.isEmpty())
    {
        parsePlayerPacket(packet);
        packet = "";
    }
}

我多次被告知这段代码很愚蠢,我同意,因为在对其进行分析时,我发现读取每个字节并使用 packet += "" 附加它是愚蠢且缓慢的。

我想改进这个,但我不知道怎么做..我确信我能找到一些东西,但我担心它会比这更慢,因为我必须根据 '\u0000 来拆分数据包' 、 '\n''\r' 来解析它们。而且我知道 split 3 次是非常慢的。

有人可以给我一个主意吗?或者一段代码?这会让我很开心。

如果你要解释,请使用非常简单的语言,并附上代码示例,我只是一个JAVA初学者。谢谢

最佳答案

BufferedReader 读取大块数据,甚至一次读取一个字符,都不存在明显的性能问题。

除非您的分析已将 BufferedReader.read() 方法识别为代码中的特定热点,否则您能做的最好的事情就是使代码简单易读,而不是花时间优化它.


对于您的具体情况:

  • 是的,代码有点蹩脚,但是
  • 不,从性能角度来看,它不太可能产生很大的差异。

真正的性能瓶颈很可能是网络本身。您可以采取一些应用程序级别的措施来解决此问题,但最终您只能以端到端网络连接支持的速率发送/接收数据。


My profiling result is saying that it's coming from: BufferedReader.read(). What does it mean really?

你确定时间真的花在了Socket的read方法上吗?如果是,那么真正的问题是您的应用程序线程花费了大量时间等待网络数据包到达。如果是这种情况,那么您唯一能做的就是减少客户端和服务器端刷新的次数,以便网络不必处理如此多的小数据包。根据您的应用程序,这可能不可行。

我将按如下方式编写您的代码:

BufferedReader _in = new BufferedReader(
        new InputStreamReader(_socket.getInputStream()));

StringBuilder packet = new StringBuilder();
int ch;

while ((ch = _in.read()) != 1) {
    if (ch != '\u0000' && ch != '\n' && ch != '\r') {
        packet.append((char) ch);
    } else if (!packet.isEmpty()) {
        parsePlayerPacket(packet.toString());
        packet = new StringBuilder();
    }
}

但我认为这会对性能产生太大影响......除非“数据包”通常有数百个字符长。 (我调整的真正目的是减少读取数据包时创建的临时字符串的数量。我认为没有一种简单的方法可以让它在读取中花费更少的实时时间来电。)

关于java - 一次读socket一个字节,如何改变这个,优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7369275/

相关文章:

python - file.tell() 不一致

java - 谷歌分析 : Get access token from refresh token

java - Apache Commons ZipArchiveOutputStream 在添加带有非 ASCII 字符的文件名时中断

C 套接字 - send() 发送,recv() 不接收

c - 套接字无法连接到服务器

java - 我的 Telegram 机器人无法读取其他 Telegram 机器人发送的消息

java - 摆脱在 JUnit 窗口中显示长包名称的问题

bash - 处理通过管道传输到 netcat 的脚本的输入

html - html5中的canplaythrough事件到底是什么时候触发的?