mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 07:14:30 +02:00
8061281: Microbenchmark suite build support, directory layout and sample benchmarks
8061282: Migrate jmh-jdk-microbenchmarks into the JDK Co-authored-by: Magnus Ihse Bursie <magnus.ihse.bursie@oracle.com> Co-authored-by: Erik Joelsson <erik.joelsson@oracle.com> Co-authored-by: Staffan Friberg <sfriberg@kth.se> Reviewed-by: ecaspole, mchung, erikj, ihse
This commit is contained in:
parent
14b7467279
commit
7a30c97753
247 changed files with 26097 additions and 13 deletions
253
test/micro/org/openjdk/bench/java/net/SocketStreaming.java
Normal file
253
test/micro/org/openjdk/bench/java/net/SocketStreaming.java
Normal file
|
@ -0,0 +1,253 @@
|
|||
/*
|
||||
* Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package org.openjdk.bench.java.net;
|
||||
|
||||
import org.openjdk.jmh.annotations.Benchmark;
|
||||
import org.openjdk.jmh.annotations.BenchmarkMode;
|
||||
import org.openjdk.jmh.annotations.Mode;
|
||||
import org.openjdk.jmh.annotations.OutputTimeUnit;
|
||||
import org.openjdk.jmh.annotations.Scope;
|
||||
import org.openjdk.jmh.annotations.Setup;
|
||||
import org.openjdk.jmh.annotations.State;
|
||||
import org.openjdk.jmh.annotations.TearDown;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.InetAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Micro benchmark for streaming data over a Socket.
|
||||
*/
|
||||
@BenchmarkMode(Mode.AverageTime)
|
||||
@OutputTimeUnit(TimeUnit.MILLISECONDS)
|
||||
@State(Scope.Thread)
|
||||
public class SocketStreaming {
|
||||
|
||||
/** The bytes to write/read. */
|
||||
public static final int dataLength = 16383;
|
||||
/** setTcpNoDelay(noNagle) */
|
||||
public static final boolean noNagle = false;
|
||||
|
||||
private WriterThread writerThread;
|
||||
private Socket readSocket;
|
||||
private byte[] bytes;
|
||||
|
||||
@Setup
|
||||
public void prepare() throws Exception {
|
||||
bytes = new byte[dataLength];
|
||||
|
||||
// Setup the writer thread
|
||||
writerThread = new WriterThread(dataLength, noNagle);
|
||||
writerThread.start();
|
||||
|
||||
// Wait for a read socket
|
||||
readSocket = writerThread.waitForReadSocket();
|
||||
}
|
||||
|
||||
@TearDown
|
||||
public void cleanup() throws IOException {
|
||||
// Take down the writer thread and the reader socket
|
||||
writerThread.finish();
|
||||
while (!readSocket.isClosed()) {
|
||||
readSocket.close();
|
||||
}
|
||||
readSocket = null;
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void testSocketInputStreamRead() throws InterruptedException, IOException {
|
||||
InputStream in = readSocket.getInputStream();
|
||||
|
||||
// Notify the writer thread to add elements to stream
|
||||
writerThread.requestSendBytes();
|
||||
|
||||
// Read these from the stream
|
||||
int bytesRead = 0;
|
||||
while (bytesRead < dataLength) {
|
||||
int lastRead = in.read(bytes);
|
||||
if (lastRead < 0) {
|
||||
throw new InternalError("Unexpectedly got " + lastRead + " bytes from the socket");
|
||||
}
|
||||
bytesRead += lastRead;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Thread used to write bytes to a socket.
|
||||
*/
|
||||
private class WriterThread extends Thread {
|
||||
|
||||
/** The number of bytes to write. */
|
||||
private int dataLength;
|
||||
/** setTcpNoDelay(noNagle) */
|
||||
private boolean noNagle;
|
||||
/** Lock needed to send sendBytes requests. */
|
||||
private final Object sendBytesLock = new Object();
|
||||
/** Indicates that a sendBytes has been requested. */
|
||||
private boolean sendBytesRequested;
|
||||
/** Indicates that no more sendBytes will be requested. Time to shutdown. */
|
||||
private boolean sendBytesDone;
|
||||
/** Lock needed to protect the connectPort variable. */
|
||||
private final Object connectLock = new Object();
|
||||
/** The port the read socket should connect to. */
|
||||
private int connectPort = -1;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param dataLength The number of bytes to write
|
||||
* @param noNagle setTcpNoDelay(noNagle)
|
||||
*/
|
||||
public WriterThread(int dataLength, boolean noNagle) {
|
||||
super("Load producer");
|
||||
this.dataLength = dataLength;
|
||||
this.noNagle = noNagle;
|
||||
}
|
||||
|
||||
/** Entry point for data sending helper thread. */
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Socket writeSocket;
|
||||
ServerSocket serverSocket = new ServerSocket(0);
|
||||
|
||||
/* Tell the other thread that we now know the port number.
|
||||
* The other thread will now start to connect until the following accept() call succeeds.
|
||||
*/
|
||||
synchronized (connectLock) {
|
||||
connectPort = serverSocket.getLocalPort();
|
||||
connectLock.notify();
|
||||
}
|
||||
|
||||
// Wait for the other thread to connect
|
||||
writeSocket = serverSocket.accept();
|
||||
writeSocket.setTcpNoDelay(noNagle);
|
||||
|
||||
// No more connects so this can be closed
|
||||
serverSocket.close();
|
||||
serverSocket = null;
|
||||
|
||||
OutputStream out = writeSocket.getOutputStream();
|
||||
|
||||
// Iterate as long as sendBytes are issued
|
||||
while (waitForSendBytesRequest()) {
|
||||
sendBytes(out);
|
||||
}
|
||||
|
||||
// Time to shutdown
|
||||
while (!writeSocket.isClosed()) {
|
||||
writeSocket.close();
|
||||
}
|
||||
writeSocket = null;
|
||||
} catch (Exception e) {
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends bytes to the output stream
|
||||
*
|
||||
* @param out The output stream
|
||||
* @throws IOException
|
||||
*/
|
||||
private void sendBytes(OutputStream out) throws IOException {
|
||||
byte outBytes[] = new byte[dataLength];
|
||||
|
||||
int bytesToSend = dataLength;
|
||||
int bytesSent = 0;
|
||||
while (bytesSent < bytesToSend) {
|
||||
out.write(outBytes);
|
||||
bytesSent += outBytes.length;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for the readSocket and returns it when it is ready.
|
||||
*
|
||||
* @return The socket to read from
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
@SuppressWarnings("SleepWhileHoldingLock")
|
||||
public Socket waitForReadSocket() throws InterruptedException {
|
||||
int theConnectPort = waitForConnectPort();
|
||||
|
||||
while (true) {
|
||||
try {
|
||||
return new Socket(InetAddress.getByName(null), theConnectPort);
|
||||
} catch (IOException e) {
|
||||
// Wait some more for the server thread to get going
|
||||
Thread.sleep(1000);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for next sendBytes request
|
||||
*
|
||||
* @return <code>true</code> if it is time to sendBytes, <code>false</code> if it is time to shutdown
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
public boolean waitForSendBytesRequest() throws InterruptedException {
|
||||
synchronized (sendBytesLock) {
|
||||
while (!sendBytesRequested && !sendBytesDone) {
|
||||
sendBytesLock.wait();
|
||||
}
|
||||
|
||||
// Clear the flag
|
||||
sendBytesRequested = false;
|
||||
|
||||
return !sendBytesDone;
|
||||
}
|
||||
}
|
||||
|
||||
/** Requests a sendBytes. */
|
||||
public void requestSendBytes() {
|
||||
synchronized (sendBytesLock) {
|
||||
sendBytesRequested = true;
|
||||
sendBytesLock.notify();
|
||||
}
|
||||
}
|
||||
|
||||
/** Tells the writerThread that it is time to shutdown. */
|
||||
public void finish() {
|
||||
synchronized (sendBytesLock) {
|
||||
sendBytesDone = true;
|
||||
sendBytesLock.notify();
|
||||
}
|
||||
}
|
||||
|
||||
private int waitForConnectPort() throws InterruptedException {
|
||||
synchronized (connectLock) {
|
||||
while (connectPort == -1) {
|
||||
connectLock.wait();
|
||||
}
|
||||
return connectPort;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue