blob: 1bb35b4fb6894a8414282e0812cf0476747b6ffe [file] [log] [blame]
/* GENERATED SOURCE. DO NOT MODIFY. */
/*
* Copyright 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.org.conscrypt;
import static com.android.org.conscrypt.TestUtils.newTextMessage;
import java.io.OutputStream;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
/**
* Benchmark for comparing performance of client socket implementations.
* @hide This class is not part of the Android public SDK API
*/
public final class ClientSocketBenchmark {
/**
* Provider for the benchmark configuration
*/
interface Config {
EndpointFactory clientFactory();
EndpointFactory serverFactory();
int messageSize();
String cipher();
ChannelType channelType();
BenchmarkProtocol protocol();
}
private ClientEndpoint client;
private ServerEndpoint server;
private byte[] message;
private ExecutorService executor;
private Future<?> sendingFuture;
private volatile boolean stopping;
private static final AtomicLong bytesCounter = new AtomicLong();
private AtomicBoolean recording = new AtomicBoolean();
ClientSocketBenchmark(Config config) throws Exception {
recording.set(false);
message = newTextMessage(config.messageSize());
// Always use the same server for consistency across the benchmarks.
server = config.serverFactory().newServer(
ChannelType.CHANNEL, config.messageSize(), config.protocol().getProtocols(),
ciphers(config));
server.setMessageProcessor(new ServerEndpoint.MessageProcessor() {
@Override
public void processMessage(byte[] inMessage, int numBytes, OutputStream os) {
if (recording.get()) {
// Server received a message, increment the count.
bytesCounter.addAndGet(numBytes);
}
}
});
Future<?> connectedFuture = server.start();
client = config.clientFactory().newClient(
config.channelType(), server.port(), config.protocol().getProtocols(), ciphers(config));
client.start();
// Wait for the initial connection to complete.
connectedFuture.get(5, TimeUnit.SECONDS);
executor = Executors.newSingleThreadExecutor();
sendingFuture = executor.submit(new Runnable() {
@Override
public void run() {
try {
Thread thread = Thread.currentThread();
while (!stopping && !thread.isInterrupted()) {
client.sendMessage(message);
}
} finally {
client.flush();
}
}
});
}
void close() throws Exception {
stopping = true;
// Wait for the sending thread to stop.
sendingFuture.get(5, TimeUnit.SECONDS);
client.stop();
server.stop();
executor.shutdown();
executor.awaitTermination(5, TimeUnit.SECONDS);
}
/**
* Simple benchmark for the amount of time to send a given number of messages (used by
* Caliper).
*/
void time(final int numMessages) throws Exception {
reset();
recording.set(true);
while (bytesCounter.get() < numMessages) {
Thread.sleep(50);
}
recording.set(false);
}
/**
* Simple benchmark for throughput (used by JMH).
*/
void throughput() throws Exception {
recording.set(true);
// Send as many messages as we can in a second.
Thread.sleep(1001);
recording.set(false);
}
static void reset() {
bytesCounter.set(0);
}
static long bytesPerSecond() {
return bytesCounter.get();
}
private String[] ciphers(Config config) {
return new String[] {config.cipher()};
}
}