Browse Source

Merge pull request #219 from Netflix/adrian.perf-example

Demonstrates impact of advice to cache Feign.newInstance
pull/222/head
Adrian Cole 10 years ago
parent
commit
27dc3739a0
  1. 29
      benchmark/pom.xml
  2. 46
      benchmark/src/main/java/feign/benchmark/ContractBenchmarks.java
  3. 4
      benchmark/src/main/java/feign/benchmark/FeignTestInterface.java
  4. 57
      benchmark/src/main/java/feign/benchmark/JAXRSTestInterface.java
  5. 85
      benchmark/src/main/java/feign/benchmark/RealRequestBenchmarks.java
  6. 109
      benchmark/src/main/java/feign/benchmark/WhatShouldWeCacheBenchmarks.java

29
benchmark/pom.xml

@ -27,13 +27,34 @@ @@ -27,13 +27,34 @@
</dependency>
<dependency>
<groupId>com.netflix.feign</groupId>
<artifactId>feign-jaxrs</artifactId>
<artifactId>feign-okhttp</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>jsr311-api</artifactId>
<version>1.1.1</version>
<groupId>com.squareup.okhttp</groupId>
<artifactId>mockwebserver</artifactId>
<version>2.3.0</version>
<exclusions>
<exclusion>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.reactivex</groupId>
<artifactId>rxnetty</artifactId>
<version>0.4.8</version>
</dependency>
<dependency>
<groupId>io.reactivex</groupId>
<artifactId>rxjava</artifactId>
<version>1.0.9</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-codec-http</artifactId>
<version>4.0.26.Final</version>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>

46
benchmark/src/main/java/feign/benchmark/ContractBenchmarks.java

@ -1,46 +0,0 @@ @@ -1,46 +0,0 @@
package feign.benchmark;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Measurement;
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.Warmup;
import java.util.concurrent.TimeUnit;
import feign.Contract;
import feign.jaxrs.JAXRSContract;
@Measurement(iterations = 5, time = 1)
@Warmup(iterations = 5, time = 1)
@Fork(3)
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.SECONDS)
@State(Scope.Thread)
public class ContractBenchmarks {
private Contract feignContract;
private Contract jaxrsContract;
@Setup
public void setup() {
feignContract = new Contract.Default();
jaxrsContract = new JAXRSContract();
}
@Benchmark
public void parseFeign() {
feignContract.parseAndValidatateMetadata(FeignTestInterface.class);
}
@Benchmark
public void parseJAXRS() {
jaxrsContract.parseAndValidatateMetadata(JAXRSTestInterface.class);
}
}

4
benchmark/src/main/java/feign/benchmark/FeignTestInterface.java

@ -2,8 +2,6 @@ package feign.benchmark; @@ -2,8 +2,6 @@ package feign.benchmark;
import java.util.List;
import javax.ws.rs.HeaderParam;
import feign.Body;
import feign.Headers;
import feign.Param;
@ -35,5 +33,5 @@ interface FeignTestInterface { @@ -35,5 +33,5 @@ interface FeignTestInterface {
@RequestLine("POST /")
@Headers({"Happy: sad", "Auth-Token: {authToken}"})
void headers(@HeaderParam("authToken") String token);
void headers(@Param("authToken") String token);
}

57
benchmark/src/main/java/feign/benchmark/JAXRSTestInterface.java

@ -1,57 +0,0 @@ @@ -1,57 +0,0 @@
package feign.benchmark;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.List;
import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.HttpMethod;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import feign.Headers;
import feign.Response;
@Consumes("application/json")
interface JAXRSTestInterface {
@GET
@Path("/?Action=GetUser&Version=2010-05-08&limit=1")
Response query();
@GET
@Path("/domains/{domainId}/records")
Response mixedParams(@PathParam("domainId") int id, @QueryParam("name") String nameFilter,
@QueryParam("type") String typeFilter);
@PATCH
Response customMethod();
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@HttpMethod("PATCH")
@interface PATCH {
}
@PUT
@Produces("application/json")
void bodyParam(List<String> body);
@POST
void form(@FormParam("customer_name") String customer, @FormParam("user_name") String user,
@FormParam("password") String password);
@POST
@Headers("Happy: sad")
void headers(@HeaderParam("Auth-Token") String token);
}

85
benchmark/src/main/java/feign/benchmark/RealRequestBenchmarks.java

@ -0,0 +1,85 @@ @@ -0,0 +1,85 @@
package feign.benchmark;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Measurement;
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 org.openjdk.jmh.annotations.Warmup;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import feign.Feign;
import feign.Response;
import io.netty.buffer.ByteBuf;
import io.reactivex.netty.RxNetty;
import io.reactivex.netty.protocol.http.server.HttpServer;
import io.reactivex.netty.protocol.http.server.HttpServerRequest;
import io.reactivex.netty.protocol.http.server.HttpServerResponse;
import io.reactivex.netty.protocol.http.server.RequestHandler;
@Measurement(iterations = 5, time = 1)
@Warmup(iterations = 10, time = 1)
@Fork(3)
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.SECONDS)
@State(Scope.Benchmark)
public class RealRequestBenchmarks {
private static final int SERVER_PORT = 8765;
private HttpServer<ByteBuf, ByteBuf> server;
private OkHttpClient client;
private FeignTestInterface okFeign;
private Request queryRequest;
@Setup
public void setup() {
server = RxNetty.createHttpServer(SERVER_PORT, new RequestHandler<ByteBuf, ByteBuf>() {
public rx.Observable handle(HttpServerRequest<ByteBuf> request,
HttpServerResponse<ByteBuf> response) {
return response.flush();
}
});
server.start();
client = new OkHttpClient();
client.setRetryOnConnectionFailure(false);
okFeign = Feign.builder()
.client(new feign.okhttp.OkHttpClient(client))
.target(FeignTestInterface.class, "http://localhost:" + SERVER_PORT);
queryRequest = new Request.Builder()
.url("http://localhost:" + SERVER_PORT + "/?Action=GetUser&Version=2010-05-08&limit=1")
.build();
}
@TearDown
public void tearDown() throws InterruptedException {
server.shutdown();
}
/**
* How fast can we execute get commands synchronously?
*/
@Benchmark
public com.squareup.okhttp.Response query_baseCaseUsingOkHttp() throws IOException {
com.squareup.okhttp.Response result = client.newCall(queryRequest).execute();
result.body().close();
return result;
}
/**
* How fast can we execute get commands synchronously using Feign?
*/
@Benchmark
public Response query_feignUsingOkHttp() {
return okFeign.query();
}
}

109
benchmark/src/main/java/feign/benchmark/WhatShouldWeCacheBenchmarks.java

@ -0,0 +1,109 @@ @@ -0,0 +1,109 @@
package feign.benchmark;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Measurement;
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.Warmup;
import java.io.IOException;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import feign.Client;
import feign.Contract;
import feign.Feign;
import feign.MethodMetadata;
import feign.Request;
import feign.Response;
import feign.Target.HardCodedTarget;
@Measurement(iterations = 5, time = 1)
@Warmup(iterations = 10, time = 1)
@Fork(3)
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.SECONDS)
@State(Scope.Thread)
public class WhatShouldWeCacheBenchmarks {
private Contract feignContract;
private Contract cachedContact;
private Client fakeClient;
private Feign cachedFakeFeign;
private FeignTestInterface cachedFakeApi;
@Setup
public void setup() {
feignContract = new Contract.Default();
cachedContact = new Contract() {
private final List<MethodMetadata> cached =
new Default().parseAndValidatateMetadata(FeignTestInterface.class);
public List<MethodMetadata> parseAndValidatateMetadata(Class<?> declaring) {
return cached;
}
};
fakeClient = new Client() {
public Response execute(Request request, Request.Options options) throws IOException {
Map<String, Collection<String>> headers = new LinkedHashMap<String, Collection<String>>();
return Response.create(200, "ok", headers, (byte[]) null);
}
};
cachedFakeFeign = Feign.builder().client(fakeClient).build();
cachedFakeApi = cachedFakeFeign.newInstance(
new HardCodedTarget<FeignTestInterface>(FeignTestInterface.class, "http://localhost"));
}
/**
* How fast is parsing an api interface?
*/
@Benchmark
public List<MethodMetadata> parseFeignContract() {
return feignContract.parseAndValidatateMetadata(FeignTestInterface.class);
}
/**
* How fast is creating a feign instance for each http request, without considering network?
*/
@Benchmark
public Response buildAndQuery_fake() {
return Feign.builder().client(fakeClient)
.target(FeignTestInterface.class, "http://localhost").query();
}
/**
* How fast is creating a feign instance for each http request, without considering network, and
* without re-parsing the annotated http api?
*/
@Benchmark
public Response buildAndQuery_fake_cachedContract() {
return Feign.builder().contract(cachedContact).client(fakeClient)
.target(FeignTestInterface.class, "http://localhost").query();
}
/**
* How fast re-parsing the annotated http api for each http request, without considering network?
*/
@Benchmark
public Response buildAndQuery_fake_cachedFeign() {
return cachedFakeFeign.newInstance(
new HardCodedTarget<FeignTestInterface>(FeignTestInterface.class, "http://localhost"))
.query();
}
/**
* How fast is our advice to use a cached api for each http request, without considering network?
*/
@Benchmark
public Response buildAndQuery_fake_cachedApi() {
return cachedFakeApi.query();
}
}
Loading…
Cancel
Save