udp_socket_perftest.cc 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. // Copyright 2015 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. #include "base/bind.h"
  5. #include "base/memory/weak_ptr.h"
  6. #include "base/run_loop.h"
  7. #include "base/test/task_environment.h"
  8. #include "base/timer/elapsed_timer.h"
  9. #include "net/base/io_buffer.h"
  10. #include "net/base/ip_endpoint.h"
  11. #include "net/base/net_errors.h"
  12. #include "net/base/test_completion_callback.h"
  13. #include "net/log/net_log_source.h"
  14. #include "net/socket/udp_client_socket.h"
  15. #include "net/socket/udp_server_socket.h"
  16. #include "net/socket/udp_socket.h"
  17. #include "net/test/gtest_util.h"
  18. #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
  19. #include "testing/gmock/include/gmock/gmock.h"
  20. #include "testing/gtest/include/gtest/gtest.h"
  21. #include "testing/perf/perf_result_reporter.h"
  22. #include "testing/platform_test.h"
  23. using net::test::IsOk;
  24. namespace net {
  25. namespace {
  26. static constexpr char kMetricPrefixUDPSocket[] = "UDPSocketWrite.";
  27. static constexpr char kMetricElapsedTimeMs[] = "elapsed_time";
  28. static constexpr char kMetricWriteSpeedBytesPerSecond[] = "write_speed";
  29. perf_test::PerfResultReporter SetUpUDPSocketReporter(const std::string& story) {
  30. perf_test::PerfResultReporter reporter(kMetricPrefixUDPSocket, story);
  31. reporter.RegisterImportantMetric(kMetricElapsedTimeMs, "ms");
  32. reporter.RegisterImportantMetric(kMetricWriteSpeedBytesPerSecond,
  33. "bytesPerSecond_biggerIsBetter");
  34. return reporter;
  35. }
  36. class UDPSocketPerfTest : public PlatformTest {
  37. public:
  38. UDPSocketPerfTest()
  39. : buffer_(base::MakeRefCounted<IOBufferWithSize>(kPacketSize)) {}
  40. void DoneWritePacketsToSocket(UDPClientSocket* socket,
  41. int num_of_packets,
  42. base::OnceClosure* done_callback,
  43. int error) {
  44. WritePacketsToSocket(socket, num_of_packets, done_callback);
  45. }
  46. // Send |num_of_packets| to |socket|. Invoke |done_callback| when done.
  47. void WritePacketsToSocket(UDPClientSocket* socket,
  48. int num_of_packets,
  49. base::OnceClosure* done_callback);
  50. // Use non-blocking IO if |use_nonblocking_io| is true. This variable only
  51. // has effect on Windows.
  52. void WriteBenchmark(bool use_nonblocking_io);
  53. protected:
  54. static const int kPacketSize = 1024;
  55. scoped_refptr<IOBufferWithSize> buffer_;
  56. base::WeakPtrFactory<UDPSocketPerfTest> weak_factory_{this};
  57. };
  58. const int UDPSocketPerfTest::kPacketSize;
  59. // Creates and address from an ip/port and returns it in |address|.
  60. void CreateUDPAddress(const std::string& ip_str,
  61. uint16_t port,
  62. IPEndPoint* address) {
  63. IPAddress ip_address;
  64. if (!ip_address.AssignFromIPLiteral(ip_str))
  65. return;
  66. *address = IPEndPoint(ip_address, port);
  67. }
  68. void UDPSocketPerfTest::WritePacketsToSocket(UDPClientSocket* socket,
  69. int num_of_packets,
  70. base::OnceClosure* done_callback) {
  71. scoped_refptr<IOBufferWithSize> io_buffer =
  72. base::MakeRefCounted<IOBufferWithSize>(kPacketSize);
  73. memset(io_buffer->data(), 'G', kPacketSize);
  74. while (num_of_packets) {
  75. int rv = socket->Write(
  76. io_buffer.get(), io_buffer->size(),
  77. base::BindOnce(&UDPSocketPerfTest::DoneWritePacketsToSocket,
  78. weak_factory_.GetWeakPtr(), socket, num_of_packets - 1,
  79. done_callback),
  80. TRAFFIC_ANNOTATION_FOR_TESTS);
  81. if (rv == ERR_IO_PENDING)
  82. break;
  83. --num_of_packets;
  84. }
  85. if (!num_of_packets) {
  86. std::move(*done_callback).Run();
  87. return;
  88. }
  89. }
  90. void UDPSocketPerfTest::WriteBenchmark(bool use_nonblocking_io) {
  91. base::ElapsedTimer total_elapsed_timer;
  92. base::test::SingleThreadTaskEnvironment task_environment(
  93. base::test::SingleThreadTaskEnvironment::MainThreadType::IO);
  94. const uint16_t kPort = 9999;
  95. // Setup the server to listen.
  96. IPEndPoint bind_address;
  97. CreateUDPAddress("127.0.0.1", kPort, &bind_address);
  98. auto server = std::make_unique<UDPServerSocket>(nullptr, NetLogSource());
  99. if (use_nonblocking_io)
  100. server->UseNonBlockingIO();
  101. int rv = server->Listen(bind_address);
  102. ASSERT_THAT(rv, IsOk());
  103. // Setup the client.
  104. IPEndPoint server_address;
  105. CreateUDPAddress("127.0.0.1", kPort, &server_address);
  106. auto client = std::make_unique<UDPClientSocket>(DatagramSocket::DEFAULT_BIND,
  107. nullptr, NetLogSource());
  108. if (use_nonblocking_io)
  109. client->UseNonBlockingIO();
  110. rv = client->Connect(server_address);
  111. EXPECT_THAT(rv, IsOk());
  112. base::RunLoop run_loop;
  113. base::OnceClosure done_callback = run_loop.QuitClosure();
  114. base::ElapsedTimer write_elapsed_timer;
  115. int packets = 100000;
  116. client->SetSendBufferSize(1024);
  117. WritePacketsToSocket(client.get(), packets, &done_callback);
  118. run_loop.Run();
  119. double write_elapsed = write_elapsed_timer.Elapsed().InSecondsF();
  120. double total_elapsed = total_elapsed_timer.Elapsed().InMillisecondsF();
  121. auto reporter =
  122. SetUpUDPSocketReporter(use_nonblocking_io ? "nonblocking" : "blocking");
  123. reporter.AddResult(kMetricElapsedTimeMs, total_elapsed);
  124. reporter.AddResult(kMetricWriteSpeedBytesPerSecond,
  125. packets * 1024 / write_elapsed);
  126. }
  127. TEST_F(UDPSocketPerfTest, Write) {
  128. WriteBenchmark(false);
  129. }
  130. TEST_F(UDPSocketPerfTest, WriteNonBlocking) {
  131. WriteBenchmark(true);
  132. }
  133. } // namespace
  134. } // namespace net