Path: blob/master/test/micro/org/openjdk/bench/java/net/SocketStreaming.java
41161 views
/*1* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/22package org.openjdk.bench.java.net;2324import org.openjdk.jmh.annotations.Benchmark;25import org.openjdk.jmh.annotations.BenchmarkMode;26import org.openjdk.jmh.annotations.Mode;27import org.openjdk.jmh.annotations.OutputTimeUnit;28import org.openjdk.jmh.annotations.Scope;29import org.openjdk.jmh.annotations.Setup;30import org.openjdk.jmh.annotations.State;31import org.openjdk.jmh.annotations.TearDown;3233import java.io.IOException;34import java.io.InputStream;35import java.io.OutputStream;36import java.net.InetAddress;37import java.net.ServerSocket;38import java.net.Socket;39import java.util.concurrent.TimeUnit;4041/**42* Micro benchmark for streaming data over a Socket.43*/44@BenchmarkMode(Mode.AverageTime)45@OutputTimeUnit(TimeUnit.MILLISECONDS)46@State(Scope.Thread)47public class SocketStreaming {4849/** The bytes to write/read. */50public static final int dataLength = 16383;51/** setTcpNoDelay(noNagle) */52public static final boolean noNagle = false;5354private WriterThread writerThread;55private Socket readSocket;56private byte[] bytes;5758@Setup59public void prepare() throws Exception {60bytes = new byte[dataLength];6162// Setup the writer thread63writerThread = new WriterThread(dataLength, noNagle);64writerThread.start();6566// Wait for a read socket67readSocket = writerThread.waitForReadSocket();68}6970@TearDown71public void cleanup() throws IOException {72// Take down the writer thread and the reader socket73writerThread.finish();74while (!readSocket.isClosed()) {75readSocket.close();76}77readSocket = null;78}7980@Benchmark81public void testSocketInputStreamRead() throws InterruptedException, IOException {82InputStream in = readSocket.getInputStream();8384// Notify the writer thread to add elements to stream85writerThread.requestSendBytes();8687// Read these from the stream88int bytesRead = 0;89while (bytesRead < dataLength) {90int lastRead = in.read(bytes);91if (lastRead < 0) {92throw new InternalError("Unexpectedly got " + lastRead + " bytes from the socket");93}94bytesRead += lastRead;95}96}9798/**99* Thread used to write bytes to a socket.100*/101private class WriterThread extends Thread {102103/** The number of bytes to write. */104private int dataLength;105/** setTcpNoDelay(noNagle) */106private boolean noNagle;107/** Lock needed to send sendBytes requests. */108private final Object sendBytesLock = new Object();109/** Indicates that a sendBytes has been requested. */110private boolean sendBytesRequested;111/** Indicates that no more sendBytes will be requested. Time to shutdown. */112private boolean sendBytesDone;113/** Lock needed to protect the connectPort variable. */114private final Object connectLock = new Object();115/** The port the read socket should connect to. */116private int connectPort = -1;117118/**119* Constructor.120*121* @param dataLength The number of bytes to write122* @param noNagle setTcpNoDelay(noNagle)123*/124public WriterThread(int dataLength, boolean noNagle) {125super("Load producer");126this.dataLength = dataLength;127this.noNagle = noNagle;128}129130/** Entry point for data sending helper thread. */131@Override132public void run() {133try {134Socket writeSocket;135ServerSocket serverSocket = new ServerSocket(0);136137/* Tell the other thread that we now know the port number.138* The other thread will now start to connect until the following accept() call succeeds.139*/140synchronized (connectLock) {141connectPort = serverSocket.getLocalPort();142connectLock.notify();143}144145// Wait for the other thread to connect146writeSocket = serverSocket.accept();147writeSocket.setTcpNoDelay(noNagle);148149// No more connects so this can be closed150serverSocket.close();151serverSocket = null;152153OutputStream out = writeSocket.getOutputStream();154155// Iterate as long as sendBytes are issued156while (waitForSendBytesRequest()) {157sendBytes(out);158}159160// Time to shutdown161while (!writeSocket.isClosed()) {162writeSocket.close();163}164writeSocket = null;165} catch (Exception e) {166System.exit(1);167}168}169170/**171* Sends bytes to the output stream172*173* @param out The output stream174* @throws IOException175*/176private void sendBytes(OutputStream out) throws IOException {177byte outBytes[] = new byte[dataLength];178179int bytesToSend = dataLength;180int bytesSent = 0;181while (bytesSent < bytesToSend) {182out.write(outBytes);183bytesSent += outBytes.length;184}185}186187/**188* Waits for the readSocket and returns it when it is ready.189*190* @return The socket to read from191* @throws InterruptedException192*/193@SuppressWarnings("SleepWhileHoldingLock")194public Socket waitForReadSocket() throws InterruptedException {195int theConnectPort = waitForConnectPort();196197while (true) {198try {199return new Socket(InetAddress.getByName(null), theConnectPort);200} catch (IOException e) {201// Wait some more for the server thread to get going202Thread.sleep(1000);203}204}205206}207208/**209* Waits for next sendBytes request210*211* @return <code>true</code> if it is time to sendBytes, <code>false</code> if it is time to shutdown212* @throws InterruptedException213*/214public boolean waitForSendBytesRequest() throws InterruptedException {215synchronized (sendBytesLock) {216while (!sendBytesRequested && !sendBytesDone) {217sendBytesLock.wait();218}219220// Clear the flag221sendBytesRequested = false;222223return !sendBytesDone;224}225}226227/** Requests a sendBytes. */228public void requestSendBytes() {229synchronized (sendBytesLock) {230sendBytesRequested = true;231sendBytesLock.notify();232}233}234235/** Tells the writerThread that it is time to shutdown. */236public void finish() {237synchronized (sendBytesLock) {238sendBytesDone = true;239sendBytesLock.notify();240}241}242243private int waitForConnectPort() throws InterruptedException {244synchronized (connectLock) {245while (connectPort == -1) {246connectLock.wait();247}248return connectPort;249}250}251}252}253254255