Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(527)

Side by Side Diff: net/url_request/url_request_quic_perftest.cc

Issue 2875083002: Add url_request_quic_perftest.cc (Closed)
Patch Set: Use final result from MemoryDumpManager Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/BUILD.gn ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <inttypes.h>
6
7 #include <memory>
8
9 #include "base/callback.h"
10 #include "base/files/file_path.h"
11 #include "base/memory/ptr_util.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/run_loop.h"
14 #include "base/single_thread_task_runner.h"
15 #include "base/strings/string_number_conversions.h"
16 #include "base/strings/stringprintf.h"
17 #include "base/time/time.h"
18 #include "base/trace_event/memory_dump_manager.h"
19 #include "base/trace_event/memory_dump_request_args.h"
20 #include "base/trace_event/process_memory_dump.h"
21 #include "base/trace_event/trace_config.h"
22 #include "base/trace_event/trace_config_memory_test_util.h"
23 #include "base/trace_event/trace_event_argument.h"
24 #include "base/trace_event/trace_log.h"
25 #include "net/base/load_timing_info.h"
26 #include "net/cert/mock_cert_verifier.h"
27 #include "net/dns/mapped_host_resolver.h"
28 #include "net/dns/mock_host_resolver.h"
29 #include "net/http/http_status_code.h"
30 #include "net/quic/chromium/crypto/proof_source_chromium.h"
31 #include "net/quic/test_tools/crypto_test_utils.h"
32 #include "net/test/cert_test_util.h"
33 #include "net/test/embedded_test_server/embedded_test_server.h"
34 #include "net/test/embedded_test_server/http_response.h"
35 #include "net/test/gtest_util.h"
36 #include "net/test/test_data_directory.h"
37 #include "net/tools/quic/quic_http_response_cache.h"
38 #include "net/tools/quic/quic_simple_server.h"
39 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
40 #include "net/url_request/url_request.h"
41 #include "net/url_request/url_request_test_util.h"
42 #include "testing/gmock/include/gmock/gmock.h"
43 #include "testing/gtest/include/gtest/gtest.h"
44 #include "testing/perf/perf_test.h"
45 #include "url/gurl.h"
46
47 using testing::_;
48 using testing::Invoke;
49
50 namespace net {
51
52 namespace {
53
54 const int kAltSvcPort = 6121;
55 const char kOriginHost[] = "mail.example.com";
56 const char kAltSvcHost[] = "test.example.com";
57 // Used as a simple response from the server.
58 const char kHelloPath[] = "/hello.txt";
59 const char kHelloAltSvcResponse[] = "Hello from QUIC Server";
60 const char kHelloOriginResponse[] = "Hello from TCP Server";
61 const int kHelloStatus = 200;
62
63 std::unique_ptr<test_server::HttpResponse> HandleRequest(
64 const test_server::HttpRequest& request) {
65 std::unique_ptr<test_server::BasicHttpResponse> http_response(
66 new test_server::BasicHttpResponse());
67 http_response->AddCustomHeader(
68 "Alt-Svc", base::StringPrintf(
69 "quic=\"%s:%d\"; v=\"%u\"", kAltSvcHost, kAltSvcPort,
70 HttpNetworkSession::Params().quic_supported_versions[0]));
71 http_response->set_code(HTTP_OK);
72 http_response->set_content(kHelloOriginResponse);
73 http_response->set_content_type("text/plain");
74 return std::move(http_response);
75 }
76
77 void PrintPerfTest(const std::string& name,
78 int value,
79 const std::string& unit) {
80 const ::testing::TestInfo* test_info =
81 ::testing::UnitTest::GetInstance()->current_test_info();
82 perf_test::PrintResult(test_info->test_case_name(),
83 std::string(".") + test_info->name(), name,
84 static_cast<double>(value), unit, true);
85 }
86
87 // This mocks the RequestGlobalDumpFunction which is typically handled by
88 // process_local_dump_manager_impl.cc.
89 class GlobalMemoryDumpHandler {
90 public:
91 MOCK_METHOD2(
92 RequestGlobalMemoryDump,
93 void(const base::trace_event::MemoryDumpRequestArgs& args,
94 const base::trace_event::GlobalMemoryDumpCallback& callback));
95 GlobalMemoryDumpHandler() {}
96 };
97
98 // A TestURLRequestContext that records memory dump stats when OnMemoryDump() is
99 // invoked.
100 class MemoryTestURLRequestContext : public TestURLRequestContext {
101 public:
102 MemoryTestURLRequestContext() : TestURLRequestContext(true) {}
103
104 bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
105 base::trace_event::ProcessMemoryDump* pmd) override {
106 bool result = TestURLRequestContext::OnMemoryDump(args, pmd);
107
108 const base::trace_event::MemoryAllocatorDump* url_request_context_dump =
109 pmd->GetAllocatorDump(
110 base::StringPrintf("net/url_request_context/unknown/0x%" PRIxPTR,
111 reinterpret_cast<uintptr_t>(this)));
112 url_request_context_dump_attrs_ =
113 url_request_context_dump->attributes_for_testing()->ToBaseValue();
114
115 const base::trace_event::MemoryAllocatorDump* quic_stream_factory_dump =
116 pmd->GetAllocatorDump(base::StringPrintf(
117 "net/http_network_session_%p/quic_stream_factory",
118 http_transaction_factory()->GetSession()));
119 quic_stream_factory_attrs_ =
120 quic_stream_factory_dump->attributes_for_testing()->ToBaseValue();
121
122 const base::trace_event::MemoryAllocatorDump* http_stream_factory_dump =
123 pmd->GetAllocatorDump(
124 base::StringPrintf("net/http_network_session_%p/stream_factory",
125 http_transaction_factory()->GetSession()));
126 EXPECT_EQ(nullptr, http_stream_factory_dump);
127 return result;
128 }
129
130 std::unique_ptr<base::Value> url_request_context_dump_attrs_;
131 std::unique_ptr<base::Value> quic_stream_factory_attrs_;
132 };
133
134 class URLRequestQuicPerfTest : public ::testing::Test {
135 public:
136 void ProcessDumpRecordingCallbackAdapter(
137 base::trace_event::GlobalMemoryDumpCallback callback,
138 uint64_t dump_guid,
139 bool success,
140 const base::Optional<base::trace_event::MemoryDumpCallbackResult>&
141 result) {
142 if (result.has_value()) {
143 results_.push_back(result.value());
144 }
145 callback.Run(dump_guid, success);
146 }
147
148 protected:
149 URLRequestQuicPerfTest() : message_loop_(new base::MessageLoopForIO()) {
150 InitializeMemoryDumpManager();
151 mdm_->set_dumper_registrations_ignored_for_testing(false);
152 context_ = base::MakeUnique<MemoryTestURLRequestContext>();
153 mdm_->set_dumper_registrations_ignored_for_testing(true);
154 StartTcpServer();
155 StartQuicServer();
156
157 // Host mapping.
158 std::unique_ptr<MockHostResolver> resolver(new MockHostResolver());
159 resolver->rules()->AddRule(kAltSvcHost, "127.0.0.1");
160 host_resolver_.reset(new MappedHostResolver(std::move(resolver)));
161 std::string map_rule = base::StringPrintf("MAP %s 127.0.0.1:%d",
162 kOriginHost, tcp_server_->port());
163 EXPECT_TRUE(host_resolver_->AddRuleFromString(map_rule));
164
165 std::unique_ptr<HttpNetworkSession::Params> params(
166 new HttpNetworkSession::Params);
167 params->cert_verifier = &cert_verifier_;
168 params->enable_quic = true;
169 params->enable_user_alternate_protocol_ports = true;
170 context_->set_host_resolver(host_resolver_.get());
171 context_->set_http_network_session_params(std::move(params));
172 context_->set_cert_verifier(&cert_verifier_);
173 context_->Init();
174 }
175
176 void TearDown() override {
177 if (quic_server_) {
178 quic_server_->Shutdown();
nednguyen 2017/05/27 00:28:39 what about shutting down tcp_server_?
xunjieli 2017/05/29 20:16:00 The destructor of EmbeddedTestServer calls Shutdow
nednguyen 2017/05/30 13:31:38 I see. Can you add comment explaining why we don't
xunjieli 2017/06/02 20:43:59 Done.
179 // If possible, deliver the conncetion close packet to the client before
180 // destruct the TestURLRequestContext.
181 base::RunLoop().RunUntilIdle();
182 }
183 mdm_.reset();
184 message_loop_.reset();
185 }
186
187 std::unique_ptr<URLRequest> CreateRequest(const GURL& url,
188 RequestPriority priority,
189 URLRequest::Delegate* delegate) {
190 return context_->CreateRequest(url, priority, delegate,
191 TRAFFIC_ANNOTATION_FOR_TESTS);
192 }
193
194 // Turns a Closure into a GlobalMemoryDumpCallback and takes care of posting
195 // the closure on the correct task runner.
196 void GlobalDumpCallbackAdapter(
197 scoped_refptr<base::SingleThreadTaskRunner> task_runner,
198 base::Closure closure,
199 uint64_t dump_guid,
200 bool success) {
201 task_runner->PostTask(FROM_HERE, closure);
202 }
203
204 void RequestGlobalDumpAndWait(
205 base::trace_event::MemoryDumpType dump_type,
206 base::trace_event::MemoryDumpLevelOfDetail level_of_detail) {
207 base::RunLoop run_loop;
208 base::trace_event::GlobalMemoryDumpCallback callback =
209 base::Bind(&URLRequestQuicPerfTest::GlobalDumpCallbackAdapter,
210 base::Unretained(this), base::ThreadTaskRunnerHandle::Get(),
211 run_loop.QuitClosure());
212 mdm_->RequestGlobalDump(dump_type, level_of_detail, callback);
213 run_loop.Run();
214 }
215
216 MemoryTestURLRequestContext* context() const { return context_.get(); }
nednguyen 2017/05/27 00:28:39 why defining this if we can just use context_-> in
xunjieli 2017/05/29 20:16:00 It's hard to reason about the tests if the tests s
nednguyen 2017/05/30 13:31:38 I think if the accessor just returns the non-const
xunjieli 2017/06/02 20:43:59 I hear you, but I find it easier to reason about t
217
218 const std::vector<base::trace_event::MemoryDumpCallbackResult>* GetResults()
219 const {
220 return &results_;
221 }
222
223 GlobalMemoryDumpHandler global_dump_handler_;
224 std::unique_ptr<base::trace_event::MemoryDumpManager> mdm_;
225
226 private:
227 void InitializeMemoryDumpManager() {
228 mdm_ = base::trace_event::MemoryDumpManager::CreateInstanceForTesting();
229 mdm_->set_dumper_registrations_ignored_for_testing(true);
230 mdm_->Initialize(
231 BindRepeating(&GlobalMemoryDumpHandler::RequestGlobalMemoryDump,
232 base::Unretained(&global_dump_handler_)),
233 /*is_coordinator=*/false);
234 }
235
236 void StartQuicServer() {
237 net::QuicConfig config;
238 response_cache_.AddSimpleResponse(kOriginHost, kHelloPath, kHelloStatus,
239 kHelloAltSvcResponse);
240 quic_server_.reset(new QuicSimpleServer(
241 test::crypto_test_utils::ProofSourceForTesting(), config,
242 net::QuicCryptoServerConfig::ConfigOptions(), AllSupportedVersions(),
243 &response_cache_));
244 int rv = quic_server_->Listen(
245 net::IPEndPoint(net::IPAddress::IPv4AllZeros(), kAltSvcPort));
246 ASSERT_GE(rv, 0) << "Quic server fails to start";
247
248 CertVerifyResult verify_result;
249 verify_result.verified_cert = ImportCertFromFile(
250 GetTestCertsDirectory(), "quic_test.example.com.crt");
251 cert_verifier_.AddResultForCert(verify_result.verified_cert.get(),
252 verify_result, OK);
253 }
254
255 void StartTcpServer() {
256 tcp_server_ = base::MakeUnique<EmbeddedTestServer>(
257 net::EmbeddedTestServer::TYPE_HTTPS);
258 tcp_server_->RegisterRequestHandler(base::Bind(&HandleRequest));
259 ASSERT_TRUE(tcp_server_->Start()) << "HTTP/1.1 server fails to start";
260
261 CertVerifyResult verify_result;
262 verify_result.verified_cert = tcp_server_->GetCertificate();
263 cert_verifier_.AddResultForCert(tcp_server_->GetCertificate(),
264 verify_result, OK);
265 }
266
267 std::unique_ptr<MappedHostResolver> host_resolver_;
268 std::unique_ptr<EmbeddedTestServer> tcp_server_;
269 std::unique_ptr<QuicSimpleServer> quic_server_;
270 std::unique_ptr<base::MessageLoop> message_loop_;
271 std::unique_ptr<MemoryTestURLRequestContext> context_;
272 std::vector<base::trace_event::MemoryDumpCallbackResult> results_;
273 QuicHttpResponseCache response_cache_;
274 MockCertVerifier cert_verifier_;
275 };
276
277 } // namespace
278
279 TEST_F(URLRequestQuicPerfTest, TestGetRequest) {
280 bool quic_succeeded = false;
281 GURL url(base::StringPrintf("https://%s%s", kOriginHost, kHelloPath));
282 base::TimeTicks start = base::TimeTicks::Now();
283 const int kNumRequest = 1000;
284 for (int i = 0; i < kNumRequest; ++i) {
285 TestDelegate delegate;
286 std::unique_ptr<URLRequest> request =
287 CreateRequest(url, DEFAULT_PRIORITY, &delegate);
288
289 request->Start();
290 EXPECT_TRUE(request->is_pending());
291 base::RunLoop().Run();
292
293 EXPECT_TRUE(request->status().is_success());
294 if (delegate.data_received() == kHelloAltSvcResponse) {
295 quic_succeeded = true;
296 } else {
297 EXPECT_EQ(kHelloOriginResponse, delegate.data_received());
298 }
299 }
300 base::TimeTicks end = base::TimeTicks::Now();
301 PrintPerfTest("time", (end - start).InMilliseconds() / kNumRequest, "ms");
302
303 EXPECT_TRUE(quic_succeeded);
304 base::trace_event::TraceLog::GetInstance()->SetEnabled(
305 base::trace_event::TraceConfig(
306 base::trace_event::MemoryDumpManager::kTraceCategory, ""),
307 base::trace_event::TraceLog::RECORDING_MODE);
308
309 EXPECT_CALL(global_dump_handler_, RequestGlobalMemoryDump(_, _))
nednguyen 2017/05/27 00:28:39 silly question, what is this mock test for?
xunjieli 2017/05/29 20:16:00 I am following the MemoryDumpManagerTest example.
nednguyen 2017/05/30 13:31:38 It seems a bit unintuitive to me to rely on gtest
xunjieli 2017/06/02 20:43:59 Acknowledged.
310 .WillOnce(Invoke([this](
311 const base::trace_event::MemoryDumpRequestArgs& args,
312 const base::trace_event::GlobalMemoryDumpCallback&
313 callback) {
314 base::trace_event::ProcessMemoryDumpCallback process_callback =
315 Bind(&URLRequestQuicPerfTest::ProcessDumpRecordingCallbackAdapter,
316 base::Unretained(this), callback);
317 mdm_->CreateProcessDump(args, process_callback);
318 }));
319
320 RequestGlobalDumpAndWait(
321 base::trace_event::MemoryDumpType::EXPLICITLY_TRIGGERED,
322 base::trace_event::MemoryDumpLevelOfDetail::LIGHT);
323 base::trace_event::TraceLog::GetInstance()->SetDisabled();
324
325 // Check ProcessMemoryDump stats.
326 ASSERT_EQ(1u, GetResults()->size());
327 base::trace_event::MemoryDumpCallbackResult result = GetResults()->front();
328 PrintPerfTest("chrome_malloc_total_kb", result.chrome_dump.malloc_total_kb,
329 "kB");
330 PrintPerfTest("os_resident_set_kb", result.os_dump.resident_set_kb, "kB");
331
332 // Check URLRequestContext::OnMemoryDump() stats.
333 base::DictionaryValue* attrs;
334 ASSERT_TRUE(
335 context()->url_request_context_dump_attrs_->GetAsDictionary(&attrs));
336 base::DictionaryValue* object_count_attrs;
337 ASSERT_TRUE(attrs->GetDictionary(
338 base::trace_event::MemoryAllocatorDump::kNameObjectCount,
339 &object_count_attrs));
340 std::string object_count_str;
341 ASSERT_TRUE(object_count_attrs->GetString("value", &object_count_str));
342 EXPECT_EQ("0", object_count_str);
343
344 ASSERT_TRUE(context()->quic_stream_factory_attrs_->GetAsDictionary(&attrs));
345 ASSERT_TRUE(attrs->GetDictionary("active_jobs", &object_count_attrs));
346 ASSERT_TRUE(object_count_attrs->GetString("value", &object_count_str));
347 EXPECT_EQ("0", object_count_str);
348 int object_count = -1;
349 ASSERT_TRUE(base::HexStringToInt(object_count_str, &object_count));
350 PrintPerfTest("active_quic_jobs", object_count, "count");
351
352 ASSERT_TRUE(attrs->GetDictionary("all_sessions", &object_count_attrs));
353 ASSERT_TRUE(object_count_attrs->GetString("value", &object_count_str));
354 EXPECT_EQ("1", object_count_str);
355 ASSERT_TRUE(base::HexStringToInt(object_count_str, &object_count));
356 PrintPerfTest("active_quic_sessions", object_count, "count");
357 }
358
359 } // namespace net
OLDNEW
« no previous file with comments | « net/BUILD.gn ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698