Created
January 20, 2011 19:36
-
-
Save aviflax/788468 to your computer and use it in GitHub Desktop.
Benchmarking HTTP client performance using Apache HttpClient 3.1 and 4.0 with and without Restlet 1.1 and 2.0. The server is a constant value (always warmed up) and I tried to make the scripts as identical as possible.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env groovy -cp restlet-1.1.10/httpclient/* | |
/*** SETTINGS ***/ | |
requestsToSend = args.length >= 1 ? args[0] as Integer : 10000 | |
concurrency = args.length >= 2 ? args[1] as Integer : 10 | |
port = args.length >= 3 ? args[2] as Integer : 3000 | |
/*** /SETTINGS ***/ | |
import java.util.concurrent.atomic.AtomicInteger | |
import org.apache.commons.httpclient.* | |
import org.apache.commons.httpclient.methods.PostMethod | |
requestsPerThread = (requestsToSend / concurrency) as Integer | |
println "Sending $requestsToSend requests across $concurrency threads" | |
httpClient = new HttpClient(new MultiThreadedHttpConnectionManager()) | |
httpClient.httpConnectionManager.params.defaultMaxConnectionsPerHost = 50 | |
httpClient.httpConnectionManager.params.maxTotalConnections = 50 | |
requestURL = "http://localhost:$port/" | |
formParams = [] | |
formParams << new NameValuePair('foo', 'bar') | |
20.times { formParams << new NameValuePair('foo.' + it, 'bar'.multiply(it * 2)) } | |
entity = formParams as NameValuePair[] | |
requestCounter = new AtomicInteger(0) | |
threads = [] | |
concurrency.times { | |
threads << Thread.start { | |
def request = new PostMethod(requestURL) | |
request.requestBody = entity | |
requestsPerThread.times { | |
httpClient.executeMethod request | |
if (request.getStatusCode() != 202) { | |
println "\n\nThread aborting due to status: $response.statusLine\n\n" | |
Thread.currentThread().interrupt() | |
} | |
request.releaseConnection() | |
int counterValue = requestCounter.incrementAndGet() | |
if (counterValue % 1000 == 0) { | |
print counterValue | |
print ' requests sent and handled\r' | |
} | |
} | |
} | |
} | |
threads.each { it.join() } | |
println "$requestCounter requests sent and handled" | |
System.exit(0) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env groovy -cp restlet-2.0.4/restlet/*:restlet-2.0.4/httpclient/* | |
/*** SETTINGS ***/ | |
requestsToSend = args.length >= 1 ? args[0] as Integer : 10000 | |
concurrency = args.length >= 2 ? args[1] as Integer : 10 | |
port = args.length >= 3 ? args[2] as Integer : 3000 | |
/*** /SETTINGS ***/ | |
requestsPerThread = (requestsToSend / concurrency) as Integer | |
println "Sending $requestsToSend requests across $concurrency threads" | |
import javax.net.ssl.SSLContext | |
import java.util.concurrent.atomic.* | |
import org.apache.http.* | |
import org.apache.http.client.* | |
import org.apache.http.client.entity.UrlEncodedFormEntity | |
import org.apache.http.client.methods.HttpPost | |
import org.apache.http.client.params.* | |
import org.apache.http.conn.ClientConnectionManager | |
import org.apache.http.conn.params.* | |
import org.apache.http.conn.scheme.* | |
import org.apache.http.conn.ssl.SSLSocketFactory | |
import org.apache.http.impl.client.DefaultHttpClient | |
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager | |
import org.apache.http.message.BasicNameValuePair | |
import org.apache.http.params.* | |
import org.restlet.engine.security.DefaultSslContextFactory | |
import org.restlet.engine.security.SslContextFactory | |
params = new BasicHttpParams() | |
configure(params) | |
schemeRegistry = new SchemeRegistry() | |
configure(schemeRegistry) | |
connManager = new ThreadSafeClientConnManager(params, schemeRegistry) | |
httpClient = new DefaultHttpClient(connManager, params) | |
requestURL = "http://localhost:$port/" | |
formparams = [] | |
formparams << new BasicNameValuePair('foo', 'bar') | |
20.times { formparams << new BasicNameValuePair('foo.' + it, 'bar'.multiply(it * 2)) } | |
entity = new UrlEncodedFormEntity(formparams, "UTF-8") | |
requestCounter = new AtomicInteger(0) | |
threads = [] | |
concurrency.times { | |
threads << Thread.start { | |
def request = new HttpPost(requestURL) | |
request.entity = entity | |
requestsPerThread.times { | |
HttpResponse response = httpClient.execute(request) | |
if (response.getStatusLine().getStatusCode() != 202) { | |
println "\n\nThread aborting due to status: $response.statusLine\n\n" | |
Thread.currentThread().interrupt() | |
} | |
response.getEntity().consumeContent() | |
int counterValue = requestCounter.incrementAndGet() | |
if (counterValue % 1000 == 0) { | |
print counterValue | |
print ' requests sent and handled\r' | |
} | |
} | |
} | |
} | |
threads.each { it.join() } | |
println "$requestCounter requests sent and handled" | |
System.exit(0) | |
/*** TAKEN FROM org.restlet.ext.httpclient.HttpClientHelper ***/ | |
def void configure(HttpParams params) { | |
ConnManagerParams.setMaxTotalConnections(params, 50) | |
ConnManagerParams.setMaxConnectionsPerRoute(params, new ConnPerRouteBean(50)) | |
// Configure other parameters | |
HttpClientParams.setAuthenticating(params, false) | |
HttpClientParams.setRedirecting(params, false) | |
HttpClientParams.setCookiePolicy(params, CookiePolicy.BROWSER_COMPATIBILITY) | |
HttpConnectionParams.setTcpNoDelay(params, false) | |
HttpConnectionParams.setConnectionTimeout(params, 0) | |
HttpConnectionParams.setSoTimeout(params, 0) | |
} | |
/** | |
* Configures the scheme registry. By default, it registers the HTTP and the | |
* HTTPS schemes. | |
* | |
* @param schemeRegistry | |
* The scheme registry to configure. | |
*/ | |
def void configure(SchemeRegistry schemeRegistry) { | |
schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)) | |
SSLSocketFactory sslSocketFactory = null | |
SslContextFactory sslContextFactory = new DefaultSslContextFactory() | |
if (sslContextFactory != null) { | |
try { | |
SSLContext sslContext = sslContextFactory.createSslContext() | |
sslSocketFactory = new SSLSocketFactory(sslContext) | |
} catch (Exception e) { | |
throw new RuntimeException("Unable to create SSLContext.", e) | |
} | |
} else { | |
sslSocketFactory = SSLSocketFactory.getSocketFactory() | |
} | |
schemeRegistry.register(new Scheme("https", sslSocketFactory, 443)) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*** SETTINGS ***/ | |
requestsToSend = args.length >= 1 ? args[0] as Integer : 10000 | |
concurrency = args.length >= 2 ? args[1] as Integer : 10 | |
port = args.length >= 3 ? args[2] as Integer : 3000 | |
/*** /SETTINGS ***/ | |
requestsPerThread = (requestsToSend / concurrency) as Integer | |
import java.util.concurrent.atomic.* | |
import org.restlet.* | |
import org.restlet.data.* | |
import org.restlet.representation.* | |
import org.restlet.resource.* | |
ref = new Reference("http://localhost:$port/") | |
def client = new Client(new Context(), Protocol.HTTP) | |
client.context.parameters.add 'maxConnectionsPerHost', (concurrency * 2) as String | |
client.context.parameters.add 'maxTotalConnections', (concurrency * 2) as String | |
// need to pre-start the client because was otherwise having concurrency issues | |
client.start() | |
form = new Form() | |
form.add 'foo', 'bar' | |
20.times { form.add 'foo.' + it, 'bar'.multiply(it * 2) } | |
formText = form.webRepresentation.text | |
requestCounter = new AtomicInteger(0) | |
threads = [] | |
concurrency.times { | |
threads << Thread.start { | |
def request = new Request(Method.POST, ref, new StringRepresentation(formText, MediaType.APPLICATION_WWW_FORM)) | |
requestsPerThread.times { | |
Response response = client.handle(request) | |
if (response.getStatus().getCode() != 202) { | |
println "\n\nThread aborting due to status: ${response.status}\n\n" | |
Thread.currentThread().interrupt() | |
} | |
int counterValue = requestCounter.incrementAndGet() | |
if (counterValue % 1000 == 0) { | |
print counterValue | |
print ' requests sent and handled\r' | |
} | |
} | |
} | |
} | |
threads.each { it.join() } | |
println "$requestCounter requests sent and handled" | |
System.exit(0) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env java -cp groovy-all-1.7.5.jar:restlet-2.0.4/restlet/*:restlet-2.0.4/jetty/* groovy.lang.GroovyShell | |
/*** SETTINGS ***/ | |
port = args.length >= 1 ? args[0] as Integer : 3000 | |
/*** /SETTINGS ***/ | |
import java.util.concurrent.atomic.* | |
import org.restlet.* | |
import org.restlet.data.* | |
import org.restlet.representation.* | |
import org.restlet.resource.* | |
class RequestHandler extends Restlet { | |
static requestCounter = new AtomicInteger(0) | |
void handle(Request request, Response response) { | |
response.setStatus(Status.SUCCESS_ACCEPTED) | |
int counterValue = requestCounter.incrementAndGet() | |
if (counterValue % 1000 == 0) { | |
print counterValue | |
print ' requests handled\r' | |
} | |
} | |
} | |
new Server(Protocol.HTTP, port, new RequestHandler()).start() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment