summaryrefslogtreecommitdiffstats
path: root/lldb/source
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source')
-rw-r--r--lldb/source/Core/IOHandler.cpp7
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp195
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h2
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp78
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 ()
OpenPOWER on IntegriCloud