`
feikiss
  • 浏览: 100329 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

java socket performance investigation

阅读更多
these days I'm confused about the Tcp performance while using java socket. In fact the java code is very simple. details as below:

1. server open a port and begin to listen.
2. client request and after connect to server, client begin to write to socket.
3. after server got the request, it will open a new thread to handle this connection. (this connection is a long connection which will not time out).
4. the server will keep reading until it got the end separator, then give a response to the client and continue to keep reading again.
5. after client get the response, it will send another request again.
I find if the client write the whole message (including the end separator) one time, the communication speed is good satisfactorily, the speed can reach to 50000 messages per minute. How ever, if the client write the bytes to socket in separated times, the speed cut down quickly, just almost 1400 messages per minute, it is 1/40 times compared with the original speed. I'm quite confused about it. Then I throw out my question in the stackoverflow and get a big help from some guys. The following is my server side:

public class ServerForHelp {

    final static int BUFSIZE = 10240;
    Socket socket;
    String delimiter = "" + (char) 28 + (char) 13;

    public static void main(String[] args) throws IOException {

            ServerSocket ss = new ServerSocket(9200);
            System.out.println("begin to accept...");
            while (true) {
                Socket s = ss.accept();
                Thread t = new Thread(new SocketThread1(s));
                t.start();
            }
    }

    public String readUntilDelimiter() throws Exception {
        StringBuffer stringBuf = new StringBuffer();
        InputStream stream = socket.getInputStream();
        InputStreamReader reader = null;
        reader = new InputStreamReader(stream);

        char[] buf = new char[BUFSIZE];

        while (true) {
            int n = -1;
                n = reader.read(buf, 0, BUFSIZE);
            if (n == -1) {
                return null;  // it means the client has closed the connection, so return null.
            } else if (n == 0) {
                continue; // continue to read the data until got the delimiter from the socket.
            }

            stringBuf.append(buf, 0, n);
            String s = stringBuf.toString();

            int delimPos = s.indexOf(delimiter);
            if (delimPos >= 0) {
                // found the delimiter; return prefix of s up to separator and
                // To make the thing simple, I have discarded the content after the delimiter.
                String result = s.substring(0, delimPos);
                sendTheResponse(socket);
                return result;
            }
        }
    }

    private void sendTheResponse(Socket socket) throws IOException {
        Writer writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        writer.write("Hi, From server response");
        writer.flush();
    }

}

class SocketThread1 implements Runnable {

    Socket socket;

    public SocketThread1(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        ServerForHelp server = new ServerForHelp();
        server.socket = socket;
        while (true) {
            try {
                if (server.readUntilDelimiter() == null) // it means that the client has closed the connection, exist
                    break;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

}

It is a normal socket programming.
and the following is my client side:
public void execute() throws Exception{

        int msgCnt = 0;
        Socket socket = null;
        byte[] bufBytes = new byte[512];
        long start = 0;
        final char START_MESSAGE = 0x0B;
        final char END_MESSAGE = 0x1C;
        final char END_OF_RECORD = 0x0D;//\r
        String MESSAGE = "HELLO, TEST";
        socket = new Socket("192.168.81.39", 9200);
        OutputStream os = socket.getOutputStream();
        InputStream is = socket.getInputStream();

        while (System.currentTimeMillis() - start < 60000)
        {

            // If you send the total message at one time, the speed will be improved significantly  

            // FORMAT 1
            StringBuffer buf = new StringBuffer();
            buf.append(START_MESSAGE);
            buf.append(MESSAGE);
            buf.append(END_MESSAGE);
            buf.append(END_OF_RECORD);
            os.write(buf.toString().getBytes());
            // FORMAT 1 END

            //FORMAT 2
//        os.write(START_MESSAGE);
//        os.write(MESSAGES[port].getBytes());
//        os.write(END_MESSAGE);
//        os.write(END_OF_RECORD);
            //FORMAT 2 END
            os.flush();
            is.read(bufBytes);
            msgCnt++;

            System.out.println(msgCnt);
        }
        System.out.println( msgCnt + " messages per minute");
    }


If I use the "FORMAT 1", to send the message, the speed could reach to 50000 messages per minute, but If use "FORMAT 2", the speed is down to 1400 messages per minute.

And the following is the response I got from stackoverflow:

Multiple very short writes to a socket in rapid succession followed by a read can trigger a bad interaction between Nagle's algorithm and TCP delayed acknowledgment; even if you disable Nagle's algorithm, you'll cause an entire packet to be sent per individual write call (with 40+ bytes of overhead, whether the write is one byte or a thousand).

Wrapping a BufferedOutputStream around the socket's output stream should give you performance similar to "FORMAT 1" (precisely because it holds things in a byte array until it fills or is flushed).

As John Nagle explained on Slashdot:

The user-level solution is to avoid write-write-read sequences on sockets. write-read-write-read is fine. write-write-write is fine. But write-write-read is a killer. So, if you can, buffer up your little writes to TCP and send them all at once.

===end
With this answer, I'm more clear about the TCP socket now and the performance issue has been resolved too.
0
1
分享到:
评论
2 楼 feikiss 2013-07-18  
wuchsh2013 写道
英文水平很牛逼。

不敢当。。。小儿科- -
1 楼 wuchsh2013 2013-07-17  
英文水平很牛逼。

相关推荐

    Java.EE.7.Performance.Tuning.and.Optimization.178217642X

    Learn to plan a performance investigation in enterprise applications Build a performance troubleshooting strategy Design and implement high performing Java enterprise applications In Detail With the ...

    TEMS Investigation 使用说明.docx

    《TEMS Investigation 16 使用说明》文档详细介绍了如何安装和使用华为的TEMS Investigation 16软件,这是一款用于移动通信网络测试和分析的专业工具。文档特别强调了相较于旧版本15.3,16版修复了一系列重要的问题...

    TEMS Investigation 14.2 Release Note

    在本文档TEMS Investigation 14.2 Release Note中,我们主要关注TEMS Investigation 14.2版本的新功能和特性,同时也会详细介绍一些具体的操作步骤和应用场景。 首先,TEMS Investigation 14.2版本新增了对Sharp ...

    TEMS_Investigation__7.1中文说明书

    《TEMS Investigation 7.1中文说明书》是一个关键的资源,它详细介绍了Telecommunications Engineer's Mobile System (TEMS) Investigation工具的7.1版本。TEMS Investigation是移动网络测试和分析的重要工具,广泛...

    Tems Investigation测试软件说明书

    **TEMS Investigation测试软件说明书** **1. 前言** 在我们的项目部门新引入了TEMS Investigation测试软件,为了确保团队能够有效地使用这一高级工具,本说明书将详细介绍软件的安装、配置和基本操作。TEMS ...

    opti-scan+Investigation+7.4.3.0

    "Opti-scan Investigation 7.4.3.0" 是一款由欧佩泰斯(可能是指一家专注于光学扫描或检测技术的公司)开发的专业软件工具。这款软件主要用于光学扫描和调查,它提供了高级的图像处理和分析功能,旨在帮助用户在多个...

    Topology Investigation for DCDC Power Conversion for Distributed Power System

    本文主要讨论了分布式电力系统中直流变换(DC/DC转换器)的拓扑研究,特别是在前端转换器中的LLC转换器应用。随着超大规模集成电路(VLSI)技术的快速发展,小型化、高性能的数字系统越来越常见。...

    Numerical Investigation

    标题中的“Numerical Investigation”指的是数值模拟研究,这是一种在计算机上使用数学模型和算法来模拟物理现象的方法。在IT行业中,数值模拟广泛应用于解决复杂的工程问题,特别是在流体力学、热力学、电磁学等...

    David Marr - 1982 - Vision:A Computational Investigation into the Huma.pdf

    《Vision:A Computational Investigation into the Human Representation and Processing of Visual Information》,计算机视觉奠基之作

    Dissertation-Investigation of High-density Integrated Solution for AC-DC Convers

    本篇论文主要研究了在电信和计算机应用领域,如何实现高密度集成的AC-DC转换解决方案,以满足分布式电源系统(DPS)的需求。文章详细探讨了LLC谐振转换器的设计,以及如何通过提高功率密度来优化前端AC/DC转换器。...

    TEM/EDX investigation on adsorption of Pb on soil mineral components

    TEM与EDX方法在土壤矿物对Pb吸附方面的应用,王思源,卢升高,本研究采用透射电镜(TEM)和X射线能谱(EDX)研究两种土壤(潮软土和网纹湿老成土)中不同矿物对铅(Pb)的吸附,用选区电子衍射(SEAD

    AS-IS_Investigation-SD_Module

    根据给定文件的信息,我们可以深入探讨AS-IS调查SD(销售与分销)模块的关键知识点,以及在实施SAP项目时所涉及的重要概念。 ### 核心知识点解析 #### 1.... AS-IS调查SD模块是SAP项目实施过程中的一个关键阶段,主要...

    ERICSSON TEMS Investigation 10.0 使用培训

    TEMS是目前世面上最全面的无线网络优化产品解决...TEMS Investigation 10.0 概述 TEMS Investigation 10.0的使用介绍 TEMS Investigation 10.0 Data Collection(前台) TEMS Investigation 10.0 Route Analysis(后台)

    Raman scattering investigation of calcium tetraboride

    钙硼化合物作为一类有趣的材料,在材料科学研究中具有重要意义,特别是钙四硼化物(CaB4)因其优异的物理性质和潜在的应用价值而受到关注。韩宪越、于栋利和刘忠源的研究团队在对CaB4的拉曼散射研究中,应用群论和...

    Investigation on microwave photonic filter group delay performance

    Investigation on the group delay performance of microwave photonic filters is presented. Analysis and simulation results show symmetrical distribution on the delayed optical signals in the impulse ...

    interface of llvm investigation

    在这个“interface of llvm investigation”中,我们将深入探讨LLVM的接口设计,包括中间表示(IR)、选项(Option)、pragma指令以及后端(Backend)等方面。 1. **中间表示(IR)**:LLVM IR是LLVM的核心组成部分...

    Investigation加密狗

    Investigation加密狗破解插件

Global site tag (gtag.js) - Google Analytics