diff options
Diffstat (limited to 'lldb/source')
4 files changed, 219 insertions, 63 deletions
diff --git a/lldb/source/Core/IOHandler.cpp b/lldb/source/Core/IOHandler.cpp index 77e9202402d..b1ee57268ef 100644 --- a/lldb/source/Core/IOHandler.cpp +++ b/lldb/source/Core/IOHandler.cpp @@ -380,7 +380,8 @@ IOHandlerEditline::IOHandlerEditline (Debugger &debugger, m_curr_line_idx (UINT32_MAX), m_multi_line (multi_line), m_color_prompts (color_prompts), - m_interrupt_exits (true) + m_interrupt_exits (true), + m_editing (false) { SetPrompt(prompt); @@ -474,6 +475,7 @@ IOHandlerEditline::GetLine (std::string &line, bool &interrupted) char buffer[256]; bool done = false; bool got_line = false; + m_editing = true; while (!done) { if (fgets(buffer, sizeof(buffer), in) == NULL) @@ -508,6 +510,7 @@ IOHandlerEditline::GetLine (std::string &line, bool &interrupted) line.append(buffer, buffer_len); } } + m_editing = false; // We might have gotten a newline on a line by itself // make sure to return true in this case. return got_line; @@ -754,7 +757,7 @@ IOHandlerEditline::Refresh () { m_editline_ap->Refresh(); } - else + else if (m_editing) { #endif const char *prompt = GetPrompt(); diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index 7d33658a31c..a05059f061a 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -11,10 +11,12 @@ #include "GDBRemoteCommunicationClient.h" // C Includes +#include <math.h> #include <sys/stat.h> // C++ Includes #include <sstream> +#include <numeric> // Other libraries and framework includes #include "llvm/ADT/STLExtras.h" @@ -154,11 +156,6 @@ GDBRemoteCommunicationClient::HandshakeWithServer (Error *error_ptr) // a live connection to a remote GDB server... if (QueryNoAckModeSupported()) { -#if 0 - // Set above line to "#if 1" to test packet speed if remote GDB server - // supports the qSpeedTest packet... - TestPacketSpeed(10000); -#endif return true; } else @@ -2797,87 +2794,165 @@ GDBRemoteCommunicationClient::SetNonStopMode (const bool enable) } +static void +MakeSpeedTestPacket(StreamString &packet, uint32_t send_size, uint32_t recv_size) +{ + packet.Clear(); + packet.Printf ("qSpeedTest:response_size:%i;data:", recv_size); + uint32_t bytes_left = send_size; + while (bytes_left > 0) + { + if (bytes_left >= 26) + { + packet.PutCString("abcdefghijklmnopqrstuvwxyz"); + bytes_left -= 26; + } + else + { + packet.Printf ("%*.*s;", bytes_left, bytes_left, "abcdefghijklmnopqrstuvwxyz"); + bytes_left = 0; + } + } +} + +template<typename T> +T calculate_standard_deviation(const std::vector<T> &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; + accum += delta * delta; + }); + + T stdev = sqrt(accum / (v.size()-1)); + return stdev; +} + void -GDBRemoteCommunicationClient::TestPacketSpeed (const uint32_t num_packets) +GDBRemoteCommunicationClient::TestPacketSpeed (const uint32_t num_packets, uint32_t max_send, uint32_t max_recv, bool json, Stream &strm) { uint32_t i; TimeValue start_time, end_time; uint64_t total_time_nsec; if (SendSpeedTestPacket (0, 0)) { - static uint32_t g_send_sizes[] = { 0, 64, 128, 512, 1024 }; - static uint32_t g_recv_sizes[] = { 0, 64, 128, 512, 1024 }; //, 4*1024, 8*1024, 16*1024, 32*1024, 48*1024, 64*1024, 96*1024, 128*1024 }; - const size_t k_num_send_sizes = llvm::array_lengthof(g_send_sizes); - const size_t k_num_recv_sizes = llvm::array_lengthof(g_recv_sizes); - const uint64_t k_recv_amount = 4*1024*1024; // Receive 4MB - for (uint32_t send_idx = 0; send_idx < k_num_send_sizes; ++send_idx) + StreamString packet; + if (json) + strm.Printf("{ \"packet_speeds\" : {\n \"num_packets\" : %u,\n \"results\" : [", num_packets); + else + strm.Printf("Testing sending %u packets of various sizes:\n", num_packets); + strm.Flush(); + + uint32_t result_idx = 0; + uint32_t send_size; + std::vector<float> packet_times; + + for (send_size = 0; send_size <= max_send; send_size ? send_size *= 2 : send_size = 4) { - const uint32_t send_size = g_send_sizes[send_idx]; - for (uint32_t recv_idx = 0; recv_idx < k_num_recv_sizes; ++recv_idx) + for (uint32_t recv_size = 0; recv_size <= max_recv; recv_size ? recv_size *= 2 : recv_size = 4) { - const uint32_t recv_size = g_recv_sizes[recv_idx]; - StreamString packet; - packet.Printf ("qSpeedTest:response_size:%i;data:", recv_size); - uint32_t bytes_left = send_size; - while (bytes_left > 0) + MakeSpeedTestPacket (packet, send_size, recv_size); + + packet_times.clear(); + // Test how long it takes to send 'num_packets' packets + start_time = TimeValue::Now(); + for (i=0; i<num_packets; ++i) { - if (bytes_left >= 26) - { - packet.PutCString("abcdefghijklmnopqrstuvwxyz"); - bytes_left -= 26; - } - else - { - packet.Printf ("%*.*s;", bytes_left, bytes_left, "abcdefghijklmnopqrstuvwxyz"); - bytes_left = 0; - } + TimeValue packet_start_time = TimeValue::Now(); + StringExtractorGDBRemote response; + SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), 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(); - start_time = TimeValue::Now(); - if (recv_size == 0) + 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<float>(packet_times); + if (json) { - for (i=0; i<num_packets; ++i) - { - StringExtractorGDBRemote response; - SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false); - } + 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); + ++result_idx; } else { - uint32_t bytes_read = 0; - while (bytes_read < k_recv_amount) - { - StringExtractorGDBRemote response; - SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false); - bytes_read += recv_size; - } + strm.Printf ("qSpeedTest(send=%-7u, recv=%-7u) in %" PRIu64 ".%9.9" PRIu64 " 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); + } + strm.Flush(); + } + } + + const uint64_t k_recv_amount = 4*1024*1024; // Receive amount in bytes + + const float k_recv_amount_mb = (float)k_recv_amount/(1024.0f*1024.0f); + if (json) + strm.Printf("\n ]\n },\n \"download_speed\" : {\n \"byte_size\" : %" PRIu64 ",\n \"results\" : [", k_recv_amount); + else + strm.Printf("Testing receiving %2.1fMB of data using varying receive packet sizes:\n", k_recv_amount_mb); + strm.Flush(); + send_size = 0; + result_idx = 0; + for (uint32_t recv_size = 32; recv_size <= max_recv; recv_size *= 2) + { + MakeSpeedTestPacket (packet, send_size, recv_size); + + // If we have a receive size, test how long it takes to receive 4MB of data + if (recv_size > 0) + { + start_time = TimeValue::Now(); + uint32_t bytes_read = 0; + uint32_t packet_count = 0; + while (bytes_read < k_recv_amount) + { + StringExtractorGDBRemote response; + SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false); + bytes_read += recv_size; + ++packet_count; } end_time = TimeValue::Now(); total_time_nsec = end_time.GetAsNanoSecondsSinceJan1_1970() - start_time.GetAsNanoSecondsSinceJan1_1970(); - if (recv_size == 0) + float mb_second = ((((float)k_recv_amount)/(float)total_time_nsec) * (float)TimeValue::NanoSecPerSec) / (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; + + if (json) { - float packets_per_second = (((float)num_packets)/(float)total_time_nsec) * (float)TimeValue::NanoSecPerSec; - printf ("%u qSpeedTest(send=%-7u, recv=%-7u) in %" PRIu64 ".%9.9" PRIu64 " sec for %f packets/sec.\n", - num_packets, - send_size, - recv_size, - total_time_nsec / TimeValue::NanoSecPerSec, - total_time_nsec % TimeValue::NanoSecPerSec, - packets_per_second); + 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); + ++result_idx; } else { - float mb_second = ((((float)k_recv_amount)/(float)total_time_nsec) * (float)TimeValue::NanoSecPerSec) / (1024.0*1024.0); - printf ("%u qSpeedTest(send=%-7u, recv=%-7u) sent 4MB in %" PRIu64 ".%9.9" PRIu64 " sec for %f MB/sec.\n", - num_packets, - send_size, - recv_size, - total_time_nsec / TimeValue::NanoSecPerSec, - total_time_nsec % TimeValue::NanoSecPerSec, - mb_second); + strm.Printf ("qSpeedTest(send=%-7u, recv=%-7u) %6u packets needed to receive %2.1fMB in %" PRIu64 ".%9.9" PRIu64 " 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); } + strm.Flush(); } } + if (json) + strm.Printf("\n ]\n }\n}\n"); + else + strm.EOL(); } } diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h index 99b29a92423..517eb3d0f17 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -400,7 +400,7 @@ public: SetNonStopMode (const bool enable); void - TestPacketSpeed (const uint32_t num_packets); + TestPacketSpeed (const uint32_t num_packets, uint32_t max_send, uint32_t max_recv, bool json, Stream &strm); // This packet is for testing the speed of the interface only. Both // the client and server need to support it, but this allows us to diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index 9b8ccd21f72..e1f5f2fbd53 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -55,6 +55,9 @@ #include "lldb/Interpreter/CommandObjectMultiword.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/OptionValueProperties.h" +#include "lldb/Interpreter/Options.h" +#include "lldb/Interpreter/OptionGroupBoolean.h" +#include "lldb/Interpreter/OptionGroupUInt64.h" #include "lldb/Interpreter/Property.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Target/DynamicLoader.h" @@ -4311,6 +4314,80 @@ ProcessGDBRemote::LoadModules () return new_modules.GetSize(); } +class CommandObjectProcessGDBRemoteSpeedTest: public CommandObjectParsed +{ +public: + CommandObjectProcessGDBRemoteSpeedTest(CommandInterpreter &interpreter) : + CommandObjectParsed (interpreter, + "process plugin packet speed-test", + "Tests packet speeds of various sizes to determine the performance characteristics of the GDB remote connection. ", + NULL), + m_option_group (interpreter), + m_num_packets (LLDB_OPT_SET_1, false, "count", 'c', 0, eArgTypeCount, "The number of packets to send of each varying size (default is 1000).", 1000), + m_max_send (LLDB_OPT_SET_1, false, "max-send", 's', 0, eArgTypeCount, "The maximum number of bytes to send in a packet. Sizes increase in powers of 2 while the size is less than or equal to this option value. (default 1024).", 1024), + m_max_recv (LLDB_OPT_SET_1, false, "max-receive", 'r', 0, eArgTypeCount, "The maximum number of bytes to receive in a packet. Sizes increase in powers of 2 while the size is less than or equal to this option value. (default 1024).", 1024), + m_json (LLDB_OPT_SET_1, false, "json", 'j', "Print the output as JSON data for easy parsing.", false, true) + { + m_option_group.Append (&m_num_packets, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); + m_option_group.Append (&m_max_send, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); + m_option_group.Append (&m_max_recv, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); + m_option_group.Append (&m_json, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); + m_option_group.Finalize(); + } + + ~CommandObjectProcessGDBRemoteSpeedTest () + { + } + + + Options * + GetOptions () override + { + return &m_option_group; + } + + bool + DoExecute (Args& command, CommandReturnObject &result) override + { + const size_t argc = command.GetArgumentCount(); + if (argc == 0) + { + ProcessGDBRemote *process = (ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr(); + if (process) + { + StreamSP output_stream_sp (m_interpreter.GetDebugger().GetAsyncOutputStream()); + result.SetImmediateOutputStream (output_stream_sp); + + const uint32_t num_packets = (uint32_t)m_num_packets.GetOptionValue().GetCurrentValue(); + const uint64_t max_send = m_max_send.GetOptionValue().GetCurrentValue(); + const uint64_t max_recv = m_max_recv.GetOptionValue().GetCurrentValue(); + const bool json = m_json.GetOptionValue().GetCurrentValue(); + if (output_stream_sp) + process->GetGDBRemote().TestPacketSpeed (num_packets, max_send, max_recv, json, *output_stream_sp); + else + { + process->GetGDBRemote().TestPacketSpeed (num_packets, max_send, max_recv, json, result.GetOutputStream()); + } + result.SetStatus (eReturnStatusSuccessFinishResult); + return true; + } + } + else + { + result.AppendErrorWithFormat ("'%s' takes no arguments", m_cmd_name.c_str()); + } + result.SetStatus (eReturnStatusFailed); + return false; + } +protected: + OptionGroupOptions m_option_group; + OptionGroupUInt64 m_num_packets; + OptionGroupUInt64 m_max_send; + OptionGroupUInt64 m_max_recv; + OptionGroupBoolean m_json; + +}; + class CommandObjectProcessGDBRemotePacketHistory : public CommandObjectParsed { private: @@ -4524,6 +4601,7 @@ public: LoadSubCommand ("send", CommandObjectSP (new CommandObjectProcessGDBRemotePacketSend (interpreter))); LoadSubCommand ("monitor", CommandObjectSP (new CommandObjectProcessGDBRemotePacketMonitor (interpreter))); LoadSubCommand ("xfer-size", CommandObjectSP (new CommandObjectProcessGDBRemotePacketXferSize (interpreter))); + LoadSubCommand ("speed-test", CommandObjectSP (new CommandObjectProcessGDBRemoteSpeedTest (interpreter))); } ~CommandObjectProcessGDBRemotePacket () |