URLConnectionBenchmark.java revision 5a7833b406bb2716b057d3ed923f22f1f86b2a20
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package benchmarks.regression;
18
19import com.google.caliper.Param;
20import com.google.caliper.SimpleBenchmark;
21import com.google.mockwebserver.MockResponse;
22import com.google.mockwebserver.MockWebServer;
23import java.io.IOException;
24import java.io.InputStream;
25import java.net.HttpURLConnection;
26import java.net.URL;
27import java.net.URLConnection;
28
29public final class URLConnectionBenchmark extends SimpleBenchmark {
30
31    @Param({"0", "1024", "1048576"}) private int bodySize;
32    @Param({"2048"}) private int chunkSize;
33    @Param({"1024"}) private int readBufferSize;
34    @Param private ResponseHeaders responseHeaders;
35    @Param private TransferEncoding transferEncoding;
36    private byte[] readBuffer;
37
38    private MockWebServer server;
39    private URL url;
40
41    protected void setUp() throws Exception {
42        readBuffer = new byte[readBufferSize];
43        server = new MockWebServer();
44
45        MockResponse response = new MockResponse();
46        responseHeaders.apply(response);
47        transferEncoding.setBody(response, bodySize, chunkSize);
48        server.enqueue(response);
49
50        // keep serving the same response for all iterations
51        server.setSingleResponse(true);
52        server.play();
53
54        url = server.getUrl("/");
55        get(); // ensure the server has started its threads, etc.
56    }
57
58    protected void tearDown() throws Exception {
59        /*
60         * Entice the server to shut itself down gracefully. The shutdown method
61         * doesn't work on Dalvik because socket.close() doesn't release blocked
62         * threads. Instead, read the last continuously-served request, and then
63         * cause the server to close the otherwise-reusable HTTP connection.
64         */
65        server.setSingleResponse(false);
66        get();
67        server.shutdown();
68    }
69
70    public int timeGet(int reps) throws IOException {
71        int totalBytesRead = 0;
72        for (int i = 0; i < reps; i++) {
73            totalBytesRead += get();
74        }
75        return totalBytesRead;
76    }
77
78    private int get() throws IOException {
79        int totalBytesRead = 0;
80        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
81        // URLConnection connection = url.openConnection();
82        InputStream in = connection.getInputStream();
83        int count;
84        while ((count = in.read(readBuffer)) != -1) {
85            totalBytesRead += count;
86        }
87        return totalBytesRead;
88    }
89
90    enum TransferEncoding {
91        FIXED_LENGTH,
92        CHUNKED;
93
94        void setBody(MockResponse response, int bodySize, int chunkSize) throws IOException {
95            if (this == TransferEncoding.FIXED_LENGTH) {
96                response.setBody(new byte[bodySize]);
97            } else if (this == TransferEncoding.CHUNKED) {
98                response.setChunkedBody(new byte[bodySize], chunkSize);
99            }
100        }
101    }
102
103    enum ResponseHeaders {
104        MINIMAL,
105        TYPICAL;
106
107        void apply(MockResponse response) {
108            if (this == TYPICAL) {
109                /* from http://api.twitter.com/1/statuses/public_timeline.json */
110                response.addHeader("Date: Wed, 30 Jun 2010 17:57:39 GMT");
111                response.addHeader("Server: hi");
112                response.addHeader("X-RateLimit-Remaining: 0");
113                response.addHeader("X-Runtime: 0.01637");
114                response.addHeader("Content-Type: application/json; charset=utf-8");
115                response.addHeader("X-RateLimit-Class: api_whitelisted");
116                response.addHeader("Cache-Control: no-cache, max-age=300");
117                response.addHeader("X-RateLimit-Reset: 1277920980");
118                response.addHeader("Set-Cookie: _twitter_sess=BAh7EDoOcmV0dXJuX3RvIjZodHRwOi8vZGV2L"
119                        + "nR3aXR0ZXIuY29tL3BhZ2Vz%250AL3NpZ25faW5fd2l0aF90d2l0dGVyOgxjc3JmX2lkIiUw"
120                        + "ODFhNGY2NTM5NjRm%250ANjY1N2M2NzcwNWI0MDlmZGZjZjoVaW5fbmV3X3VzZXJfZmxvdzA"
121                        + "6EXRyYW5z%250AX3Byb21wdDAiKXNob3dfZGlzY292ZXJhYmlsaXR5X2Zvcl9qZXNzZXdpbH"
122                        + "Nv%250AbjA6E3Nob3dfaGVscF9saW5rMDoTcGFzc3dvcmRfdG9rZW4iLWUyYjlhNmM3%250A"
123                        + "MWJiNzI3NWNlZDI1NDY3MGMzZWNmMTE0MjI4N2EyNGE6D2NyZWF0ZWRfYXRs%250AKwhiM%2"
124                        + "52F6JKQE6CXVzZXJpA8tE3iIKZmxhc2hJQzonQWN0aW9uQ29udHJvbGxl%250Acjo6Rmxhc2"
125                        + "g6OkZsYXNoSGFzaHsABjoKQHVzZWR7ADoHaWQiJWZmMTNhM2Qx%250AZTU1YTkzMmYyMWM0M"
126                        + "GNhZjU4NDVjMTQz--11250628c85830219438eb7eba96a541a9af4098; domain=.twitt"
127                        + "er.com; path=/");
128                response.addHeader("Expires: Wed, 30 Jun 2010 18:02:39 GMT");
129                response.addHeader("Vary: Accept-Encoding");
130            }
131        }
132    }
133}
134