13c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller/*
23c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * Copyright (C) 2014 Square, Inc.
33c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller *
43c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * Licensed under the Apache License, Version 2.0 (the "License");
53c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * you may not use this file except in compliance with the License.
63c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * You may obtain a copy of the License at
73c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller *
83c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller *      http://www.apache.org/licenses/LICENSE-2.0
93c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller *
103c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * Unless required by applicable law or agreed to in writing, software
113c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * distributed under the License is distributed on an "AS IS" BASIS,
123c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * See the License for the specific language governing permissions and
143c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * limitations under the License.
153c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller */
163c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerpackage com.squareup.okhttp.benchmarks;
173c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
183c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport com.squareup.okhttp.Dispatcher;
193c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport com.squareup.okhttp.Failure;
203c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport com.squareup.okhttp.OkHttpClient;
213c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport com.squareup.okhttp.Request;
223c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport com.squareup.okhttp.Response;
233c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport com.squareup.okhttp.internal.SslContextBuilder;
243c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport java.io.IOException;
253c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport java.net.URL;
263c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport java.util.concurrent.LinkedBlockingQueue;
273c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport java.util.concurrent.ThreadPoolExecutor;
283c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport java.util.concurrent.TimeUnit;
293c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport java.util.concurrent.atomic.AtomicInteger;
303c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport javax.net.ssl.HostnameVerifier;
313c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport javax.net.ssl.SSLContext;
323c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport javax.net.ssl.SSLSession;
333c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport javax.net.ssl.SSLSocketFactory;
343c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
353c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerclass OkHttpAsync implements HttpClient {
363c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  private static final boolean VERBOSE = false;
373c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
383c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  private final AtomicInteger requestsInFlight = new AtomicInteger();
393c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
403c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  private OkHttpClient client;
413c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  private Response.Receiver receiver;
423c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  private int concurrencyLevel;
433c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  private int targetBacklog;
443c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
453c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  @Override public void prepare(final Benchmark benchmark) {
463c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    concurrencyLevel = benchmark.concurrencyLevel;
473c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    targetBacklog = benchmark.targetBacklog;
483c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
493c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    client = new OkHttpClient();
503c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    client.setProtocols(benchmark.protocols);
513c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    client.setDispatcher(new Dispatcher(new ThreadPoolExecutor(benchmark.concurrencyLevel,
523c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        benchmark.concurrencyLevel, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>())));
533c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
543c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    if (benchmark.tls) {
553c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      SSLContext sslContext = SslContextBuilder.localhost();
563c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      SSLSocketFactory socketFactory = sslContext.getSocketFactory();
573c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      HostnameVerifier hostnameVerifier = new HostnameVerifier() {
583c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        @Override public boolean verify(String s, SSLSession session) {
593c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller          return true;
603c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        }
613c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      };
623c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      client.setSslSocketFactory(socketFactory);
633c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      client.setHostnameVerifier(hostnameVerifier);
643c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    }
653c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
663c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    receiver = new Response.Receiver() {
673c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      @Override public void onFailure(Failure failure) {
683c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        System.out.println("Failed: " + failure.exception());
693c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      }
703c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
713c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      @Override public boolean onResponse(Response response) throws IOException {
723c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        Response.Body body = response.body();
733c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        long total = SynchronousHttpClient.readAllAndClose(body.byteStream());
743c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        long finish = System.nanoTime();
753c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        if (VERBOSE) {
763c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller          long start = (Long) response.request().tag();
773c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller          System.out.printf("Transferred % 8d bytes in %4d ms%n",
783c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller              total, TimeUnit.NANOSECONDS.toMillis(finish - start));
793c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        }
803c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        requestsInFlight.decrementAndGet();
813c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        return true;
823c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      }
833c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    };
843c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
853c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
863c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  @Override public void enqueue(URL url) throws Exception {
873c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    requestsInFlight.incrementAndGet();
883c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    client.enqueue(new Request.Builder().tag(System.nanoTime()).url(url).build(), receiver);
893c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
903c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
913c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  @Override public synchronized boolean acceptingJobs() {
923c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    return requestsInFlight.get() < (concurrencyLevel + targetBacklog);
933c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
943c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller}
95