llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-lldb Author: Raphael Isemann (Teemperor) <details> <summary>Changes</summary> LLDB tracks how often certain commands are invoked. This patch adds to this functionality how long it takes in total for all these commands to be invoked. --- Full diff: https://github.com/llvm/llvm-project/pull/200817.diff 6 Files Affected: - (modified) lldb/include/lldb/Interpreter/CommandInterpreter.h (+17-4) - (modified) lldb/source/Commands/CommandObjectCommands.cpp (+17-13) - (modified) lldb/source/Interpreter/CommandInterpreter.cpp (+6-2) - (modified) lldb/source/Interpreter/CommandObject.cpp (+6-2) - (modified) lldb/test/API/commands/statistics/basic/TestStats.py (+12-1) - (modified) lldb/test/API/functionalities/stats_api/TestStatisticsAPI.py (+2-1) ``````````diff diff --git a/lldb/include/lldb/Interpreter/CommandInterpreter.h b/lldb/include/lldb/Interpreter/CommandInterpreter.h index 6fd5b5285c27d..7e77d7adb223a 100644 --- a/lldb/include/lldb/Interpreter/CommandInterpreter.h +++ b/lldb/include/lldb/Interpreter/CommandInterpreter.h @@ -683,8 +683,9 @@ class CommandInterpreter : public Broadcaster, Status PreprocessCommand(std::string &command); Status PreprocessToken(std::string &token); - void IncreaseCommandUsage(const CommandObject &cmd_obj) { - ++m_command_usages[cmd_obj.GetCommandName()]; + void IncreaseCommandUsage(const CommandObject &cmd_obj, + const StatsDuration &duration) { + m_command_stats[cmd_obj.GetCommandName()].addInvocation(duration); } void SetPrintCallback(CommandReturnObjectCallback callback); @@ -815,8 +816,20 @@ class CommandInterpreter : public Broadcaster, bool m_allow_exit_code = false; /// Command usage statistics. - typedef llvm::StringMap<uint64_t> CommandUsageMap; - CommandUsageMap m_command_usages; + struct CommandStats { + /// How often this command was invoked. + uint64_t invocations = 0; + /// Total wall time for all invocations. + StatsDuration totalDuration; + + void addInvocation(const StatsDuration &duration) { + invocations += 1; + totalDuration += duration.get(); + } + }; + + typedef llvm::StringMap<CommandStats> CommandStatsMap; + CommandStatsMap m_command_stats; /// Turn on settings `interpreter.save-transcript` for LLDB to populate /// this stream. Otherwise this stream is empty. diff --git a/lldb/source/Commands/CommandObjectCommands.cpp b/lldb/source/Commands/CommandObjectCommands.cpp index 84e661ec01f53..5f80167edeb58 100644 --- a/lldb/source/Commands/CommandObjectCommands.cpp +++ b/lldb/source/Commands/CommandObjectCommands.cpp @@ -1089,25 +1089,29 @@ class CommandObjectPythonFunction : public CommandObjectRaw { CommandReturnObject &result) override { ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter(); - m_interpreter.IncreaseCommandUsage(*this); - Status error; result.SetStatus(eReturnStatusInvalid); - if (!scripter || !scripter->RunScriptBasedCommand( - m_function_name.c_str(), raw_command_line, m_synchro, - result, error, m_exe_ctx)) { - result.AppendError(error.AsCString()); - } else { - // Don't change the status if the command already set it... - if (result.GetStatus() == eReturnStatusInvalid) { - if (result.GetOutputString().empty()) - result.SetStatus(eReturnStatusSuccessFinishNoResult); - else - result.SetStatus(eReturnStatusSuccessFinishResult); + StatsDuration duration; + { + ElapsedTime measure(duration); + if (!scripter || !scripter->RunScriptBasedCommand( + m_function_name.c_str(), raw_command_line, m_synchro, + result, error, m_exe_ctx)) { + result.AppendError(error.AsCString()); + } else { + // Don't change the status if the command already set it... + if (result.GetStatus() == eReturnStatusInvalid) { + if (result.GetOutputString().empty()) + result.SetStatus(eReturnStatusSuccessFinishNoResult); + else + result.SetStatus(eReturnStatusSuccessFinishResult); + } } } + + m_interpreter.IncreaseCommandUsage(*this, duration); } private: diff --git a/lldb/source/Interpreter/CommandInterpreter.cpp b/lldb/source/Interpreter/CommandInterpreter.cpp index 0c5456c2c3b57..20e29eee45162 100644 --- a/lldb/source/Interpreter/CommandInterpreter.cpp +++ b/lldb/source/Interpreter/CommandInterpreter.cpp @@ -3911,8 +3911,12 @@ CommandInterpreter::ResolveCommandImpl(std::string &command_line, llvm::json::Value CommandInterpreter::GetStatistics() { llvm::json::Object stats; - for (const auto &command_usage : m_command_usages) - stats.try_emplace(command_usage.getKey(), command_usage.getValue()); + for (const auto &command_usage : m_command_stats) { + const auto &cmd = command_usage.second; + llvm::json::Object cmdObj{{"invocations", cmd.invocations}, + {"duration", cmd.totalDuration.get().count()}}; + stats.try_emplace(command_usage.first(), std::move(cmdObj)); + } return stats; } diff --git a/lldb/source/Interpreter/CommandObject.cpp b/lldb/source/Interpreter/CommandObject.cpp index 75abf49e77207..702c2e8da43eb 100644 --- a/lldb/source/Interpreter/CommandObject.cpp +++ b/lldb/source/Interpreter/CommandObject.cpp @@ -856,9 +856,13 @@ void CommandObjectParsed::Execute(const char *args_string, Cleanup(); return; } - m_interpreter.IncreaseCommandUsage(*this); DoExecuteStatusCheck check(result); - DoExecute(cmd_args, result); + StatsDuration duration; + { + ElapsedTime measure(duration); + DoExecute(cmd_args, result); + } + m_interpreter.IncreaseCommandUsage(*this, duration); } } diff --git a/lldb/test/API/commands/statistics/basic/TestStats.py b/lldb/test/API/commands/statistics/basic/TestStats.py index a32b8feecc5cf..67a484e7fabb3 100644 --- a/lldb/test/API/commands/statistics/basic/TestStats.py +++ b/lldb/test/API/commands/statistics/basic/TestStats.py @@ -437,7 +437,18 @@ def test_commands(self): command_stats = self.get_command_stats(debug_stats) self.assertNotEqual(command_stats, None) - self.assertEqual(command_stats["target list"], 2) + self.assertEqual(command_stats["target list"]["invocations"], 2) + + # Duration should always be positive. + old_duration = command_stats["target list"]["duration"] + self.assertGreater(command_stats["target list"]["duration"], 0) + + # Check that duration increases with each command. + interp.HandleCommand("target list", result) + debug_stats = self.get_stats() + command_stats = self.get_command_stats(debug_stats) + self.assertGreater(command_stats["target list"]["duration"], old_duration) + def test_breakpoints(self): """Test "statistics dump" diff --git a/lldb/test/API/functionalities/stats_api/TestStatisticsAPI.py b/lldb/test/API/functionalities/stats_api/TestStatisticsAPI.py index 5f09e8fe07c0b..ff98bd94ddadd 100644 --- a/lldb/test/API/functionalities/stats_api/TestStatisticsAPI.py +++ b/lldb/test/API/functionalities/stats_api/TestStatisticsAPI.py @@ -120,7 +120,8 @@ def test_command_stats_api(self): command_stats = json.loads(stream.GetData()) # Verify bt command is correctly parsed into final form. - self.assertEqual(command_stats["thread backtrace"], 1) + self.assertEqual(command_stats["thread backtrace"]["invocations"], 1) + self.assertGreater(command_stats["thread backtrace"]["duration"], 0) # Verify original raw command is not duplicatedly captured. self.assertNotIn("bt", command_stats) # Verify bt's regex command is not duplicatedly captured. `````````` </details> https://github.com/llvm/llvm-project/pull/200817 _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
