0

CPU オーバーヘッドを増加させる 2 つのスレッドがあります。1. ソケットから同期的に読み取る。2. 他のクライアントからの接続を受け入れるのを待っています

問題 1、クライアントからのデータを読み込もうとしていますが、readline を使用できません。着信データには、メッセージのヘッダーの終わりを知るためにマークする改行が含まれているためです。だから私はスレッドでその方法を使用していますが、CPUオーバーヘッドが増加します

 public static String convertStreamToString(TCPServerConnectionListner socket) throws UnsupportedEncodingException, IOException, InterruptedException {

        BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getSocket().getInputStream()));
        // At this point it is too early to read. So it most likely return false
        System.out.println("Buffer Reader ready? " + reader.ready());
        // StringBuilder to hold the response
        StringBuilder sb = new StringBuilder();
        // Indicator to show if we have started to receive data or not
        boolean dataStreamStarted = false;
        // How many times we went to sleep waiting for data
        int sleepCounter = 0;
        // How many times (max) we will sleep before bailing out
        int sleepMaxCounter = 5;
        // Sleep max counter after data started
        int sleepMaxDataCounter = 50;
        // How long to sleep for each cycle
        int sleepTime = 5;
        // Start time
        long startTime = System.currentTimeMillis();
        // This is a tight loop. Not sure what it will do to CPU
        while (true) {
            if (reader.ready()) {
                sb.append((char) reader.read());
                // Once started we do not expect server to stop in the middle and restart
                dataStreamStarted = true;
            } else {
                Thread.sleep(sleepTime);
                if (dataStreamStarted && (sleepCounter >= sleepMaxDataCounter)) {
                    System.out.println("Reached max sleep time of " + (sleepMaxDataCounter * sleepTime) + " ms after data started");
                    break;
                } else {
                    if (sleepCounter >= sleepMaxCounter) {
                        System.out.println("Reached max sleep time of " + (sleepMaxCounter * sleepTime) + " ms. Bailing out");
                        // Reached max timeout waiting for data. Bail..
                        break;
                    }
                }
                sleepCounter++;
            }

        }
        long endTime = System.currentTimeMillis();

        System.out.println(sb.toString());
        System.out.println("Time " + (endTime - startTime));

        return sb.toString();
    }

問題 2、それを行うための最良の方法がわかりません。他のクライアントを常に待機し、それを受け入れるスレッドを持っているだけです。ただし、これには多くの CPU オーバーヘッドも必要です。

 // Listner to accept any client connection
    @Override
    public void run() {

        while (true) {
            try {
                mutex.acquire();
                if (!welcomeSocket.isClosed()) {
                    connectionSocket = welcomeSocket.accept();
                   // Thread.sleep(5);
                }


            } catch (IOException ex) {
                Logger.getLogger(TCPServerConnectionListner.class.getName()).log(Level.SEVERE, null, ex);
            } catch (InterruptedException ex) {
                Logger.getLogger(TCPServerConnectionListner.class.getName()).log(Level.SEVERE, null, ex);
            }
            finally
            {
                mutex.release();
            }

        }
    }
}

プロファイラーの画像も役に立ちますが、なぜ SwingWorker スレッドにそれほど時間がかかるのでしょうか? ここに画像の説明を入力

問題 1 のコードを更新します。

    public static String convertStreamToString(TCPServerConnectionListner socket) throws UnsupportedEncodingException, IOException, InterruptedException {

            byte[] resultBuff = new byte[0];
            byte[] buff = new byte[65534];
            int k = -1;
            k = socket.getSocket().getInputStream().read(buff, 0, buff.length);
                byte[] tbuff = new byte[resultBuff.length + k]; // temp buffer size = bytes already read + bytes last read
                System.arraycopy(resultBuff, 0, tbuff, 0, resultBuff.length); // copy previous bytes
                System.arraycopy(buff, 0, tbuff, resultBuff.length, k);  // copy current lot
                resultBuff = tbuff; // call the temp buffer as your result buff

        return new String(resultBuff);
    }

}
        ![snapshot][2]
4

3 に答える 3

2

ready()電話を切ってブロックするだけです。ready() が false のときに行うことはすべて、スリープを含め、文字通り完全に時間の無駄です。read()、正確に適切な時間ブロックします。しsleep()ません。CPU 時間を浪費する十分な時間スリープしていないか、待ち時間が長くなりすぎています。たまには正しい時間に寝ることもあるかもしれませんが、これは 100% の運であり、適切な管理ではありません。読み取りタイムアウトが必要な場合は、読み取りタイムアウトを使用します。

于 2013-04-12T10:00:49.180 に答える
1

タイムアウト後、データがなくなるまで待機しているようです。

Socket.setSoTimeout(timeout in seconds)を使用することをお勧めします

より良い解決策は、データの最後に到達したことを知ることができるプロトコルを使用して、これを行う必要がないことです。サーバーの実装が不十分で、修正する方法がない場合にのみ、これを行います。

于 2013-04-12T08:23:33.380 に答える
0

問題 1. 100% の CPU は、BufferedReader.read() から単一の文字を読み取っているためである可能性があります。代わりに、データのチャンクを配列に読み取り、それを stringbuilder に追加できます。

于 2013-04-12T11:14:07.273 に答える