Index: lldb/trunk/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp =================================================================== --- lldb/trunk/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp +++ lldb/trunk/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp @@ -445,7 +445,7 @@ { // Scope for the scoped timeout object process_gdb_remote::GDBRemoteCommunication::ScopedTimeout timeout( - m_gdb_client, 5); + m_gdb_client, std::chrono::seconds(5)); arg_packet_err = m_gdb_client.SendArgumentsPacket(launch_info); } Index: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp +++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp @@ -188,8 +188,11 @@ const size_t max_response_retries = 3; for (size_t i = 0; i < max_response_retries; ++i) { - packet_result = - ReadPacket(response, GetPacketTimeoutInMicroSeconds(), true); + packet_result = ReadPacket( + response, std::chrono::duration_cast( + GetPacketTimeout()) + .count(), + true); // Make sure we received a response if (packet_result != PacketResult::Success) return packet_result; Index: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h =================================================================== --- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h +++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h @@ -24,7 +24,6 @@ #include "lldb/Core/Listener.h" #include "lldb/Host/HostThread.h" #include "lldb/Host/Predicate.h" -#include "lldb/Host/TimeValue.h" #include "lldb/Interpreter/Args.h" #include "lldb/lldb-public.h" @@ -83,12 +82,13 @@ // created ScopedTimeout object got out of scope class ScopedTimeout { public: - ScopedTimeout(GDBRemoteCommunication &gdb_comm, uint32_t timeout); + ScopedTimeout(GDBRemoteCommunication &gdb_comm, + std::chrono::seconds timeout); ~ScopedTimeout(); private: GDBRemoteCommunication &m_gdb_comm; - uint32_t m_saved_timeout; + std::chrono::seconds m_saved_timeout; }; GDBRemoteCommunication(const char *comm_name, const char *listener_name); @@ -112,19 +112,16 @@ // Set the global packet timeout. // // For clients, this is the timeout that gets used when sending - // packets and waiting for responses. For servers, this might not - // get used, and if it doesn't this should be moved to the - // GDBRemoteCommunicationClient. + // packets and waiting for responses. For servers, this is used when waiting + // for ACKs. //------------------------------------------------------------------ - uint32_t SetPacketTimeout(uint32_t packet_timeout) { - const uint32_t old_packet_timeout = m_packet_timeout; + std::chrono::seconds SetPacketTimeout(std::chrono::seconds packet_timeout) { + const auto old_packet_timeout = m_packet_timeout; m_packet_timeout = packet_timeout; return old_packet_timeout; } - uint32_t GetPacketTimeoutInMicroSeconds() const { - return m_packet_timeout * TimeValue::MicroSecPerSec; - } + std::chrono::seconds GetPacketTimeout() const { return m_packet_timeout; } //------------------------------------------------------------------ // Start a debugserver instance on the current host using the @@ -215,7 +212,7 @@ mutable bool m_dumped_to_log; }; - uint32_t m_packet_timeout; + std::chrono::seconds m_packet_timeout; uint32_t m_echo_number; LazyBool m_supports_qEcho; History m_history; Index: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp +++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp @@ -28,7 +28,6 @@ #include "lldb/Host/Socket.h" #include "lldb/Host/StringConvert.h" #include "lldb/Host/ThreadLauncher.h" -#include "lldb/Host/TimeValue.h" #include "lldb/Target/Platform.h" #include "lldb/Target/Process.h" #include "llvm/ADT/SmallString.h" @@ -262,8 +261,11 @@ GDBRemoteCommunication::PacketResult GDBRemoteCommunication::GetAck() { StringExtractorGDBRemote packet; - PacketResult result = - ReadPacket(packet, GetPacketTimeoutInMicroSeconds(), false); + PacketResult result = ReadPacket( + packet, + std::chrono::duration_cast(GetPacketTimeout()) + .count(), + false); if (result == PacketResult::Success) { if (packet.GetResponseType() == StringExtractorGDBRemote::ResponseType::eAck) @@ -1320,7 +1322,7 @@ void GDBRemoteCommunication::DumpHistory(Stream &strm) { m_history.Dump(strm); } GDBRemoteCommunication::ScopedTimeout::ScopedTimeout( - GDBRemoteCommunication &gdb_comm, uint32_t timeout) + GDBRemoteCommunication &gdb_comm, std::chrono::seconds timeout) : m_gdb_comm(gdb_comm) { m_saved_timeout = m_gdb_comm.SetPacketTimeout(timeout); } Index: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h =================================================================== --- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -244,7 +244,7 @@ const ArchSpec &GetHostArchitecture(); - uint32_t GetHostDefaultPacketTimeout(); + std::chrono::seconds GetHostDefaultPacketTimeout(); const ArchSpec &GetProcessArchitecture(); @@ -556,7 +556,7 @@ // qGDBServerVersion is not supported uint32_t m_gdb_server_version; // from reply to qGDBServerVersion, zero if // qGDBServerVersion is not supported - uint32_t m_default_packet_timeout; + std::chrono::seconds m_default_packet_timeout; uint64_t m_max_packet_size; // as returned by qSupported std::string m_qSupported_response; // the complete response to qSupported Index: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -26,7 +26,6 @@ #include "lldb/Core/StreamString.h" #include "lldb/Host/HostInfo.h" #include "lldb/Host/StringConvert.h" -#include "lldb/Host/TimeValue.h" #include "lldb/Interpreter/Args.h" #include "lldb/Symbol/Symbol.h" #include "lldb/Target/MemoryRegionInfo.h" @@ -203,11 +202,8 @@ // longer than normal to receive a reply. Wait at least 6 seconds for a // reply to this packet. - const uint32_t minimum_timeout = 6; - uint32_t old_timeout = GetPacketTimeoutInMicroSeconds() / - lldb_private::TimeValue::MicroSecPerSec; - GDBRemoteCommunication::ScopedTimeout timeout( - *this, std::max(old_timeout, minimum_timeout)); + ScopedTimeout timeout( + *this, std::max(GetPacketTimeout(), std::chrono::seconds(6))); StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse("QStartNoAckMode", response, false) == @@ -319,7 +315,7 @@ m_hostname.clear(); m_gdb_server_name.clear(); m_gdb_server_version = UINT32_MAX; - m_default_packet_timeout = 0; + m_default_packet_timeout = std::chrono::seconds(0); m_max_packet_size = 0; m_qSupported_response.clear(); m_supported_async_json_packets_is_valid = false; @@ -1202,7 +1198,9 @@ if (m_watchpoints_trigger_after_instruction != eLazyBoolCalculate) ++num_keys_decoded; } else if (name.equals("default_packet_timeout")) { - if (!value.getAsInteger(0, m_default_packet_timeout)) { + uint32_t timeout_seconds; + if (!value.getAsInteger(0, timeout_seconds)) { + m_default_packet_timeout = std::chrono::seconds(timeout_seconds); SetPacketTimeout(m_default_packet_timeout); ++num_keys_decoded; } @@ -1331,7 +1329,8 @@ return m_host_arch; } -uint32_t GDBRemoteCommunicationClient::GetHostDefaultPacketTimeout() { +std::chrono::seconds +GDBRemoteCommunicationClient::GetHostDefaultPacketTimeout() { if (m_qHostInfo_is_valid == eLazyBoolCalculate) GetHostInfo(); return m_default_packet_timeout; @@ -2023,7 +2022,7 @@ StringExtractorGDBRemote response; // Increase timeout as the first qfProcessInfo packet takes a long time // on Android. The value of 1min was arrived at empirically. - GDBRemoteCommunication::ScopedTimeout timeout(*this, 60); + ScopedTimeout timeout(*this, std::chrono::seconds(60)); if (SendPacketAndWaitForResponse(packet.GetString(), response, false) == PacketResult::Success) { do { @@ -2133,26 +2132,27 @@ } } -template T calculate_standard_deviation(const std::vector &v) { - T sum = std::accumulate(std::begin(v), std::end(v), T(0)); - T mean = sum / (T)v.size(); - T accum = T(0); - std::for_each(std::begin(v), std::end(v), [&](const T d) { - T delta = d - mean; +std::chrono::duration calculate_standard_deviation( + const std::vector> &v) { + using Dur = std::chrono::duration; + Dur sum = std::accumulate(std::begin(v), std::end(v), Dur()); + Dur mean = sum / v.size(); + float accum = 0; + for (auto d : v) { + float delta = (d - mean).count(); accum += delta * delta; - }); + }; - T stdev = sqrt(accum / (v.size() - 1)); - return stdev; + return Dur(sqrtf(accum / (v.size() - 1))); } void GDBRemoteCommunicationClient::TestPacketSpeed(const uint32_t num_packets, uint32_t max_send, uint32_t max_recv, bool json, Stream &strm) { + using namespace std::chrono; + uint32_t i; - TimeValue start_time, end_time; - uint64_t total_time_nsec; if (SendSpeedTestPacket(0, 0)) { StreamString packet; if (json) @@ -2166,7 +2166,7 @@ uint32_t result_idx = 0; uint32_t send_size; - std::vector packet_times; + std::vector> packet_times; for (send_size = 0; send_size <= max_send; send_size ? send_size *= 2 : send_size = 4) { @@ -2176,46 +2176,40 @@ packet_times.clear(); // Test how long it takes to send 'num_packets' packets - start_time = TimeValue::Now(); + const auto start_time = steady_clock::now(); for (i = 0; i < num_packets; ++i) { - TimeValue packet_start_time = TimeValue::Now(); + const auto packet_start_time = steady_clock::now(); StringExtractorGDBRemote response; SendPacketAndWaitForResponse(packet.GetString(), response, false); - TimeValue packet_end_time = TimeValue::Now(); - uint64_t packet_time_nsec = - packet_end_time.GetAsNanoSecondsSinceJan1_1970() - - packet_start_time.GetAsNanoSecondsSinceJan1_1970(); - packet_times.push_back((float)packet_time_nsec); - } - end_time = TimeValue::Now(); - total_time_nsec = end_time.GetAsNanoSecondsSinceJan1_1970() - - start_time.GetAsNanoSecondsSinceJan1_1970(); + const auto packet_end_time = steady_clock::now(); + packet_times.push_back(packet_end_time - packet_start_time); + } + const auto end_time = steady_clock::now(); + const auto total_time = end_time - start_time; float packets_per_second = - (((float)num_packets) / (float)total_time_nsec) * - (float)TimeValue::NanoSecPerSec; - float total_ms = - (float)total_time_nsec / (float)TimeValue::NanoSecPerMilliSec; - float average_ms_per_packet = total_ms / num_packets; - const float standard_deviation = - calculate_standard_deviation(packet_times); + ((float)num_packets) / duration(total_time).count(); + auto average_per_packet = total_time / num_packets; + const duration standard_deviation = + calculate_standard_deviation(packet_times); if (json) { strm.Printf("%s\n {\"send_size\" : %6" PRIu32 ", \"recv_size\" : %6" PRIu32 ", \"total_time_nsec\" : %12" PRIu64 ", \"standard_deviation_nsec\" : %9" PRIu64 " }", result_idx > 0 ? "," : "", send_size, recv_size, - total_time_nsec, (uint64_t)standard_deviation); + duration_cast(total_time).count(), + duration_cast(standard_deviation).count()); ++result_idx; } else { strm.Printf( - "qSpeedTest(send=%-7u, recv=%-7u) in %" PRIu64 ".%9.9" PRIu64 + "qSpeedTest(send=%-7u, recv=%-7u) in %.9f" " sec for %9.2f packets/sec (%10.6f ms per packet) with standard " "deviation of %10.6f ms\n", - send_size, recv_size, total_time_nsec / TimeValue::NanoSecPerSec, - total_time_nsec % TimeValue::NanoSecPerSec, packets_per_second, - average_ms_per_packet, - standard_deviation / (float)TimeValue::NanoSecPerMilliSec); + send_size, recv_size, duration(total_time).count(), + packets_per_second, + duration(average_per_packet).count(), + duration(standard_deviation).count()); } strm.Flush(); } @@ -2241,7 +2235,7 @@ // If we have a receive size, test how long it takes to receive 4MB of // data if (recv_size > 0) { - start_time = TimeValue::Now(); + const auto start_time = steady_clock::now(); uint32_t bytes_read = 0; uint32_t packet_count = 0; while (bytes_read < k_recv_amount) { @@ -2250,35 +2244,31 @@ bytes_read += recv_size; ++packet_count; } - end_time = TimeValue::Now(); - total_time_nsec = end_time.GetAsNanoSecondsSinceJan1_1970() - - start_time.GetAsNanoSecondsSinceJan1_1970(); - float mb_second = ((((float)k_recv_amount) / (float)total_time_nsec) * - (float)TimeValue::NanoSecPerSec) / + const auto end_time = steady_clock::now(); + const auto total_time = end_time - start_time; + float mb_second = ((float)k_recv_amount) / + duration(total_time).count() / (1024.0 * 1024.0); float packets_per_second = - (((float)packet_count) / (float)total_time_nsec) * - (float)TimeValue::NanoSecPerSec; - float total_ms = - (float)total_time_nsec / (float)TimeValue::NanoSecPerMilliSec; - float average_ms_per_packet = total_ms / packet_count; + ((float)packet_count) / duration(total_time).count(); + const auto average_per_packet = total_time / packet_count; if (json) { strm.Printf("%s\n {\"send_size\" : %6" PRIu32 ", \"recv_size\" : %6" PRIu32 ", \"total_time_nsec\" : %12" PRIu64 " }", result_idx > 0 ? "," : "", send_size, recv_size, - total_time_nsec); + duration_cast(total_time).count()); ++result_idx; } else { strm.Printf("qSpeedTest(send=%-7u, recv=%-7u) %6u packets needed to " - "receive %2.1fMB in %" PRIu64 ".%9.9" PRIu64 + "receive %2.1fMB in %.9f" " sec for %f MB/sec for %9.2f packets/sec (%10.6f ms per " "packet)\n", send_size, recv_size, packet_count, k_recv_amount_mb, - total_time_nsec / TimeValue::NanoSecPerSec, - total_time_nsec % TimeValue::NanoSecPerSec, mb_second, - packets_per_second, average_ms_per_packet); + duration(total_time).count(), mb_second, + packets_per_second, + duration(average_per_packet).count()); } strm.Flush(); } @@ -2335,7 +2325,7 @@ } } // give the process a few seconds to startup - GDBRemoteCommunication::ScopedTimeout timeout(*this, 10); + ScopedTimeout timeout(*this, std::chrono::seconds(10)); if (SendPacketAndWaitForResponse(stream.GetString(), response, false) == PacketResult::Success) { Index: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -34,7 +34,6 @@ #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" #include "lldb/Host/StringConvert.h" -#include "lldb/Host/TimeValue.h" #include "lldb/Host/common/NativeProcessProtocol.h" #include "lldb/Host/common/NativeRegisterContext.h" #include "lldb/Host/common/NativeThreadProtocol.h" Index: lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -46,7 +46,6 @@ #include "lldb/Host/StringConvert.h" #include "lldb/Host/Symbols.h" #include "lldb/Host/ThreadLauncher.h" -#include "lldb/Host/TimeValue.h" #include "lldb/Host/XML.h" #include "lldb/Interpreter/Args.h" #include "lldb/Interpreter/CommandInterpreter.h" @@ -289,7 +288,7 @@ const uint64_t timeout_seconds = GetGlobalPluginProperties()->GetPacketTimeout(); if (timeout_seconds > 0) - m_gdb_comm.SetPacketTimeout(timeout_seconds); + m_gdb_comm.SetPacketTimeout(std::chrono::seconds(timeout_seconds)); } //---------------------------------------------------------------------- @@ -424,9 +423,9 @@ // Check if qHostInfo specified a specific packet timeout for this connection. // If so then lets update our setting so the user knows what the timeout is // and can see it. - const uint32_t host_packet_timeout = m_gdb_comm.GetHostDefaultPacketTimeout(); - if (host_packet_timeout) { - GetGlobalPluginProperties()->SetPacketTimeout(host_packet_timeout); + const auto host_packet_timeout = m_gdb_comm.GetHostDefaultPacketTimeout(); + if (host_packet_timeout > std::chrono::seconds(0)) { + GetGlobalPluginProperties()->SetPacketTimeout(host_packet_timeout.count()); } // Register info search order: @@ -899,7 +898,8 @@ { // Scope for the scoped timeout object - GDBRemoteCommunication::ScopedTimeout timeout(m_gdb_comm, 10); + GDBRemoteCommunication::ScopedTimeout timeout(m_gdb_comm, + std::chrono::seconds(10)); int arg_packet_err = m_gdb_comm.SendArgumentsPacket(launch_info); if (arg_packet_err == 0) { @@ -2573,7 +2573,8 @@ if (m_public_state.GetValue() != eStateAttaching) { StringExtractorGDBRemote response; bool send_async = true; - GDBRemoteCommunication::ScopedTimeout(m_gdb_comm, 3); + GDBRemoteCommunication::ScopedTimeout(m_gdb_comm, + std::chrono::seconds(3)); if (m_gdb_comm.SendPacketAndWaitForResponse("k", response, send_async) == GDBRemoteCommunication::PacketResult::Success) { @@ -3894,7 +3895,8 @@ if (m_gdb_comm.GetLoadedDynamicLibrariesInfosSupported()) { // Scope for the scoped timeout object - GDBRemoteCommunication::ScopedTimeout timeout(m_gdb_comm, 10); + GDBRemoteCommunication::ScopedTimeout timeout(m_gdb_comm, + std::chrono::seconds(10)); StreamString packet; packet << "jGetLoadedDynamicLibrariesInfos:"; Index: lldb/trunk/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp =================================================================== --- lldb/trunk/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp +++ lldb/trunk/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp @@ -20,12 +20,14 @@ #include "Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h" #include "lldb/Core/DataBuffer.h" #include "lldb/Core/ModuleSpec.h" +#include "lldb/Core/StructuredData.h" #include "llvm/ADT/ArrayRef.h" using namespace lldb_private::process_gdb_remote; using namespace lldb_private; using namespace lldb; +using namespace llvm; namespace { @@ -45,8 +47,7 @@ ASSERT_EQ(PacketResult::Success, server.SendUnimplementedResponse(nullptr)); } -void HandlePacket(MockServer &server, llvm::StringRef expected, - llvm::StringRef response) { +void HandlePacket(MockServer &server, StringRef expected, StringRef response) { StringExtractorGDBRemote request; ASSERT_EQ(PacketResult::Success, server.GetPacket(request)); ASSERT_EQ(expected, request.GetStringRef()); @@ -260,3 +261,45 @@ ASSERT_FALSE(async_result.get().hasValue()) << "response was: " << response; } } + +TEST_F(GDBRemoteCommunicationClientTest, TestPacketSpeedJSON) { + TestClient client; + MockServer server; + Connect(client, server); + if (HasFailure()) + return; + + std::thread server_thread([&server] { + StringExtractorGDBRemote request; + PacketResult result = server.GetPacket(request); + if (result == PacketResult::ErrorDisconnected) + return; + ASSERT_EQ(PacketResult::Success, result); + StringRef ref = request.GetStringRef(); + ASSERT_TRUE(ref.consume_front("qSpeedTest:response_size:")); + int size; + ASSERT_FALSE(ref.consumeInteger(10, size)) << "ref: " << ref; + std::string response(size, 'X'); + ASSERT_EQ(PacketResult::Success, server.SendPacket(response)); + }); + + StreamString ss; + client.TestPacketSpeed(10, 32, 32, true, ss); + client.Disconnect(); + server_thread.join(); + + auto object_sp = StructuredData::ParseJSON(ss.GetString()); + ASSERT_TRUE(bool(object_sp)); + auto dict_sp = object_sp->GetAsDictionary(); + ASSERT_TRUE(bool(dict_sp)); + + object_sp = dict_sp->GetValueForKey("packet_speeds"); + ASSERT_TRUE(bool(object_sp)); + dict_sp = object_sp->GetAsDictionary(); + ASSERT_TRUE(bool(dict_sp)); + + int num_packets; + ASSERT_TRUE(dict_sp->GetValueForKeyAsInteger("num_packets", num_packets)) + << ss.GetString(); + ASSERT_EQ(10, num_packets); +}