Skip to content

Commit

Permalink
New benchmark targets for Apache HTTP Client and URLConnection.
Browse files Browse the repository at this point in the history
OkHttp [HTTP_11]
bodyByteCount=1048576 headerCount=20 threadCount=10
Requests per second: 690.9

UrlConnection [HTTP_11]
bodyByteCount=1048576 headerCount=20 threadCount=10
Requests per second: 671.3

ApacheHttpClient [HTTP_11]
bodyByteCount=1048576 headerCount=20 threadCount=10
Requests per second: 317.4
  • Loading branch information
squarejesse committed Feb 1, 2014
1 parent e369755 commit 7c21992
Show file tree
Hide file tree
Showing 5 changed files with 190 additions and 12 deletions.
4 changes: 4 additions & 0 deletions benchmarks/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,9 @@
<artifactId>npn-boot</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* Copyright (C) 2014 Square, Inc.
*
* 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.squareup.okhttp.benchmarks;

import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.TimeUnit;
import java.util.zip.GZIPInputStream;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;

class ApacheHttpClientRequest implements Runnable {
private static final boolean VERBOSE = false;
private final HttpClient client;
private final String url;

public ApacheHttpClientRequest(String url, HttpClient client) {
this.client = client;
this.url = url;
}

public void run() {
byte[] buffer = new byte[1024];
long start = System.nanoTime();
try {
HttpResponse response = client.execute(new HttpGet(url));
InputStream in = response.getEntity().getContent();
Header contentEncoding = response.getFirstHeader("Content-Encoding");
if (contentEncoding != null && contentEncoding.getValue().equals("gzip")) {
in = new GZIPInputStream(in);
}

// Consume the response body.
int total = 0;
for (int count; (count = in.read(buffer)) != -1; ) {
total += count;
}
in.close();
long finish = System.nanoTime();

if (VERBOSE) {
System.out.println(String.format("Transferred % 8d bytes in %4d ms",
total, TimeUnit.NANOSECONDS.toMillis(finish - start)));
}
} catch (IOException e) {
System.out.println("Failed: " + e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Protocol;
import com.squareup.okhttp.internal.SslContextBuilder;
import com.squareup.okhttp.internal.http.HttpsURLConnectionImpl;
import com.squareup.okhttp.mockwebserver.Dispatcher;
import com.squareup.okhttp.mockwebserver.MockResponse;
import com.squareup.okhttp.mockwebserver.MockWebServer;
import com.squareup.okhttp.mockwebserver.RecordedRequest;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
Expand All @@ -40,6 +40,11 @@
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import org.apache.http.client.HttpClient;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.PoolingClientConnectionManager;

/**
* This benchmark is fake, but may be useful for certain relative comparisons.
Expand All @@ -51,8 +56,7 @@ public class Benchmark {
private final Random random = new Random(0);

/** Which client to run.*/
// TODO: implement additional candidates for other HTTP client libraries.
Candidate candidate = new OkHttp();
Candidate candidate = new UrlConnection(); // new OkHttp(); // new ApacheHttpClient();

/** How many concurrent threads to execute. */
int threadCount = 10;
Expand All @@ -62,10 +66,10 @@ public class Benchmark {
boolean tls = false;

/** True to use gzip content-encoding for the response body. */
boolean gzip = true;
boolean gzip = false;

/** Don't combine chunked with SPDY_3 or HTTP_2; that's not allowed. */
boolean chunked = true;
boolean chunked = false;

/** The size of the HTTP response body, in uncompressed bytes. */
int bodyByteCount = 1024 * 1024;
Expand Down Expand Up @@ -216,8 +220,6 @@ class OkHttp implements Candidate {
client = new OkHttpClient();
client.setProtocols(protocols);

URL.setURLStreamHandlerFactory(client);

if (tls) {
SSLContext sslContext = SslContextBuilder.localhost();
SSLSocketFactory socketFactory = sslContext.getSocketFactory();
Expand All @@ -232,7 +234,45 @@ class OkHttp implements Candidate {
}

@Override public Runnable request(String url) {
return new HttpURLConnectionRequest(url);
return new OkHttpRequest(client, url);
}
}

class UrlConnection implements Candidate {
@Override public void prepare() {
if (tls) {
SSLContext sslContext = SslContextBuilder.localhost();
SSLSocketFactory socketFactory = sslContext.getSocketFactory();
HostnameVerifier hostnameVerifier = new HostnameVerifier() {
@Override public boolean verify(String s, SSLSession session) {
return true;
}
};
HttpsURLConnectionImpl.setDefaultHostnameVerifier(hostnameVerifier);
HttpsURLConnectionImpl.setDefaultSSLSocketFactory(socketFactory);
}
}

@Override public Runnable request(String url) {
return new UrlConnectionRequest(url);
}
}

class ApacheHttpClient implements Candidate {
private HttpClient client;

@Override public void prepare() {
ClientConnectionManager connectionManager = new PoolingClientConnectionManager();
if (tls) {
SSLContext sslContext = SslContextBuilder.localhost();
connectionManager.getSchemeRegistry().register(
new Scheme("https", 443, new org.apache.http.conn.ssl.SSLSocketFactory(sslContext)));
}
client = new DefaultHttpClient(connectionManager);
}

@Override public Runnable request(String url) {
return new ApacheHttpClientRequest(url, client);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,23 @@
*/
package com.squareup.okhttp.benchmarks;

import com.squareup.okhttp.OkHttpClient;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.concurrent.TimeUnit;

public class HttpURLConnectionRequest implements Runnable {
class OkHttpRequest implements Runnable {
private static final boolean VERBOSE = false;

private final OkHttpClient client;
private final URL url;

public HttpURLConnectionRequest(String url) {
public OkHttpRequest(OkHttpClient client, String url) {
try {
this.client = client;
this.url = new URL(url);
} catch (MalformedURLException e) {
throw new AssertionError();
Expand All @@ -38,10 +42,10 @@ public void run() {
byte[] buffer = new byte[1024];
long start = System.nanoTime();
try {
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
HttpURLConnection urlConnection = client.open(url);
InputStream in = urlConnection.getInputStream();

// Discard the response body.
// Consume the response body.
int total = 0;
for (int count; (count = in.read(buffer)) != -1; ) {
total += count;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* Copyright (C) 2014 Square, Inc.
*
* 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.squareup.okhttp.benchmarks;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.concurrent.TimeUnit;
import java.util.zip.GZIPInputStream;

/** Uses the default java.net.HttpURLConnection implementation. */
class UrlConnectionRequest implements Runnable {
private static final boolean VERBOSE = false;

private final URL url;

public UrlConnectionRequest(String url) {
try {
this.url = new URL(url);
} catch (MalformedURLException e) {
throw new AssertionError();
}
}

public void run() {
byte[] buffer = new byte[1024];
long start = System.nanoTime();
try {
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
InputStream in = urlConnection.getInputStream();
if ("gzip".equals(urlConnection.getHeaderField("Content-Encoding"))) {
in = new GZIPInputStream(in);
}

// Consume the response body.
int total = 0;
for (int count; (count = in.read(buffer)) != -1; ) {
total += count;
}
in.close();
long finish = System.nanoTime();

if (VERBOSE) {
System.out.println(String.format("Transferred % 8d bytes in %4d ms",
total, TimeUnit.NANOSECONDS.toMillis(finish - start)));
}
} catch (IOException e) {
System.out.println("Failed: " + e);
}
}
}

0 comments on commit 7c21992

Please sign in to comment.