From 69f90d6c421b997c3ed5b887269c55695f3d753a Mon Sep 17 00:00:00 2001 From: Nader Zouaoui Date: Thu, 28 Nov 2024 17:06:40 +0100 Subject: [PATCH 01/21] feat: add arg_parser to user_request --- wperf/arg_parser.cpp | 20 +- wperf/arg_parser.h | 12 +- wperf/main.cpp | 28 +- wperf/user_request.cpp | 685 ++++++++++++----------------------------- wperf/user_request.h | 6 +- 5 files changed, 226 insertions(+), 525 deletions(-) diff --git a/wperf/arg_parser.cpp b/wperf/arg_parser.cpp index f512c59..3e6b391 100644 --- a/wperf/arg_parser.cpp +++ b/wperf/arg_parser.cpp @@ -28,13 +28,15 @@ // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#include "arg_parser.h" #include #include #include #include #include #include +#include "arg-parser.h" +#include "output.h" +#include "exception.h" namespace ArgParser { arg_parser::arg_parser() {} @@ -101,26 +103,26 @@ namespace ArgParser { void arg_parser::print_help() const { - std::wcout << L"NAME:\n" + m_out.GetOutputStream() << L"NAME:\n" << L"\twperf - Performance analysis tools for Windows on Arm\n\n" << L"\tUsage: wperf [options]\n\n" << L"SYNOPSIS:\n\n"; for (auto& command : m_commands_list) { - std::wcout << L"\t" << command->get_all_flags_string() << L"\n" << command->get_usage_text() << L"\n"; + m_out.GetOutputStream() << L"\t" << command->get_all_flags_string() << L"\n" << command->get_usage_text() << L"\n"; } - std::wcout << L"OPTIONS:\n\n"; + m_out.GetOutputStream() << L"OPTIONS:\n\n"; for (auto& flag : m_flags_list) { - std::wcout << L" " << flag->get_help() << L"\n"; + m_out.GetOutputStream() << L" " << flag->get_help() << L"\n"; } - std::wcout << L"EXAMPLES:\n\n"; + m_out.GetOutputStream() << L"EXAMPLES:\n\n"; for (auto& command : m_commands_list) { if (command->get_examples().empty()) continue; - std::wcout << L" " << command->get_examples() << L"\n"; + m_out.GetOutputStream() << L" " << command->get_examples() << L"\n"; } } @@ -155,8 +157,8 @@ namespace ArgParser { if (!additional_message.empty()) { error_message << additional_message << L"\n"; } - std::wcerr << error_message.str(); - throw std::invalid_argument("INVALID_ARGUMENT"); + m_out.GetErrorOutputStream() << error_message.str(); + throw fatal_exception("INVALID_ARGUMENT"); } #pragma endregion diff --git a/wperf/arg_parser.h b/wperf/arg_parser.h index 171d2b7..117de17 100644 --- a/wperf/arg_parser.h +++ b/wperf/arg_parser.h @@ -58,7 +58,7 @@ namespace ArgParser { MAN, NO_COMMAND }; - class arg_parser_arg_command : public arg_parser_arg_opt { + class arg_parser_arg_command : public arg_parser_arg_pos { public: arg_parser_arg_command( @@ -67,8 +67,9 @@ namespace ArgParser { const std::wstring description, const std::wstring useage_text, const COMMAND_CLASS command, - const wstr_vec examples - ) : arg_parser_arg_opt(name, alias, description), m_examples(examples), m_command(command), m_useage_text(useage_text) {}; + const wstr_vec examples, + const int arg_count = 0 + ) : arg_parser_arg_pos(name, alias, description, {}, arg_count), m_examples(examples), m_command(command), m_useage_text(useage_text) {}; const COMMAND_CLASS m_command = COMMAND_CLASS::NO_COMMAND; const wstr_vec m_examples; const std::wstring m_useage_text; @@ -180,7 +181,8 @@ namespace ArgParser { L"wperf man [--json]", COMMAND_CLASS::MAN, { - } + }, + 1 ); #pragma endregion @@ -346,7 +348,7 @@ namespace ArgParser { {} ); arg_parser_arg_pos iteration_arg = arg_parser_arg_pos::arg_parser_arg_pos( - L"-i", + L"-n", {}, L"Number of consecutive counts in timeline mode (disabled by default).", {} diff --git a/wperf/main.cpp b/wperf/main.cpp index f4fe611..55d439b 100644 --- a/wperf/main.cpp +++ b/wperf/main.cpp @@ -50,6 +50,7 @@ #include "config.h" #include "perfdata.h" #include "disassembler.h" +#include "arg-parser.h" static bool no_ctrl_c = true; @@ -81,10 +82,12 @@ wmain( ) { auto exit_code = EXIT_SUCCESS; + ArgParser::arg_parser arg_parser; + arg_parser.parse(argc, argv); + user_request request; pmu_device pmu_device; - wstr_vec raw_args; LLVMDisassembler disassembler; bool spawned_process = false; @@ -92,24 +95,14 @@ wmain( PROCESS_INFORMATION pi; ZeroMemory(&pi, sizeof(pi)); - //* Handle CLI options before we initialize PMU device(s) - for (int i = 1; i < argc; i++) - raw_args.push_back(argv[i]); - - pmu_device.do_force_lock = user_request::is_force_lock(raw_args); - - if (raw_args.size() == 1 && user_request::is_help(raw_args)) + if (arg_parser.m_command == ArgParser::COMMAND_CLASS::HELP) { - user_request::print_help(); + arg_parser.print_help(); goto clean_exit; } - if (raw_args.empty()) - { - user_request::print_help_header(); - user_request::print_help_prompt(); - goto clean_exit; - } + pmu_device.do_force_lock = arg_parser.force_lock_opt.is_set(); + //* Handle CLI options before we initialize PMU device(s) try { @@ -162,7 +155,7 @@ wmain( { struct pmu_device_cfg pmu_cfg; pmu_device.get_pmu_device_cfg(pmu_cfg); - request.init(raw_args, pmu_cfg, + request.init(arg_parser, pmu_cfg, pmu_device.builtin_metrics, pmu_device.get_product_groups_metrics_names(), pmu_events::extra_events); @@ -1340,7 +1333,8 @@ wmain( #if defined(ENABLE_ETW_TRACING_APP) EventUnregisterWindowsPerf_App(); #endif - + std::wstring hellp; + std::wcin >> hellp; if(spawned_process) { TerminateProcess(pi.hProcess, 0); diff --git a/wperf/user_request.cpp b/wperf/user_request.cpp index 1667935..72777ac 100644 --- a/wperf/user_request.cpp +++ b/wperf/user_request.cpp @@ -319,7 +319,7 @@ bool user_request::is_help(const wstr_vec& raw_args) || is_cli_option_in_args(raw_args, std::wstring(L"-h")); } -void user_request::init(wstr_vec& raw_args, const struct pmu_device_cfg& pmu_cfg, +void user_request::init(ArgParser::arg_parser& parsed_args, const struct pmu_device_cfg& pmu_cfg, std::map& builtin_metrics, const std::map >& groups_of_metrics, std::map>& extra_events) @@ -332,7 +332,7 @@ void user_request::init(wstr_vec& raw_args, const struct pmu_device_cfg& pmu_cfg cores_idx.resize(pmu_cfg.core_num); std::iota(cores_idx.begin(), cores_idx.end(), (UINT8)0); - parse_raw_args(raw_args, pmu_cfg, events, groups, builtin_metrics, groups_of_metrics, extra_events); + parse_raw_args(parsed_args, pmu_cfg, events, groups, builtin_metrics, groups_of_metrics, extra_events); // Deduce image name and PDB file name from PE file name if (sample_pe_file.size()) @@ -392,120 +392,237 @@ void user_request::init(wstr_vec& raw_args, const struct pmu_device_cfg& pmu_cfg check_events(EVT_DMC_CLKDIV2, MAX_MANAGED_DMC_CLKDIV2_EVENTS); } -void user_request::parse_raw_args(wstr_vec& raw_args, const struct pmu_device_cfg& pmu_cfg, +void user_request::parse_raw_args(ArgParser::arg_parser& parsed_args, const struct pmu_device_cfg& pmu_cfg, std::map>& events, std::map>& groups, std::map& builtin_metrics, const std::map >& groups_of_metrics, std::map>& extra_events) { - bool waiting_events = false; - bool waiting_metrics = false; - bool waiting_core_idx = false; - bool waiting_dmc_idx = false; - bool waiting_duration = false; - bool waiting_interval = false; - bool waiting_metric_config = false; - bool waiting_events_config = false; - bool waiting_output_filename = false; - bool waiting_output_csv_filename = false; - bool waiting_image_name = false; - bool waiting_pe_file = false; - bool waiting_pdb_file = false; - bool waiting_sample_display_row = false; - bool waiting_timeline_count = false; - bool waiting_config = false; - bool waiting_commandline = false; - bool waiting_record_spawn_delay = false; - bool waiting_man_query = false; - bool waiting_cwd = false; - bool waiting_symbol = false; + bool sample_pe_file_given = false; std::wstring waiting_duration_arg; std::wstring output_filename, output_csv_filename; - if (raw_args.empty()) + switch (parsed_args.m_command) { - print_help_header(); - print_help_prompt(); + case ArgParser::COMMAND_CLASS::STAT: + do_count = true; + break; + case ArgParser::COMMAND_CLASS::SAMPLE: + do_sample = true; + break; + case ArgParser::COMMAND_CLASS::RECORD: + do_record = true; + break; + case ArgParser::COMMAND_CLASS::TEST: + do_test = true; + break; + case ArgParser::COMMAND_CLASS::DETECT: + do_detect = true; + break; + case ArgParser::COMMAND_CLASS::HELP: + do_help = true; + break; + case ArgParser::COMMAND_CLASS::VERSION: + do_version = true; + break; + case ArgParser::COMMAND_CLASS::LIST: + do_list = true; + break; + case ArgParser::COMMAND_CLASS::MAN: + do_man = true; + break; + default: + break; } - for (const auto& a : raw_args) + if (parsed_args.metric_config_arg.is_set()) + { + load_config_metrics(parsed_args.metric_config_arg.get_values().front(), pmu_cfg); + } + if (parsed_args.event_config_arg.is_set()) + { + load_config_events(parsed_args.event_config_arg.get_values().front(), extra_events); + } + + if (builtin_metrics.size()) { - if (waiting_metric_config) + for (const auto& [key, value] : builtin_metrics) { - waiting_metric_config = false; - load_config_metrics(a, pmu_cfg); - continue; + if (metrics.find(key) == metrics.end()) + metrics[key] = value; } + } + if (parsed_args.extra_args_arg.is_set()) + { + if (sample_pe_file.empty()) + sample_pe_file = parsed_args.extra_args_arg.get_values().front(); + + record_commandline += WStringJoin(parsed_args.extra_args_arg.get_values(), L" "); + if (!(do_record || do_count)) + m_out.GetErrorOutputStream() << L"warning: only `stat` and `record` support process spawn!" << std::endl; + + sample_pe_file.clear(); + record_commandline.clear(); + } + if (parsed_args.output_prefix_arg.is_set()) + { + m_cwd = parsed_args.output_prefix_arg.get_values().front(); + } + if (parsed_args.output_filename_arg.is_set()) + { + output_filename = parsed_args.output_filename_arg.get_values().front(); + } - if (a == L"-C") - { - waiting_metric_config = true; - continue; - } + if (parsed_args.output_csv_filename_arg.is_set()) + { + output_csv_filename = parsed_args.output_csv_filename_arg.get_values().front(); + } - if (waiting_events_config) - { - waiting_events_config = false; - load_config_events(a, extra_events); - continue; - } + if (parsed_args.config_arg.is_set()) + { + wstring config_values = parsed_args.config_arg.get_values().front(); + if (drvconfig::set(config_values) == false) + m_out.GetErrorOutputStream() << L"error: can't set '" << config_values << "' config" << std::endl; + } + if (parsed_args.image_name_arg.is_set()) + { + sample_image_name = parsed_args.image_name_arg.get_values().front(); + } - if (a == L"-E") + if (parsed_args.pe_file_arg.is_set()) + { + wstring parsed_pe_file = parsed_args.pe_file_arg.get_values().front(); + if (std::filesystem::exists(parsed_pe_file) == false) { - waiting_events_config = true; - continue; + m_out.GetErrorOutputStream() << L"PE file '" << parsed_pe_file << L"' doesn't exist" + << std::endl; + throw fatal_exception("ERROR_PE_FILE_PATH"); } + sample_pe_file = parsed_pe_file; + sample_pe_file_given = true; } - - if (builtin_metrics.size()) + + if (parsed_args.pdb_file_arg.is_set()) { - for (const auto& [key, value] : builtin_metrics) + wstring parsed_pdb_file = parsed_args.pdb_file_arg.get_values().front(); + if (std::filesystem::exists(parsed_pdb_file) == false) { - if (metrics.find(key) == metrics.end()) - metrics[key] = value; + m_out.GetErrorOutputStream() << L"PDB file '" << parsed_pdb_file << L"' doesn't exist" + << std::endl; + throw fatal_exception("ERROR_PDB_FILE_PATH"); } + sample_pdb_file = parsed_pdb_file; } - for (const auto& a : raw_args) + + if (parsed_args.cores_arg.is_set()) { - if (waiting_commandline) - { - if (sample_pe_file.empty()) - { - sample_pe_file = a; - record_commandline = a; - } - else - record_commandline += L" " + a; - continue; - } + wstring core_idx_str = WStringJoin(parsed_args.cores_arg.get_values(), L","); - if (waiting_metric_config) + if (TokenizeWideStringOfInts(core_idx_str.c_str(), L',', cores_idx) == false) { - waiting_metric_config = false; - continue; + m_out.GetErrorOutputStream() << L"option -c format not supported, use comma separated list of integers, or range of integers" + << std::endl; + throw fatal_exception("ERROR_CORES"); } - if (waiting_events_config) + if (cores_idx.size() > MAX_PMU_CTL_CORES_COUNT) { - waiting_events_config = false; - continue; + m_out.GetErrorOutputStream() << L"you can specify up to " << int(MAX_PMU_CTL_CORES_COUNT) + << L"cores with -c option" + << std::endl; + throw fatal_exception("ERROR_CORES"); } + } + + if (parsed_args.iteration_arg.is_set()) + { + count_timeline = _wtoi(parsed_args.iteration_arg.get_values().front().c_str()); + } - if (waiting_events) + if (parsed_args.record_spawn_delay_arg.is_set()) + { + uint32_t val = _wtoi(parsed_args.record_spawn_delay_arg.get_values().front().c_str()); + assert(val <= UINT32_MAX); + record_spawn_delay = val; + } + + if (parsed_args.dmc_arg.is_set()) + { + + int val = _wtoi(parsed_args.output_filename_arg.get_values().front().c_str()); + assert(val <= UCHAR_MAX); + dmc_idx = (uint8_t)val; + } + + if (parsed_args.timeout_arg.is_set()) + { + count_duration = convert_timeout_arg_to_seconds(parsed_args.output_filename_arg.get_values().front(), parsed_args.timeout_arg.get_name()); + } + + if (parsed_args.interval_arg.is_set()) + { + count_interval = convert_timeout_arg_to_seconds(parsed_args.interval_arg.get_values().front(), parsed_args.interval_arg.get_name()); + } + + if (parsed_args.sample_display_row_arg.is_set()) + { + sample_display_row = _wtoi(parsed_args.sample_display_row_arg.get_values().front().c_str()); + } + + if (parsed_args.man_command.is_set()) + { + man_query_args = parsed_args.man_command.get_values().front(); + } + if (parsed_args.symbol_arg.is_set()) + { + symbol_arg = parsed_args.symbol_arg.get_values().front(); + do_symbol = true; + + } + do_disassembly = parsed_args.disassembly_opt.is_set(); + do_annotate = parsed_args.annotate_opt.is_set() || parsed_args.disassembly_opt.is_set(); + do_force_lock = parsed_args.force_lock_opt.is_set(); + do_kernel = parsed_args.kernel_opt.is_set(); + if (parsed_args.timeline_opt.is_set()) + { + do_timeline = true; + if (count_interval == -1.0) + count_interval = 60; + if (count_duration == -1.0) + count_duration = 1; + } + sample_display_short = !parsed_args.sample_display_long_opt.is_set(); + do_verbose = parsed_args.verbose_opt.is_set(); + m_out.m_isQuiet = parsed_args.quite_opt.is_set(); + if (parsed_args.json_opt.is_set() && m_outputType != TableType::ALL) + { + m_outputType = TableType::JSON; + m_out.m_isQuiet = true; + } + // TODO: Check why This flag is not documented + //if (a == L"--export_perf_data") + //{ + // do_export_perf_data = true; + // continue; + //} + + + if (parsed_args.events_arg.is_set()) { + wstring raw_events_string = WStringJoin(parsed_args.events_arg.get_values(), L","); if (do_sample || do_record) { m_sampling_flags.clear(); // Prepare to collect SPE filters - if (parse_events_str_for_feat_spe(a, m_sampling_flags)) // Check if we are sampling with SPE + if (parse_events_str_for_feat_spe(raw_events_string, m_sampling_flags)) // Check if we are sampling with SPE { if (pmu_cfg.has_spe == false) { - m_out.GetErrorOutputStream() << L"SPE is not supported by your hardware: " << a << std::endl; + m_out.GetErrorOutputStream() << L"SPE is not supported by your hardware: " << raw_events_string << std::endl; throw fatal_exception("ERROR_SPE_NOT_SUPP"); } @@ -538,7 +655,7 @@ void user_request::parse_raw_args(wstr_vec& raw_args, const struct pmu_device_cf } else // Software sampling (no SPE) { - parse_events_str_for_sample(a, ioctl_events_sample, sampling_inverval); + parse_events_str_for_sample(raw_events_string, ioctl_events_sample, sampling_inverval); // After events are parsed check if we can fulfil this request as sampling does not have multiplexing if (ioctl_events_sample.size() > pmu_cfg.total_gpc_num) { @@ -556,44 +673,14 @@ void user_request::parse_raw_args(wstr_vec& raw_args, const struct pmu_device_cf } } else - parse_events_str(a, events, groups, L"", pmu_cfg); - waiting_events = false; - continue; - } - - if (waiting_cwd) - { - waiting_cwd = false; - m_cwd = a; - continue; - } - - if (waiting_output_filename) - { - waiting_output_filename = false; - output_filename = a; - continue; - } - - if (waiting_output_csv_filename) - { - waiting_output_csv_filename = false; - output_csv_filename = a; - continue; - } - - if (waiting_config) - { - waiting_config = false; - if (drvconfig::set(a) == false) - m_out.GetErrorOutputStream() << L"error: can't set '" << a << "' config" << std::endl; - continue; + parse_events_str(raw_events_string, events, groups, L"", pmu_cfg); } - if (waiting_metrics) + if (parsed_args.metrics_arg.is_set()) { + wstring raw_metrics_string = WStringJoin(parsed_args.metrics_arg.get_values(), L","); std::vector list_of_defined_metrics; - std::wistringstream metric_stream(a); + std::wistringstream metric_stream(raw_metrics_string); std::wstring metric_token; while (std::getline(metric_stream, metric_token, L',')) @@ -642,392 +729,8 @@ void user_request::parse_raw_args(wstr_vec& raw_args, const struct pmu_device_cf else if (metric == L"ddr_bw") report_ddr_bw_metric = true; } - - waiting_metrics = false; - continue; - } - - if (waiting_image_name) - { - sample_image_name = a; - waiting_image_name = false; - continue; - } - - if (waiting_pe_file) - { - if (std::filesystem::exists(a) == false) - { - m_out.GetErrorOutputStream() << L"PE file '" << a << L"' doesn't exist" - << std::endl; - throw fatal_exception("ERROR_PE_FILE_PATH"); - } - - sample_pe_file = a; - sample_pe_file_given = true; - waiting_pe_file = false; - continue; - } - - if (waiting_pdb_file) - { - if (std::filesystem::exists(a) == false) - { - m_out.GetErrorOutputStream() << L"PDB file '" << a << L"' doesn't exist" - << std::endl; - throw fatal_exception("ERROR_PDB_FILE_PATH"); - } - - sample_pdb_file = a; - waiting_pdb_file = false; - continue; - } - - if (waiting_core_idx) - { - if (TokenizeWideStringOfInts(a.c_str(), L',', cores_idx) == false) - { - m_out.GetErrorOutputStream() << L"option -c format not supported, use comma separated list of integers, or range of integers" - << std::endl; - throw fatal_exception("ERROR_CORES"); - } - - if (cores_idx.size() > MAX_PMU_CTL_CORES_COUNT) - { - m_out.GetErrorOutputStream() << L"you can specify up to " << int(MAX_PMU_CTL_CORES_COUNT) - << L"cores with -c option" - << std::endl; - throw fatal_exception("ERROR_CORES"); - } - - waiting_core_idx = false; - continue; - } - - if (waiting_timeline_count) - { - count_timeline = _wtoi(a.c_str()); - waiting_timeline_count = false; - continue; - } - - if (waiting_record_spawn_delay) - { - uint32_t val = _wtoi(a.c_str()); - assert(val <= UINT32_MAX); - record_spawn_delay = val; - waiting_record_spawn_delay = false; - continue; - } - - if (waiting_dmc_idx) - { - int val = _wtoi(a.c_str()); - assert(val <= UCHAR_MAX); - dmc_idx = (uint8_t)val; - waiting_dmc_idx = false; - continue; - } - - if (waiting_duration) - { - count_duration = convert_timeout_arg_to_seconds(a, waiting_duration_arg); - waiting_duration = false; - continue; - } - - if (waiting_interval) - { - count_interval = convert_timeout_arg_to_seconds(a, waiting_duration_arg); - waiting_interval = false; - continue; - } - - if (waiting_sample_display_row) - { - sample_display_row = _wtoi(a.c_str()); - waiting_sample_display_row = false; - continue; - } - - if (waiting_man_query) - { - man_query_args = a; - waiting_man_query = false; - continue; - } - - if (waiting_symbol) - { - symbol_arg = a; - waiting_symbol = false; - continue; - } - - // For compatibility with Linux perf - if (a == L"list" || a == L"-l") - { - do_list = true; - continue; - } - - if (a == L"-e") - { - waiting_events = true; - continue; - } - - if (a == L"-C") // Skip this one as it was handled before any other args - { - waiting_metric_config = true; - continue; - } - - if (a == L"-E") // Skip this one as it was handled before any other args - { - waiting_events_config = true; - continue; - } - - if (a == L"-m") - { - waiting_metrics = true; - continue; - } - - if (a == L"stat") - { - do_count = true; - continue; - } - - if (a == L"record") - { - do_record = true; - continue; - } - - if (a == L"sample") - { - do_sample = true; - continue; - } - - if (a == L"detect") - { - do_detect = true; - continue; - } - if (a == L"man") - { - do_man = true; - waiting_man_query = true; - continue; - } - - if (a == L"--image_name") - { - waiting_image_name = true; - continue; - } - - if (a == L"--disassemble") - { - do_disassembly = true; - do_annotate = true; - continue; - } - - if (a == L"--force-lock") - { - do_force_lock = true; - continue; - } - - if (a == L"--export_perf_data") - { - do_export_perf_data = true; - continue; - } - - if (a == L"--record_spawn_delay") - { - waiting_record_spawn_delay = true; - continue; - } - - if (a == L"--pe_file") - { - waiting_pe_file = true; - continue; - } - - if (a == L"--pdb_file") - { - waiting_pdb_file = true; - continue; - } - - if (a == L"--timeout" || a == L"sleep") - { - waiting_duration = true; - waiting_duration_arg = a; - continue; - } - - if (a == L"--cwd" || a == L"--output-prefix") - { - waiting_cwd = true; - continue; - } - - if (a == L"--output" || a == L"-o") - { - waiting_output_filename = true; - continue; - } - - if (a == L"--output-csv") - { - waiting_output_csv_filename = true; - continue; - } - - if (a == L"--config") - { - waiting_config = true; - continue; - } - - if (a == L"-k") - { - do_kernel = true; - continue; - } - - if (a == L"-t") - { - do_timeline = true; - if (count_interval == -1.0) - count_interval = 60; - if (count_duration == -1.0) - count_duration = 1; - continue; - } - - if (a == L"-n") - { - waiting_timeline_count = true; - continue; - } - - if (a == L"--sample-display-row") - { - waiting_sample_display_row = true; - continue; - } - - if (a == L"--sample-display-long") - { - sample_display_short = false; - continue; - } - - if (a == L"-i") - { - waiting_duration_arg = a; - waiting_interval = true; - continue; - } - - if (a == L"-c" || a == L"--cpu") - { - waiting_core_idx = true; - continue; - } - - if (a == L"--dmc") - { - waiting_dmc_idx = true; - continue; - } - - if (a == L"-v" || a == L"--verbose") - { - do_verbose = true; - continue; - } - - if (a == L"--annotate") - { - do_annotate = true; - continue; - } - - if (a == L"--version") - { - do_version = true; - continue; - } - - if (a == L"-h" || a == L"--help") - { - do_help = true; - continue; - } - - if (a == L"-q") - { - m_out.m_isQuiet = true; - continue; - } - - if (a == L"--json") - { - if (m_outputType != TableType::ALL) - { - m_outputType = TableType::JSON; - m_out.m_isQuiet = true; - } - continue; - } - - if (a == L"test") - { - do_test = true; - continue; - } - - if (a == L"-s" || a == L"--symbol") - { - do_symbol = true; - waiting_symbol = true; - continue; - } - - /* This will finish command line argument parsing. After "--" we will see process to spawn in form of: - * - * wperf ... -- PROCESS_NAME ARG ARG ARG ARG ... - * - * From now on we will parse process spawn name and verbatim arguments - */ - if (a == L"--") - { - if (!(do_record || do_count)) - m_out.GetErrorOutputStream() << L"warning: only `stat` and `record` support process spawn!" << std::endl; - - waiting_commandline = true; - /* We will reload here PE file name to spawn. `waiting_commandline` will expect this - * to be empty to detect beggining of the scan. - */ - sample_pe_file.clear(); - record_commandline.clear(); - continue; } - m_out.GetErrorOutputStream() << L"warning: unexpected arg '" << a << L"' ignored" << std::endl; - } - std::wstring output_filename_full_path = output_filename; std::wstring output_filename_csv_full_path = output_csv_filename; diff --git a/wperf/user_request.h b/wperf/user_request.h index 25dad10..8a4827d 100644 --- a/wperf/user_request.h +++ b/wperf/user_request.h @@ -35,7 +35,7 @@ #include "utils.h" #include "events.h" #include "output.h" - +#include "arg-parser.h" typedef std::vector wstr_vec; class user_request @@ -43,12 +43,12 @@ class user_request public: user_request(); - void init(wstr_vec& raw_args, const struct pmu_device_cfg& pmu_cfg, + void init(ArgParser::arg_parser& parsed_args, const struct pmu_device_cfg& pmu_cfg, std::map& builtin_metrics, const std::map >& groups_of_metrics, std::map>& extra_events); - void parse_raw_args(wstr_vec& raw_args, const struct pmu_device_cfg& pmu_cfg, + void parse_raw_args(ArgParser::arg_parser& parsed_args, const struct pmu_device_cfg& pmu_cfg, std::map>& events, std::map>& groups, std::map& builtin_metrics, From 1fbf1c264ad9932166aec2dc98aeb8cd36069afd Mon Sep 17 00:00:00 2001 From: Nader Zouaoui Date: Thu, 28 Nov 2024 17:17:19 +0100 Subject: [PATCH 02/21] feat: update tests --- wperf-lib/wperf-lib.vcxproj | 2 +- wperf-test/wperf-test-arg_parser.cpp | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/wperf-lib/wperf-lib.vcxproj b/wperf-lib/wperf-lib.vcxproj index dff9fdc..493bda0 100644 --- a/wperf-lib/wperf-lib.vcxproj +++ b/wperf-lib/wperf-lib.vcxproj @@ -293,7 +293,7 @@ true - $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj + $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj;arg-parser.obj;arg-parser-arg.obj $(SolutionDir)wperf\$(IntDir) diff --git a/wperf-test/wperf-test-arg_parser.cpp b/wperf-test/wperf-test-arg_parser.cpp index d4cebad..9144795 100644 --- a/wperf-test/wperf-test-arg_parser.cpp +++ b/wperf-test/wperf-test-arg_parser.cpp @@ -32,6 +32,7 @@ #include "CppUnitTest.h" #include #include "wperf/arg_parser.h" +#include "wperf/exception.h" using namespace Microsoft::VisualStudio::CppUnitTestFramework; using namespace ArgParser; @@ -61,7 +62,7 @@ namespace wperftest const wchar_t* argv[] = { L"wperf", L"test", L"-v", L"--json", L"random" }; const int argc = _countof(argv); arg_parser parser; - Assert::ExpectException([&parser, argc, &argv]() { + Assert::ExpectException([&parser, argc, &argv]() { parser.parse(argc, argv); } ); @@ -117,7 +118,7 @@ namespace wperftest const wchar_t* argv[] = { L"wperf", L"sample", L"--timeout" }; const int argc = _countof(argv); arg_parser parser; - Assert::ExpectException([&parser, argc, &argv]() { + Assert::ExpectException([&parser, argc, &argv]() { parser.parse(argc, argv); } ); @@ -129,7 +130,7 @@ namespace wperftest const wchar_t* argv[] = { L"wperf", L"invalid_command" }; const int argc = _countof(argv); arg_parser parser; - Assert::ExpectException([&parser, argc, &argv]() { + Assert::ExpectException([&parser, argc, &argv]() { parser.parse(argc, argv); } ); @@ -150,7 +151,7 @@ namespace wperftest const wchar_t* argv[] = { L"wperf", L"sample", L"--timeout", L"5.4", L"ms" }; const int argc = _countof(argv); arg_parser parser; - Assert::ExpectException([&parser, argc, &argv]() { + Assert::ExpectException([&parser, argc, &argv]() { parser.parse(argc, argv); } ); @@ -266,7 +267,7 @@ namespace wperftest const wchar_t* argv[] = { L"wperf", L"sample", L"--unknown" }; const int argc = _countof(argv); arg_parser parser; - Assert::ExpectException([&parser, argc, &argv]() { + Assert::ExpectException([&parser, argc, &argv]() { parser.parse(argc, argv); } ); @@ -278,7 +279,7 @@ namespace wperftest const wchar_t* argv[] = { L"wperf", L"--annotate", L"--json" }; const int argc = _countof(argv); arg_parser parser; - Assert::ExpectException([&parser, argc, &argv]() { + Assert::ExpectException([&parser, argc, &argv]() { parser.parse(argc, argv); } ); From e54f44cec70252808c8993667124be9422c2aec8 Mon Sep 17 00:00:00 2001 From: Nader Zouaoui Date: Fri, 29 Nov 2024 10:38:47 +0100 Subject: [PATCH 03/21] fix: update linker on all configurations --- wperf-lib/wperf-lib.vcxproj | 16 ++++++++-------- wperf-test/wperf-test.vcxproj | 6 +++--- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/wperf-lib/wperf-lib.vcxproj b/wperf-lib/wperf-lib.vcxproj index 493bda0..1db2b38 100644 --- a/wperf-lib/wperf-lib.vcxproj +++ b/wperf-lib/wperf-lib.vcxproj @@ -161,7 +161,7 @@ true - $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj + $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj;arg-parser.obj;arg-parser-arg.obj $(SolutionDir)wperf\$(IntDir) @@ -181,7 +181,7 @@ true - $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj + $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj;arg-parser.obj;arg-parser-arg.obj $(SolutionDir)wperf\$(IntDir) @@ -202,7 +202,7 @@ true - $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj + $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj;arg-parser.obj;arg-parser-arg.obj $(SolutionDir)wperf\$(IntDir) @@ -223,7 +223,7 @@ true - $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj + $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj;arg-parser.obj;arg-parser-arg.obj $(SolutionDir)wperf\$(IntDir) @@ -247,7 +247,7 @@ true true true - $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj + $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj;arg-parser.obj;arg-parser-arg.obj $(SolutionDir)wperf\$(IntDir) @@ -272,7 +272,7 @@ true true true - $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj + $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj;arg-parser.obj;arg-parser-arg.obj $(SolutionDir)wperf\$(IntDir) @@ -314,7 +314,7 @@ true - $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj + $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj;arg-parser.obj;arg-parser-arg.obj $(SolutionDir)wperf\$(IntDir) @@ -339,7 +339,7 @@ true true true - $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj + $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj;arg-parser.obj;arg-parser-arg.obj $(SolutionDir)wperf\$(IntDir) diff --git a/wperf-test/wperf-test.vcxproj b/wperf-test/wperf-test.vcxproj index 9de6e30..3168aeb 100644 --- a/wperf-test/wperf-test.vcxproj +++ b/wperf-test/wperf-test.vcxproj @@ -170,7 +170,7 @@ true true $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories);;$(SolutionDir)\wperf\$(Platform)\$(Configuration)\;$(SolutionDir)\wperf-lib\$(Platform)\$(Configuration)\ - $(CoreLibraryDependencies);%(AdditionalDependencies);utils.obj;pe_file.obj;output.obj;parsers.obj;events.obj;padding.obj;metric.obj;wperf.obj;pmu_device.obj;spe_device.obj;wperf-lib.obj;process_api.obj;config.obj;timeline.obj;perfdata.obj;user_request.obj + $(CoreLibraryDependencies);%(AdditionalDependencies);utils.obj;pe_file.obj;output.obj;parsers.obj;events.obj;padding.obj;metric.obj;wperf.obj;pmu_device.obj;spe_device.obj;wperf-lib.obj;process_api.obj;config.obj;timeline.obj;perfdata.obj;user_request.obj;arg-parser.obj;arg-parser-arg.obj @@ -240,7 +240,7 @@ $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories);;$(SolutionDir)\wperf\$(Platform)\$(Configuration)\;$(SolutionDir)\wperf-lib\$(Platform)\$(Configuration)\ - $(CoreLibraryDependencies);%(AdditionalDependencies);utils.obj;pe_file.obj;output.obj;parsers.obj;events.obj;padding.obj;metric.obj;wperf.obj;pmu_device.obj;spe_device.obj;wperf-lib.obj;process_api.obj;config.obj;timeline.obj;perfdata.obj;user_request.obj + $(CoreLibraryDependencies);%(AdditionalDependencies);utils.obj;pe_file.obj;output.obj;parsers.obj;events.obj;padding.obj;metric.obj;wperf.obj;pmu_device.obj;spe_device.obj;wperf-lib.obj;process_api.obj;config.obj;timeline.obj;perfdata.obj;user_request.obj;arg-parser.obj;arg-parser-arg.obj Windows @@ -259,7 +259,7 @@ $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories);;$(SolutionDir)\wperf\$(Platform)\$(Configuration)\;$(SolutionDir)\wperf-lib\$(Platform)\$(Configuration)\ - $(CoreLibraryDependencies);%(AdditionalDependencies);utils.obj;pe_file.obj;output.obj;parsers.obj;events.obj;padding.obj;metric.obj;wperf.obj;pmu_device.obj;spe_device.obj;wperf-lib.obj;process_api.obj;config.obj;timeline.obj;perfdata.obj;user_request.obj + $(CoreLibraryDependencies);%(AdditionalDependencies);utils.obj;pe_file.obj;output.obj;parsers.obj;events.obj;padding.obj;metric.obj;wperf.obj;pmu_device.obj;spe_device.obj;wperf-lib.obj;process_api.obj;config.obj;timeline.obj;perfdata.obj;user_request.obj;arg-parser.obj;arg-parser-arg.obj Windows From 50ff0b122eeec1702d4f686957a224e4c2609e22 Mon Sep 17 00:00:00 2001 From: Nader Zouaoui Date: Fri, 29 Nov 2024 10:45:53 +0100 Subject: [PATCH 04/21] fix: update file names in project linkers --- wperf-lib/wperf-lib.vcxproj | 18 +++++++++--------- wperf-test/wperf-test.vcxproj | 6 +++--- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/wperf-lib/wperf-lib.vcxproj b/wperf-lib/wperf-lib.vcxproj index 1db2b38..f682ac2 100644 --- a/wperf-lib/wperf-lib.vcxproj +++ b/wperf-lib/wperf-lib.vcxproj @@ -161,7 +161,7 @@ true - $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj;arg-parser.obj;arg-parser-arg.obj + $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj;arg_parser.obj;arg_parser_arg.obj $(SolutionDir)wperf\$(IntDir) @@ -181,7 +181,7 @@ true - $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj;arg-parser.obj;arg-parser-arg.obj + $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj;arg_parser.obj;arg_parser_arg.obj $(SolutionDir)wperf\$(IntDir) @@ -202,7 +202,7 @@ true - $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj;arg-parser.obj;arg-parser-arg.obj + $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj;arg_parser.obj;arg_parser_arg.obj $(SolutionDir)wperf\$(IntDir) @@ -223,7 +223,7 @@ true - $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj;arg-parser.obj;arg-parser-arg.obj + $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj;arg_parser.obj;arg_parser_arg.obj $(SolutionDir)wperf\$(IntDir) @@ -247,7 +247,7 @@ true true true - $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj;arg-parser.obj;arg-parser-arg.obj + $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj;arg_parser.obj;arg_parser_arg.obj $(SolutionDir)wperf\$(IntDir) @@ -272,7 +272,7 @@ true true true - $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj;arg-parser.obj;arg-parser-arg.obj + $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj;arg_parser.obj;arg_parser_arg.obj $(SolutionDir)wperf\$(IntDir) @@ -293,7 +293,7 @@ true - $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj;arg-parser.obj;arg-parser-arg.obj + $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj;arg_parser.obj;arg_parser_arg.obj $(SolutionDir)wperf\$(IntDir) @@ -314,7 +314,7 @@ true - $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj;arg-parser.obj;arg-parser-arg.obj + $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj;arg_parser.obj;arg_parser_arg.obj $(SolutionDir)wperf\$(IntDir) @@ -339,7 +339,7 @@ true true true - $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj;arg-parser.obj;arg-parser-arg.obj + $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj;arg_parser.obj;arg_parser_arg.obj $(SolutionDir)wperf\$(IntDir) diff --git a/wperf-test/wperf-test.vcxproj b/wperf-test/wperf-test.vcxproj index 3168aeb..887e5da 100644 --- a/wperf-test/wperf-test.vcxproj +++ b/wperf-test/wperf-test.vcxproj @@ -170,7 +170,7 @@ true true $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories);;$(SolutionDir)\wperf\$(Platform)\$(Configuration)\;$(SolutionDir)\wperf-lib\$(Platform)\$(Configuration)\ - $(CoreLibraryDependencies);%(AdditionalDependencies);utils.obj;pe_file.obj;output.obj;parsers.obj;events.obj;padding.obj;metric.obj;wperf.obj;pmu_device.obj;spe_device.obj;wperf-lib.obj;process_api.obj;config.obj;timeline.obj;perfdata.obj;user_request.obj;arg-parser.obj;arg-parser-arg.obj + $(CoreLibraryDependencies);%(AdditionalDependencies);utils.obj;pe_file.obj;output.obj;parsers.obj;events.obj;padding.obj;metric.obj;wperf.obj;pmu_device.obj;spe_device.obj;wperf-lib.obj;process_api.obj;config.obj;timeline.obj;perfdata.obj;user_request.obj;arg_parser.obj;arg_parser_arg.obj @@ -240,7 +240,7 @@ $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories);;$(SolutionDir)\wperf\$(Platform)\$(Configuration)\;$(SolutionDir)\wperf-lib\$(Platform)\$(Configuration)\ - $(CoreLibraryDependencies);%(AdditionalDependencies);utils.obj;pe_file.obj;output.obj;parsers.obj;events.obj;padding.obj;metric.obj;wperf.obj;pmu_device.obj;spe_device.obj;wperf-lib.obj;process_api.obj;config.obj;timeline.obj;perfdata.obj;user_request.obj;arg-parser.obj;arg-parser-arg.obj + $(CoreLibraryDependencies);%(AdditionalDependencies);utils.obj;pe_file.obj;output.obj;parsers.obj;events.obj;padding.obj;metric.obj;wperf.obj;pmu_device.obj;spe_device.obj;wperf-lib.obj;process_api.obj;config.obj;timeline.obj;perfdata.obj;user_request.obj;arg_parser.obj;arg_parser_arg.obj Windows @@ -259,7 +259,7 @@ $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories);;$(SolutionDir)\wperf\$(Platform)\$(Configuration)\;$(SolutionDir)\wperf-lib\$(Platform)\$(Configuration)\ - $(CoreLibraryDependencies);%(AdditionalDependencies);utils.obj;pe_file.obj;output.obj;parsers.obj;events.obj;padding.obj;metric.obj;wperf.obj;pmu_device.obj;spe_device.obj;wperf-lib.obj;process_api.obj;config.obj;timeline.obj;perfdata.obj;user_request.obj;arg-parser.obj;arg-parser-arg.obj + $(CoreLibraryDependencies);%(AdditionalDependencies);utils.obj;pe_file.obj;output.obj;parsers.obj;events.obj;padding.obj;metric.obj;wperf.obj;pmu_device.obj;spe_device.obj;wperf-lib.obj;process_api.obj;config.obj;timeline.obj;perfdata.obj;user_request.obj;arg_parser.obj;arg_parser_arg.obj Windows From 55ea90221c2812a29b3aa12de636e22a9a417224 Mon Sep 17 00:00:00 2001 From: Nader Zouaoui Date: Fri, 29 Nov 2024 10:46:56 +0100 Subject: [PATCH 05/21] fix: update includes in wperf project --- wperf/arg_parser.cpp | 2 +- wperf/main.cpp | 2 +- wperf/user_request.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/wperf/arg_parser.cpp b/wperf/arg_parser.cpp index 3e6b391..518c601 100644 --- a/wperf/arg_parser.cpp +++ b/wperf/arg_parser.cpp @@ -34,7 +34,7 @@ #include #include #include -#include "arg-parser.h" +#include "arg_parser.h" #include "output.h" #include "exception.h" diff --git a/wperf/main.cpp b/wperf/main.cpp index 55d439b..c9169da 100644 --- a/wperf/main.cpp +++ b/wperf/main.cpp @@ -50,7 +50,7 @@ #include "config.h" #include "perfdata.h" #include "disassembler.h" -#include "arg-parser.h" +#include "arg_parser.h" static bool no_ctrl_c = true; diff --git a/wperf/user_request.h b/wperf/user_request.h index 8a4827d..f27bf33 100644 --- a/wperf/user_request.h +++ b/wperf/user_request.h @@ -35,7 +35,7 @@ #include "utils.h" #include "events.h" #include "output.h" -#include "arg-parser.h" +#include "arg_parser.h" typedef std::vector wstr_vec; class user_request From 51f4bf9175c7334fe42eb4b778c03108e7016a9a Mon Sep 17 00:00:00 2001 From: Nader Zouaoui Date: Fri, 29 Nov 2024 10:56:41 +0100 Subject: [PATCH 06/21] feat: add export_perf_data argument --- wperf/arg_parser.h | 8 +++++++- wperf/user_request.cpp | 7 +------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/wperf/arg_parser.h b/wperf/arg_parser.h index 117de17..5f3a4da 100644 --- a/wperf/arg_parser.h +++ b/wperf/arg_parser.h @@ -243,7 +243,12 @@ namespace ArgParser { L"Enable timeline mode (count multiple times with specified interval). Use `-i` to specify timeline interval, and `-n` to specify number of counts.", {} ); - + arg_parser_arg_opt export_perf_data_opt = arg_parser_arg_opt::arg_parser_arg_opt( + L"--export_perf_data", + {}, + L"", + {} + ); #pragma endregion @@ -417,6 +422,7 @@ namespace ArgParser { &interval_arg, &iteration_arg, &dmc_arg, + &export_perf_data_opt, &extra_args_arg }; diff --git a/wperf/user_request.cpp b/wperf/user_request.cpp index 72777ac..f786c8e 100644 --- a/wperf/user_request.cpp +++ b/wperf/user_request.cpp @@ -604,12 +604,7 @@ void user_request::parse_raw_args(ArgParser::arg_parser& parsed_args, const stru m_outputType = TableType::JSON; m_out.m_isQuiet = true; } - // TODO: Check why This flag is not documented - //if (a == L"--export_perf_data") - //{ - // do_export_perf_data = true; - // continue; - //} + do_export_perf_data = parsed_args.export_perf_data_opt.is_set(); if (parsed_args.events_arg.is_set()) From 1ae14285fc7f425994b6a2ca8027e3e352c9c54b Mon Sep 17 00:00:00 2001 From: Nader Zouaoui Date: Fri, 29 Nov 2024 10:58:40 +0100 Subject: [PATCH 07/21] feat: added parsed_args vector to keep track --- wperf/arg_parser.cpp | 2 +- wperf/arg_parser.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/wperf/arg_parser.cpp b/wperf/arg_parser.cpp index 518c601..e7175aa 100644 --- a/wperf/arg_parser.cpp +++ b/wperf/arg_parser.cpp @@ -84,6 +84,7 @@ namespace ArgParser { { if (current_flag->parse(raw_args)) { raw_args.erase(raw_args.begin(), raw_args.begin() + current_flag->get_arg_count() + 1); + parsed_args.push_back(current_flag); } } catch (const std::exception& err) @@ -104,7 +105,6 @@ namespace ArgParser { void arg_parser::print_help() const { m_out.GetOutputStream() << L"NAME:\n" - << L"\twperf - Performance analysis tools for Windows on Arm\n\n" << L"\tUsage: wperf [options]\n\n" << L"SYNOPSIS:\n\n"; diff --git a/wperf/arg_parser.h b/wperf/arg_parser.h index 5f3a4da..786d5e3 100644 --- a/wperf/arg_parser.h +++ b/wperf/arg_parser.h @@ -425,7 +425,7 @@ namespace ArgParser { &export_perf_data_opt, &extra_args_arg }; - + std::vector parsed_args = {}; wstr_vec m_arg_array; #pragma endregion From 86dcc8a76028392a09050e1748c8a4c7fadd3a1a Mon Sep 17 00:00:00 2001 From: Nader Zouaoui Date: Fri, 29 Nov 2024 11:00:52 +0100 Subject: [PATCH 08/21] chore: remove missed comment --- wperf/arg_parser.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/wperf/arg_parser.cpp b/wperf/arg_parser.cpp index e7175aa..27910d0 100644 --- a/wperf/arg_parser.cpp +++ b/wperf/arg_parser.cpp @@ -145,11 +145,6 @@ namespace ArgParser { std::wstring indicator(pos, L'~'); indicator += L'^'; - /* - TODO: THIS function should change to use GetErrorOutputStream before migrating to wperf - - */ - std::wostringstream error_message; error_message << L"Invalid argument detected:\n" << command << L"\n" From 1fb59e5dc1711ccb9b1dfef15bb3ce2ce5c3fdf3 Mon Sep 17 00:00:00 2001 From: Nader Zouaoui Date: Fri, 29 Nov 2024 11:33:10 +0100 Subject: [PATCH 09/21] fix: update extra arg description --- wperf/arg_parser.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wperf/arg_parser.h b/wperf/arg_parser.h index 786d5e3..0fc8b0c 100644 --- a/wperf/arg_parser.h +++ b/wperf/arg_parser.h @@ -256,7 +256,7 @@ namespace ArgParser { arg_parser_arg_pos extra_args_arg = arg_parser_arg_pos::arg_parser_arg_pos( L"--", {}, - L"-- Process name is defined by COMMAND. User can pass verbatim arguments to the process with[ARGS].", + L"Double-dash is a syntax used signify end of command options. It separates `wperf` command line options from arguments that the process spawn command operates on. Use `--` to separate `wperf.exe` command line options from the process you want to spawn followed by its verbatim arguments.", {}, -1 ); From e18818272e1378aa073298487c193b2849268b54 Mon Sep 17 00:00:00 2001 From: Nader Zouaoui Date: Thu, 28 Nov 2024 17:06:40 +0100 Subject: [PATCH 10/21] feat: add arg_parser to user_request --- wperf/arg_parser.cpp | 20 +- wperf/arg_parser.h | 12 +- wperf/main.cpp | 28 +- wperf/user_request.cpp | 685 ++++++++++++----------------------------- wperf/user_request.h | 6 +- 5 files changed, 226 insertions(+), 525 deletions(-) diff --git a/wperf/arg_parser.cpp b/wperf/arg_parser.cpp index f512c59..3e6b391 100644 --- a/wperf/arg_parser.cpp +++ b/wperf/arg_parser.cpp @@ -28,13 +28,15 @@ // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#include "arg_parser.h" #include #include #include #include #include #include +#include "arg-parser.h" +#include "output.h" +#include "exception.h" namespace ArgParser { arg_parser::arg_parser() {} @@ -101,26 +103,26 @@ namespace ArgParser { void arg_parser::print_help() const { - std::wcout << L"NAME:\n" + m_out.GetOutputStream() << L"NAME:\n" << L"\twperf - Performance analysis tools for Windows on Arm\n\n" << L"\tUsage: wperf [options]\n\n" << L"SYNOPSIS:\n\n"; for (auto& command : m_commands_list) { - std::wcout << L"\t" << command->get_all_flags_string() << L"\n" << command->get_usage_text() << L"\n"; + m_out.GetOutputStream() << L"\t" << command->get_all_flags_string() << L"\n" << command->get_usage_text() << L"\n"; } - std::wcout << L"OPTIONS:\n\n"; + m_out.GetOutputStream() << L"OPTIONS:\n\n"; for (auto& flag : m_flags_list) { - std::wcout << L" " << flag->get_help() << L"\n"; + m_out.GetOutputStream() << L" " << flag->get_help() << L"\n"; } - std::wcout << L"EXAMPLES:\n\n"; + m_out.GetOutputStream() << L"EXAMPLES:\n\n"; for (auto& command : m_commands_list) { if (command->get_examples().empty()) continue; - std::wcout << L" " << command->get_examples() << L"\n"; + m_out.GetOutputStream() << L" " << command->get_examples() << L"\n"; } } @@ -155,8 +157,8 @@ namespace ArgParser { if (!additional_message.empty()) { error_message << additional_message << L"\n"; } - std::wcerr << error_message.str(); - throw std::invalid_argument("INVALID_ARGUMENT"); + m_out.GetErrorOutputStream() << error_message.str(); + throw fatal_exception("INVALID_ARGUMENT"); } #pragma endregion diff --git a/wperf/arg_parser.h b/wperf/arg_parser.h index 171d2b7..117de17 100644 --- a/wperf/arg_parser.h +++ b/wperf/arg_parser.h @@ -58,7 +58,7 @@ namespace ArgParser { MAN, NO_COMMAND }; - class arg_parser_arg_command : public arg_parser_arg_opt { + class arg_parser_arg_command : public arg_parser_arg_pos { public: arg_parser_arg_command( @@ -67,8 +67,9 @@ namespace ArgParser { const std::wstring description, const std::wstring useage_text, const COMMAND_CLASS command, - const wstr_vec examples - ) : arg_parser_arg_opt(name, alias, description), m_examples(examples), m_command(command), m_useage_text(useage_text) {}; + const wstr_vec examples, + const int arg_count = 0 + ) : arg_parser_arg_pos(name, alias, description, {}, arg_count), m_examples(examples), m_command(command), m_useage_text(useage_text) {}; const COMMAND_CLASS m_command = COMMAND_CLASS::NO_COMMAND; const wstr_vec m_examples; const std::wstring m_useage_text; @@ -180,7 +181,8 @@ namespace ArgParser { L"wperf man [--json]", COMMAND_CLASS::MAN, { - } + }, + 1 ); #pragma endregion @@ -346,7 +348,7 @@ namespace ArgParser { {} ); arg_parser_arg_pos iteration_arg = arg_parser_arg_pos::arg_parser_arg_pos( - L"-i", + L"-n", {}, L"Number of consecutive counts in timeline mode (disabled by default).", {} diff --git a/wperf/main.cpp b/wperf/main.cpp index f4fe611..55d439b 100644 --- a/wperf/main.cpp +++ b/wperf/main.cpp @@ -50,6 +50,7 @@ #include "config.h" #include "perfdata.h" #include "disassembler.h" +#include "arg-parser.h" static bool no_ctrl_c = true; @@ -81,10 +82,12 @@ wmain( ) { auto exit_code = EXIT_SUCCESS; + ArgParser::arg_parser arg_parser; + arg_parser.parse(argc, argv); + user_request request; pmu_device pmu_device; - wstr_vec raw_args; LLVMDisassembler disassembler; bool spawned_process = false; @@ -92,24 +95,14 @@ wmain( PROCESS_INFORMATION pi; ZeroMemory(&pi, sizeof(pi)); - //* Handle CLI options before we initialize PMU device(s) - for (int i = 1; i < argc; i++) - raw_args.push_back(argv[i]); - - pmu_device.do_force_lock = user_request::is_force_lock(raw_args); - - if (raw_args.size() == 1 && user_request::is_help(raw_args)) + if (arg_parser.m_command == ArgParser::COMMAND_CLASS::HELP) { - user_request::print_help(); + arg_parser.print_help(); goto clean_exit; } - if (raw_args.empty()) - { - user_request::print_help_header(); - user_request::print_help_prompt(); - goto clean_exit; - } + pmu_device.do_force_lock = arg_parser.force_lock_opt.is_set(); + //* Handle CLI options before we initialize PMU device(s) try { @@ -162,7 +155,7 @@ wmain( { struct pmu_device_cfg pmu_cfg; pmu_device.get_pmu_device_cfg(pmu_cfg); - request.init(raw_args, pmu_cfg, + request.init(arg_parser, pmu_cfg, pmu_device.builtin_metrics, pmu_device.get_product_groups_metrics_names(), pmu_events::extra_events); @@ -1340,7 +1333,8 @@ wmain( #if defined(ENABLE_ETW_TRACING_APP) EventUnregisterWindowsPerf_App(); #endif - + std::wstring hellp; + std::wcin >> hellp; if(spawned_process) { TerminateProcess(pi.hProcess, 0); diff --git a/wperf/user_request.cpp b/wperf/user_request.cpp index 1667935..72777ac 100644 --- a/wperf/user_request.cpp +++ b/wperf/user_request.cpp @@ -319,7 +319,7 @@ bool user_request::is_help(const wstr_vec& raw_args) || is_cli_option_in_args(raw_args, std::wstring(L"-h")); } -void user_request::init(wstr_vec& raw_args, const struct pmu_device_cfg& pmu_cfg, +void user_request::init(ArgParser::arg_parser& parsed_args, const struct pmu_device_cfg& pmu_cfg, std::map& builtin_metrics, const std::map >& groups_of_metrics, std::map>& extra_events) @@ -332,7 +332,7 @@ void user_request::init(wstr_vec& raw_args, const struct pmu_device_cfg& pmu_cfg cores_idx.resize(pmu_cfg.core_num); std::iota(cores_idx.begin(), cores_idx.end(), (UINT8)0); - parse_raw_args(raw_args, pmu_cfg, events, groups, builtin_metrics, groups_of_metrics, extra_events); + parse_raw_args(parsed_args, pmu_cfg, events, groups, builtin_metrics, groups_of_metrics, extra_events); // Deduce image name and PDB file name from PE file name if (sample_pe_file.size()) @@ -392,120 +392,237 @@ void user_request::init(wstr_vec& raw_args, const struct pmu_device_cfg& pmu_cfg check_events(EVT_DMC_CLKDIV2, MAX_MANAGED_DMC_CLKDIV2_EVENTS); } -void user_request::parse_raw_args(wstr_vec& raw_args, const struct pmu_device_cfg& pmu_cfg, +void user_request::parse_raw_args(ArgParser::arg_parser& parsed_args, const struct pmu_device_cfg& pmu_cfg, std::map>& events, std::map>& groups, std::map& builtin_metrics, const std::map >& groups_of_metrics, std::map>& extra_events) { - bool waiting_events = false; - bool waiting_metrics = false; - bool waiting_core_idx = false; - bool waiting_dmc_idx = false; - bool waiting_duration = false; - bool waiting_interval = false; - bool waiting_metric_config = false; - bool waiting_events_config = false; - bool waiting_output_filename = false; - bool waiting_output_csv_filename = false; - bool waiting_image_name = false; - bool waiting_pe_file = false; - bool waiting_pdb_file = false; - bool waiting_sample_display_row = false; - bool waiting_timeline_count = false; - bool waiting_config = false; - bool waiting_commandline = false; - bool waiting_record_spawn_delay = false; - bool waiting_man_query = false; - bool waiting_cwd = false; - bool waiting_symbol = false; + bool sample_pe_file_given = false; std::wstring waiting_duration_arg; std::wstring output_filename, output_csv_filename; - if (raw_args.empty()) + switch (parsed_args.m_command) { - print_help_header(); - print_help_prompt(); + case ArgParser::COMMAND_CLASS::STAT: + do_count = true; + break; + case ArgParser::COMMAND_CLASS::SAMPLE: + do_sample = true; + break; + case ArgParser::COMMAND_CLASS::RECORD: + do_record = true; + break; + case ArgParser::COMMAND_CLASS::TEST: + do_test = true; + break; + case ArgParser::COMMAND_CLASS::DETECT: + do_detect = true; + break; + case ArgParser::COMMAND_CLASS::HELP: + do_help = true; + break; + case ArgParser::COMMAND_CLASS::VERSION: + do_version = true; + break; + case ArgParser::COMMAND_CLASS::LIST: + do_list = true; + break; + case ArgParser::COMMAND_CLASS::MAN: + do_man = true; + break; + default: + break; } - for (const auto& a : raw_args) + if (parsed_args.metric_config_arg.is_set()) + { + load_config_metrics(parsed_args.metric_config_arg.get_values().front(), pmu_cfg); + } + if (parsed_args.event_config_arg.is_set()) + { + load_config_events(parsed_args.event_config_arg.get_values().front(), extra_events); + } + + if (builtin_metrics.size()) { - if (waiting_metric_config) + for (const auto& [key, value] : builtin_metrics) { - waiting_metric_config = false; - load_config_metrics(a, pmu_cfg); - continue; + if (metrics.find(key) == metrics.end()) + metrics[key] = value; } + } + if (parsed_args.extra_args_arg.is_set()) + { + if (sample_pe_file.empty()) + sample_pe_file = parsed_args.extra_args_arg.get_values().front(); + + record_commandline += WStringJoin(parsed_args.extra_args_arg.get_values(), L" "); + if (!(do_record || do_count)) + m_out.GetErrorOutputStream() << L"warning: only `stat` and `record` support process spawn!" << std::endl; + + sample_pe_file.clear(); + record_commandline.clear(); + } + if (parsed_args.output_prefix_arg.is_set()) + { + m_cwd = parsed_args.output_prefix_arg.get_values().front(); + } + if (parsed_args.output_filename_arg.is_set()) + { + output_filename = parsed_args.output_filename_arg.get_values().front(); + } - if (a == L"-C") - { - waiting_metric_config = true; - continue; - } + if (parsed_args.output_csv_filename_arg.is_set()) + { + output_csv_filename = parsed_args.output_csv_filename_arg.get_values().front(); + } - if (waiting_events_config) - { - waiting_events_config = false; - load_config_events(a, extra_events); - continue; - } + if (parsed_args.config_arg.is_set()) + { + wstring config_values = parsed_args.config_arg.get_values().front(); + if (drvconfig::set(config_values) == false) + m_out.GetErrorOutputStream() << L"error: can't set '" << config_values << "' config" << std::endl; + } + if (parsed_args.image_name_arg.is_set()) + { + sample_image_name = parsed_args.image_name_arg.get_values().front(); + } - if (a == L"-E") + if (parsed_args.pe_file_arg.is_set()) + { + wstring parsed_pe_file = parsed_args.pe_file_arg.get_values().front(); + if (std::filesystem::exists(parsed_pe_file) == false) { - waiting_events_config = true; - continue; + m_out.GetErrorOutputStream() << L"PE file '" << parsed_pe_file << L"' doesn't exist" + << std::endl; + throw fatal_exception("ERROR_PE_FILE_PATH"); } + sample_pe_file = parsed_pe_file; + sample_pe_file_given = true; } - - if (builtin_metrics.size()) + + if (parsed_args.pdb_file_arg.is_set()) { - for (const auto& [key, value] : builtin_metrics) + wstring parsed_pdb_file = parsed_args.pdb_file_arg.get_values().front(); + if (std::filesystem::exists(parsed_pdb_file) == false) { - if (metrics.find(key) == metrics.end()) - metrics[key] = value; + m_out.GetErrorOutputStream() << L"PDB file '" << parsed_pdb_file << L"' doesn't exist" + << std::endl; + throw fatal_exception("ERROR_PDB_FILE_PATH"); } + sample_pdb_file = parsed_pdb_file; } - for (const auto& a : raw_args) + + if (parsed_args.cores_arg.is_set()) { - if (waiting_commandline) - { - if (sample_pe_file.empty()) - { - sample_pe_file = a; - record_commandline = a; - } - else - record_commandline += L" " + a; - continue; - } + wstring core_idx_str = WStringJoin(parsed_args.cores_arg.get_values(), L","); - if (waiting_metric_config) + if (TokenizeWideStringOfInts(core_idx_str.c_str(), L',', cores_idx) == false) { - waiting_metric_config = false; - continue; + m_out.GetErrorOutputStream() << L"option -c format not supported, use comma separated list of integers, or range of integers" + << std::endl; + throw fatal_exception("ERROR_CORES"); } - if (waiting_events_config) + if (cores_idx.size() > MAX_PMU_CTL_CORES_COUNT) { - waiting_events_config = false; - continue; + m_out.GetErrorOutputStream() << L"you can specify up to " << int(MAX_PMU_CTL_CORES_COUNT) + << L"cores with -c option" + << std::endl; + throw fatal_exception("ERROR_CORES"); } + } + + if (parsed_args.iteration_arg.is_set()) + { + count_timeline = _wtoi(parsed_args.iteration_arg.get_values().front().c_str()); + } - if (waiting_events) + if (parsed_args.record_spawn_delay_arg.is_set()) + { + uint32_t val = _wtoi(parsed_args.record_spawn_delay_arg.get_values().front().c_str()); + assert(val <= UINT32_MAX); + record_spawn_delay = val; + } + + if (parsed_args.dmc_arg.is_set()) + { + + int val = _wtoi(parsed_args.output_filename_arg.get_values().front().c_str()); + assert(val <= UCHAR_MAX); + dmc_idx = (uint8_t)val; + } + + if (parsed_args.timeout_arg.is_set()) + { + count_duration = convert_timeout_arg_to_seconds(parsed_args.output_filename_arg.get_values().front(), parsed_args.timeout_arg.get_name()); + } + + if (parsed_args.interval_arg.is_set()) + { + count_interval = convert_timeout_arg_to_seconds(parsed_args.interval_arg.get_values().front(), parsed_args.interval_arg.get_name()); + } + + if (parsed_args.sample_display_row_arg.is_set()) + { + sample_display_row = _wtoi(parsed_args.sample_display_row_arg.get_values().front().c_str()); + } + + if (parsed_args.man_command.is_set()) + { + man_query_args = parsed_args.man_command.get_values().front(); + } + if (parsed_args.symbol_arg.is_set()) + { + symbol_arg = parsed_args.symbol_arg.get_values().front(); + do_symbol = true; + + } + do_disassembly = parsed_args.disassembly_opt.is_set(); + do_annotate = parsed_args.annotate_opt.is_set() || parsed_args.disassembly_opt.is_set(); + do_force_lock = parsed_args.force_lock_opt.is_set(); + do_kernel = parsed_args.kernel_opt.is_set(); + if (parsed_args.timeline_opt.is_set()) + { + do_timeline = true; + if (count_interval == -1.0) + count_interval = 60; + if (count_duration == -1.0) + count_duration = 1; + } + sample_display_short = !parsed_args.sample_display_long_opt.is_set(); + do_verbose = parsed_args.verbose_opt.is_set(); + m_out.m_isQuiet = parsed_args.quite_opt.is_set(); + if (parsed_args.json_opt.is_set() && m_outputType != TableType::ALL) + { + m_outputType = TableType::JSON; + m_out.m_isQuiet = true; + } + // TODO: Check why This flag is not documented + //if (a == L"--export_perf_data") + //{ + // do_export_perf_data = true; + // continue; + //} + + + if (parsed_args.events_arg.is_set()) { + wstring raw_events_string = WStringJoin(parsed_args.events_arg.get_values(), L","); if (do_sample || do_record) { m_sampling_flags.clear(); // Prepare to collect SPE filters - if (parse_events_str_for_feat_spe(a, m_sampling_flags)) // Check if we are sampling with SPE + if (parse_events_str_for_feat_spe(raw_events_string, m_sampling_flags)) // Check if we are sampling with SPE { if (pmu_cfg.has_spe == false) { - m_out.GetErrorOutputStream() << L"SPE is not supported by your hardware: " << a << std::endl; + m_out.GetErrorOutputStream() << L"SPE is not supported by your hardware: " << raw_events_string << std::endl; throw fatal_exception("ERROR_SPE_NOT_SUPP"); } @@ -538,7 +655,7 @@ void user_request::parse_raw_args(wstr_vec& raw_args, const struct pmu_device_cf } else // Software sampling (no SPE) { - parse_events_str_for_sample(a, ioctl_events_sample, sampling_inverval); + parse_events_str_for_sample(raw_events_string, ioctl_events_sample, sampling_inverval); // After events are parsed check if we can fulfil this request as sampling does not have multiplexing if (ioctl_events_sample.size() > pmu_cfg.total_gpc_num) { @@ -556,44 +673,14 @@ void user_request::parse_raw_args(wstr_vec& raw_args, const struct pmu_device_cf } } else - parse_events_str(a, events, groups, L"", pmu_cfg); - waiting_events = false; - continue; - } - - if (waiting_cwd) - { - waiting_cwd = false; - m_cwd = a; - continue; - } - - if (waiting_output_filename) - { - waiting_output_filename = false; - output_filename = a; - continue; - } - - if (waiting_output_csv_filename) - { - waiting_output_csv_filename = false; - output_csv_filename = a; - continue; - } - - if (waiting_config) - { - waiting_config = false; - if (drvconfig::set(a) == false) - m_out.GetErrorOutputStream() << L"error: can't set '" << a << "' config" << std::endl; - continue; + parse_events_str(raw_events_string, events, groups, L"", pmu_cfg); } - if (waiting_metrics) + if (parsed_args.metrics_arg.is_set()) { + wstring raw_metrics_string = WStringJoin(parsed_args.metrics_arg.get_values(), L","); std::vector list_of_defined_metrics; - std::wistringstream metric_stream(a); + std::wistringstream metric_stream(raw_metrics_string); std::wstring metric_token; while (std::getline(metric_stream, metric_token, L',')) @@ -642,392 +729,8 @@ void user_request::parse_raw_args(wstr_vec& raw_args, const struct pmu_device_cf else if (metric == L"ddr_bw") report_ddr_bw_metric = true; } - - waiting_metrics = false; - continue; - } - - if (waiting_image_name) - { - sample_image_name = a; - waiting_image_name = false; - continue; - } - - if (waiting_pe_file) - { - if (std::filesystem::exists(a) == false) - { - m_out.GetErrorOutputStream() << L"PE file '" << a << L"' doesn't exist" - << std::endl; - throw fatal_exception("ERROR_PE_FILE_PATH"); - } - - sample_pe_file = a; - sample_pe_file_given = true; - waiting_pe_file = false; - continue; - } - - if (waiting_pdb_file) - { - if (std::filesystem::exists(a) == false) - { - m_out.GetErrorOutputStream() << L"PDB file '" << a << L"' doesn't exist" - << std::endl; - throw fatal_exception("ERROR_PDB_FILE_PATH"); - } - - sample_pdb_file = a; - waiting_pdb_file = false; - continue; - } - - if (waiting_core_idx) - { - if (TokenizeWideStringOfInts(a.c_str(), L',', cores_idx) == false) - { - m_out.GetErrorOutputStream() << L"option -c format not supported, use comma separated list of integers, or range of integers" - << std::endl; - throw fatal_exception("ERROR_CORES"); - } - - if (cores_idx.size() > MAX_PMU_CTL_CORES_COUNT) - { - m_out.GetErrorOutputStream() << L"you can specify up to " << int(MAX_PMU_CTL_CORES_COUNT) - << L"cores with -c option" - << std::endl; - throw fatal_exception("ERROR_CORES"); - } - - waiting_core_idx = false; - continue; - } - - if (waiting_timeline_count) - { - count_timeline = _wtoi(a.c_str()); - waiting_timeline_count = false; - continue; - } - - if (waiting_record_spawn_delay) - { - uint32_t val = _wtoi(a.c_str()); - assert(val <= UINT32_MAX); - record_spawn_delay = val; - waiting_record_spawn_delay = false; - continue; - } - - if (waiting_dmc_idx) - { - int val = _wtoi(a.c_str()); - assert(val <= UCHAR_MAX); - dmc_idx = (uint8_t)val; - waiting_dmc_idx = false; - continue; - } - - if (waiting_duration) - { - count_duration = convert_timeout_arg_to_seconds(a, waiting_duration_arg); - waiting_duration = false; - continue; - } - - if (waiting_interval) - { - count_interval = convert_timeout_arg_to_seconds(a, waiting_duration_arg); - waiting_interval = false; - continue; - } - - if (waiting_sample_display_row) - { - sample_display_row = _wtoi(a.c_str()); - waiting_sample_display_row = false; - continue; - } - - if (waiting_man_query) - { - man_query_args = a; - waiting_man_query = false; - continue; - } - - if (waiting_symbol) - { - symbol_arg = a; - waiting_symbol = false; - continue; - } - - // For compatibility with Linux perf - if (a == L"list" || a == L"-l") - { - do_list = true; - continue; - } - - if (a == L"-e") - { - waiting_events = true; - continue; - } - - if (a == L"-C") // Skip this one as it was handled before any other args - { - waiting_metric_config = true; - continue; - } - - if (a == L"-E") // Skip this one as it was handled before any other args - { - waiting_events_config = true; - continue; - } - - if (a == L"-m") - { - waiting_metrics = true; - continue; - } - - if (a == L"stat") - { - do_count = true; - continue; - } - - if (a == L"record") - { - do_record = true; - continue; - } - - if (a == L"sample") - { - do_sample = true; - continue; - } - - if (a == L"detect") - { - do_detect = true; - continue; - } - if (a == L"man") - { - do_man = true; - waiting_man_query = true; - continue; - } - - if (a == L"--image_name") - { - waiting_image_name = true; - continue; - } - - if (a == L"--disassemble") - { - do_disassembly = true; - do_annotate = true; - continue; - } - - if (a == L"--force-lock") - { - do_force_lock = true; - continue; - } - - if (a == L"--export_perf_data") - { - do_export_perf_data = true; - continue; - } - - if (a == L"--record_spawn_delay") - { - waiting_record_spawn_delay = true; - continue; - } - - if (a == L"--pe_file") - { - waiting_pe_file = true; - continue; - } - - if (a == L"--pdb_file") - { - waiting_pdb_file = true; - continue; - } - - if (a == L"--timeout" || a == L"sleep") - { - waiting_duration = true; - waiting_duration_arg = a; - continue; - } - - if (a == L"--cwd" || a == L"--output-prefix") - { - waiting_cwd = true; - continue; - } - - if (a == L"--output" || a == L"-o") - { - waiting_output_filename = true; - continue; - } - - if (a == L"--output-csv") - { - waiting_output_csv_filename = true; - continue; - } - - if (a == L"--config") - { - waiting_config = true; - continue; - } - - if (a == L"-k") - { - do_kernel = true; - continue; - } - - if (a == L"-t") - { - do_timeline = true; - if (count_interval == -1.0) - count_interval = 60; - if (count_duration == -1.0) - count_duration = 1; - continue; - } - - if (a == L"-n") - { - waiting_timeline_count = true; - continue; - } - - if (a == L"--sample-display-row") - { - waiting_sample_display_row = true; - continue; - } - - if (a == L"--sample-display-long") - { - sample_display_short = false; - continue; - } - - if (a == L"-i") - { - waiting_duration_arg = a; - waiting_interval = true; - continue; - } - - if (a == L"-c" || a == L"--cpu") - { - waiting_core_idx = true; - continue; - } - - if (a == L"--dmc") - { - waiting_dmc_idx = true; - continue; - } - - if (a == L"-v" || a == L"--verbose") - { - do_verbose = true; - continue; - } - - if (a == L"--annotate") - { - do_annotate = true; - continue; - } - - if (a == L"--version") - { - do_version = true; - continue; - } - - if (a == L"-h" || a == L"--help") - { - do_help = true; - continue; - } - - if (a == L"-q") - { - m_out.m_isQuiet = true; - continue; - } - - if (a == L"--json") - { - if (m_outputType != TableType::ALL) - { - m_outputType = TableType::JSON; - m_out.m_isQuiet = true; - } - continue; - } - - if (a == L"test") - { - do_test = true; - continue; - } - - if (a == L"-s" || a == L"--symbol") - { - do_symbol = true; - waiting_symbol = true; - continue; - } - - /* This will finish command line argument parsing. After "--" we will see process to spawn in form of: - * - * wperf ... -- PROCESS_NAME ARG ARG ARG ARG ... - * - * From now on we will parse process spawn name and verbatim arguments - */ - if (a == L"--") - { - if (!(do_record || do_count)) - m_out.GetErrorOutputStream() << L"warning: only `stat` and `record` support process spawn!" << std::endl; - - waiting_commandline = true; - /* We will reload here PE file name to spawn. `waiting_commandline` will expect this - * to be empty to detect beggining of the scan. - */ - sample_pe_file.clear(); - record_commandline.clear(); - continue; } - m_out.GetErrorOutputStream() << L"warning: unexpected arg '" << a << L"' ignored" << std::endl; - } - std::wstring output_filename_full_path = output_filename; std::wstring output_filename_csv_full_path = output_csv_filename; diff --git a/wperf/user_request.h b/wperf/user_request.h index 25dad10..8a4827d 100644 --- a/wperf/user_request.h +++ b/wperf/user_request.h @@ -35,7 +35,7 @@ #include "utils.h" #include "events.h" #include "output.h" - +#include "arg-parser.h" typedef std::vector wstr_vec; class user_request @@ -43,12 +43,12 @@ class user_request public: user_request(); - void init(wstr_vec& raw_args, const struct pmu_device_cfg& pmu_cfg, + void init(ArgParser::arg_parser& parsed_args, const struct pmu_device_cfg& pmu_cfg, std::map& builtin_metrics, const std::map >& groups_of_metrics, std::map>& extra_events); - void parse_raw_args(wstr_vec& raw_args, const struct pmu_device_cfg& pmu_cfg, + void parse_raw_args(ArgParser::arg_parser& parsed_args, const struct pmu_device_cfg& pmu_cfg, std::map>& events, std::map>& groups, std::map& builtin_metrics, From 1e041bd797ad86731fa3be079e87edfcf9dc4468 Mon Sep 17 00:00:00 2001 From: Nader Zouaoui Date: Thu, 28 Nov 2024 17:17:19 +0100 Subject: [PATCH 11/21] feat: update tests --- wperf-lib/wperf-lib.vcxproj | 2 +- wperf-test/wperf-test-arg_parser.cpp | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/wperf-lib/wperf-lib.vcxproj b/wperf-lib/wperf-lib.vcxproj index dff9fdc..493bda0 100644 --- a/wperf-lib/wperf-lib.vcxproj +++ b/wperf-lib/wperf-lib.vcxproj @@ -293,7 +293,7 @@ true - $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj + $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj;arg-parser.obj;arg-parser-arg.obj $(SolutionDir)wperf\$(IntDir) diff --git a/wperf-test/wperf-test-arg_parser.cpp b/wperf-test/wperf-test-arg_parser.cpp index d4cebad..9144795 100644 --- a/wperf-test/wperf-test-arg_parser.cpp +++ b/wperf-test/wperf-test-arg_parser.cpp @@ -32,6 +32,7 @@ #include "CppUnitTest.h" #include #include "wperf/arg_parser.h" +#include "wperf/exception.h" using namespace Microsoft::VisualStudio::CppUnitTestFramework; using namespace ArgParser; @@ -61,7 +62,7 @@ namespace wperftest const wchar_t* argv[] = { L"wperf", L"test", L"-v", L"--json", L"random" }; const int argc = _countof(argv); arg_parser parser; - Assert::ExpectException([&parser, argc, &argv]() { + Assert::ExpectException([&parser, argc, &argv]() { parser.parse(argc, argv); } ); @@ -117,7 +118,7 @@ namespace wperftest const wchar_t* argv[] = { L"wperf", L"sample", L"--timeout" }; const int argc = _countof(argv); arg_parser parser; - Assert::ExpectException([&parser, argc, &argv]() { + Assert::ExpectException([&parser, argc, &argv]() { parser.parse(argc, argv); } ); @@ -129,7 +130,7 @@ namespace wperftest const wchar_t* argv[] = { L"wperf", L"invalid_command" }; const int argc = _countof(argv); arg_parser parser; - Assert::ExpectException([&parser, argc, &argv]() { + Assert::ExpectException([&parser, argc, &argv]() { parser.parse(argc, argv); } ); @@ -150,7 +151,7 @@ namespace wperftest const wchar_t* argv[] = { L"wperf", L"sample", L"--timeout", L"5.4", L"ms" }; const int argc = _countof(argv); arg_parser parser; - Assert::ExpectException([&parser, argc, &argv]() { + Assert::ExpectException([&parser, argc, &argv]() { parser.parse(argc, argv); } ); @@ -266,7 +267,7 @@ namespace wperftest const wchar_t* argv[] = { L"wperf", L"sample", L"--unknown" }; const int argc = _countof(argv); arg_parser parser; - Assert::ExpectException([&parser, argc, &argv]() { + Assert::ExpectException([&parser, argc, &argv]() { parser.parse(argc, argv); } ); @@ -278,7 +279,7 @@ namespace wperftest const wchar_t* argv[] = { L"wperf", L"--annotate", L"--json" }; const int argc = _countof(argv); arg_parser parser; - Assert::ExpectException([&parser, argc, &argv]() { + Assert::ExpectException([&parser, argc, &argv]() { parser.parse(argc, argv); } ); From 2a2146e5cbc9e6e7adaba5d98995900af6011b26 Mon Sep 17 00:00:00 2001 From: Nader Zouaoui Date: Fri, 29 Nov 2024 10:38:47 +0100 Subject: [PATCH 12/21] fix: update linker on all configurations --- wperf-lib/wperf-lib.vcxproj | 16 ++++++++-------- wperf-test/wperf-test.vcxproj | 6 +++--- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/wperf-lib/wperf-lib.vcxproj b/wperf-lib/wperf-lib.vcxproj index 493bda0..1db2b38 100644 --- a/wperf-lib/wperf-lib.vcxproj +++ b/wperf-lib/wperf-lib.vcxproj @@ -161,7 +161,7 @@ true - $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj + $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj;arg-parser.obj;arg-parser-arg.obj $(SolutionDir)wperf\$(IntDir) @@ -181,7 +181,7 @@ true - $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj + $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj;arg-parser.obj;arg-parser-arg.obj $(SolutionDir)wperf\$(IntDir) @@ -202,7 +202,7 @@ true - $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj + $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj;arg-parser.obj;arg-parser-arg.obj $(SolutionDir)wperf\$(IntDir) @@ -223,7 +223,7 @@ true - $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj + $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj;arg-parser.obj;arg-parser-arg.obj $(SolutionDir)wperf\$(IntDir) @@ -247,7 +247,7 @@ true true true - $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj + $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj;arg-parser.obj;arg-parser-arg.obj $(SolutionDir)wperf\$(IntDir) @@ -272,7 +272,7 @@ true true true - $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj + $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj;arg-parser.obj;arg-parser-arg.obj $(SolutionDir)wperf\$(IntDir) @@ -314,7 +314,7 @@ true - $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj + $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj;arg-parser.obj;arg-parser-arg.obj $(SolutionDir)wperf\$(IntDir) @@ -339,7 +339,7 @@ true true true - $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj + $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj;arg-parser.obj;arg-parser-arg.obj $(SolutionDir)wperf\$(IntDir) diff --git a/wperf-test/wperf-test.vcxproj b/wperf-test/wperf-test.vcxproj index 9de6e30..3168aeb 100644 --- a/wperf-test/wperf-test.vcxproj +++ b/wperf-test/wperf-test.vcxproj @@ -170,7 +170,7 @@ true true $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories);;$(SolutionDir)\wperf\$(Platform)\$(Configuration)\;$(SolutionDir)\wperf-lib\$(Platform)\$(Configuration)\ - $(CoreLibraryDependencies);%(AdditionalDependencies);utils.obj;pe_file.obj;output.obj;parsers.obj;events.obj;padding.obj;metric.obj;wperf.obj;pmu_device.obj;spe_device.obj;wperf-lib.obj;process_api.obj;config.obj;timeline.obj;perfdata.obj;user_request.obj + $(CoreLibraryDependencies);%(AdditionalDependencies);utils.obj;pe_file.obj;output.obj;parsers.obj;events.obj;padding.obj;metric.obj;wperf.obj;pmu_device.obj;spe_device.obj;wperf-lib.obj;process_api.obj;config.obj;timeline.obj;perfdata.obj;user_request.obj;arg-parser.obj;arg-parser-arg.obj @@ -240,7 +240,7 @@ $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories);;$(SolutionDir)\wperf\$(Platform)\$(Configuration)\;$(SolutionDir)\wperf-lib\$(Platform)\$(Configuration)\ - $(CoreLibraryDependencies);%(AdditionalDependencies);utils.obj;pe_file.obj;output.obj;parsers.obj;events.obj;padding.obj;metric.obj;wperf.obj;pmu_device.obj;spe_device.obj;wperf-lib.obj;process_api.obj;config.obj;timeline.obj;perfdata.obj;user_request.obj + $(CoreLibraryDependencies);%(AdditionalDependencies);utils.obj;pe_file.obj;output.obj;parsers.obj;events.obj;padding.obj;metric.obj;wperf.obj;pmu_device.obj;spe_device.obj;wperf-lib.obj;process_api.obj;config.obj;timeline.obj;perfdata.obj;user_request.obj;arg-parser.obj;arg-parser-arg.obj Windows @@ -259,7 +259,7 @@ $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories);;$(SolutionDir)\wperf\$(Platform)\$(Configuration)\;$(SolutionDir)\wperf-lib\$(Platform)\$(Configuration)\ - $(CoreLibraryDependencies);%(AdditionalDependencies);utils.obj;pe_file.obj;output.obj;parsers.obj;events.obj;padding.obj;metric.obj;wperf.obj;pmu_device.obj;spe_device.obj;wperf-lib.obj;process_api.obj;config.obj;timeline.obj;perfdata.obj;user_request.obj + $(CoreLibraryDependencies);%(AdditionalDependencies);utils.obj;pe_file.obj;output.obj;parsers.obj;events.obj;padding.obj;metric.obj;wperf.obj;pmu_device.obj;spe_device.obj;wperf-lib.obj;process_api.obj;config.obj;timeline.obj;perfdata.obj;user_request.obj;arg-parser.obj;arg-parser-arg.obj Windows From 984f5a49c4452a48d8e527d9760ad9a5fddb85c6 Mon Sep 17 00:00:00 2001 From: Nader Zouaoui Date: Fri, 29 Nov 2024 10:45:53 +0100 Subject: [PATCH 13/21] fix: update file names in project linkers --- wperf-lib/wperf-lib.vcxproj | 18 +++++++++--------- wperf-test/wperf-test.vcxproj | 6 +++--- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/wperf-lib/wperf-lib.vcxproj b/wperf-lib/wperf-lib.vcxproj index 1db2b38..f682ac2 100644 --- a/wperf-lib/wperf-lib.vcxproj +++ b/wperf-lib/wperf-lib.vcxproj @@ -161,7 +161,7 @@ true - $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj;arg-parser.obj;arg-parser-arg.obj + $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj;arg_parser.obj;arg_parser_arg.obj $(SolutionDir)wperf\$(IntDir) @@ -181,7 +181,7 @@ true - $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj;arg-parser.obj;arg-parser-arg.obj + $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj;arg_parser.obj;arg_parser_arg.obj $(SolutionDir)wperf\$(IntDir) @@ -202,7 +202,7 @@ true - $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj;arg-parser.obj;arg-parser-arg.obj + $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj;arg_parser.obj;arg_parser_arg.obj $(SolutionDir)wperf\$(IntDir) @@ -223,7 +223,7 @@ true - $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj;arg-parser.obj;arg-parser-arg.obj + $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj;arg_parser.obj;arg_parser_arg.obj $(SolutionDir)wperf\$(IntDir) @@ -247,7 +247,7 @@ true true true - $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj;arg-parser.obj;arg-parser-arg.obj + $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj;arg_parser.obj;arg_parser_arg.obj $(SolutionDir)wperf\$(IntDir) @@ -272,7 +272,7 @@ true true true - $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj;arg-parser.obj;arg-parser-arg.obj + $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj;arg_parser.obj;arg_parser_arg.obj $(SolutionDir)wperf\$(IntDir) @@ -293,7 +293,7 @@ true - $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj;arg-parser.obj;arg-parser-arg.obj + $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj;arg_parser.obj;arg_parser_arg.obj $(SolutionDir)wperf\$(IntDir) @@ -314,7 +314,7 @@ true - $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj;arg-parser.obj;arg-parser-arg.obj + $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj;arg_parser.obj;arg_parser_arg.obj $(SolutionDir)wperf\$(IntDir) @@ -339,7 +339,7 @@ true true true - $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj;arg-parser.obj;arg-parser-arg.obj + $(CoreLibraryDependencies);%(AdditionalDependencies);events.obj;output.obj;padding.obj;parsers.obj;pe_file.obj;pmu_device.obj;spe_device.obj;process_api.obj;user_request.obj;utils.obj;wperf.obj;metric.obj;config.obj;timeline.obj;perfdata.obj;arg_parser.obj;arg_parser_arg.obj $(SolutionDir)wperf\$(IntDir) diff --git a/wperf-test/wperf-test.vcxproj b/wperf-test/wperf-test.vcxproj index 3168aeb..887e5da 100644 --- a/wperf-test/wperf-test.vcxproj +++ b/wperf-test/wperf-test.vcxproj @@ -170,7 +170,7 @@ true true $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories);;$(SolutionDir)\wperf\$(Platform)\$(Configuration)\;$(SolutionDir)\wperf-lib\$(Platform)\$(Configuration)\ - $(CoreLibraryDependencies);%(AdditionalDependencies);utils.obj;pe_file.obj;output.obj;parsers.obj;events.obj;padding.obj;metric.obj;wperf.obj;pmu_device.obj;spe_device.obj;wperf-lib.obj;process_api.obj;config.obj;timeline.obj;perfdata.obj;user_request.obj;arg-parser.obj;arg-parser-arg.obj + $(CoreLibraryDependencies);%(AdditionalDependencies);utils.obj;pe_file.obj;output.obj;parsers.obj;events.obj;padding.obj;metric.obj;wperf.obj;pmu_device.obj;spe_device.obj;wperf-lib.obj;process_api.obj;config.obj;timeline.obj;perfdata.obj;user_request.obj;arg_parser.obj;arg_parser_arg.obj @@ -240,7 +240,7 @@ $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories);;$(SolutionDir)\wperf\$(Platform)\$(Configuration)\;$(SolutionDir)\wperf-lib\$(Platform)\$(Configuration)\ - $(CoreLibraryDependencies);%(AdditionalDependencies);utils.obj;pe_file.obj;output.obj;parsers.obj;events.obj;padding.obj;metric.obj;wperf.obj;pmu_device.obj;spe_device.obj;wperf-lib.obj;process_api.obj;config.obj;timeline.obj;perfdata.obj;user_request.obj;arg-parser.obj;arg-parser-arg.obj + $(CoreLibraryDependencies);%(AdditionalDependencies);utils.obj;pe_file.obj;output.obj;parsers.obj;events.obj;padding.obj;metric.obj;wperf.obj;pmu_device.obj;spe_device.obj;wperf-lib.obj;process_api.obj;config.obj;timeline.obj;perfdata.obj;user_request.obj;arg_parser.obj;arg_parser_arg.obj Windows @@ -259,7 +259,7 @@ $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories);;$(SolutionDir)\wperf\$(Platform)\$(Configuration)\;$(SolutionDir)\wperf-lib\$(Platform)\$(Configuration)\ - $(CoreLibraryDependencies);%(AdditionalDependencies);utils.obj;pe_file.obj;output.obj;parsers.obj;events.obj;padding.obj;metric.obj;wperf.obj;pmu_device.obj;spe_device.obj;wperf-lib.obj;process_api.obj;config.obj;timeline.obj;perfdata.obj;user_request.obj;arg-parser.obj;arg-parser-arg.obj + $(CoreLibraryDependencies);%(AdditionalDependencies);utils.obj;pe_file.obj;output.obj;parsers.obj;events.obj;padding.obj;metric.obj;wperf.obj;pmu_device.obj;spe_device.obj;wperf-lib.obj;process_api.obj;config.obj;timeline.obj;perfdata.obj;user_request.obj;arg_parser.obj;arg_parser_arg.obj Windows From 816e3c3cf7e3a0432d5ce4694758fc013a361b69 Mon Sep 17 00:00:00 2001 From: Nader Zouaoui Date: Fri, 29 Nov 2024 10:46:56 +0100 Subject: [PATCH 14/21] fix: update includes in wperf project --- wperf/arg_parser.cpp | 2 +- wperf/main.cpp | 2 +- wperf/user_request.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/wperf/arg_parser.cpp b/wperf/arg_parser.cpp index 3e6b391..518c601 100644 --- a/wperf/arg_parser.cpp +++ b/wperf/arg_parser.cpp @@ -34,7 +34,7 @@ #include #include #include -#include "arg-parser.h" +#include "arg_parser.h" #include "output.h" #include "exception.h" diff --git a/wperf/main.cpp b/wperf/main.cpp index 55d439b..c9169da 100644 --- a/wperf/main.cpp +++ b/wperf/main.cpp @@ -50,7 +50,7 @@ #include "config.h" #include "perfdata.h" #include "disassembler.h" -#include "arg-parser.h" +#include "arg_parser.h" static bool no_ctrl_c = true; diff --git a/wperf/user_request.h b/wperf/user_request.h index 8a4827d..f27bf33 100644 --- a/wperf/user_request.h +++ b/wperf/user_request.h @@ -35,7 +35,7 @@ #include "utils.h" #include "events.h" #include "output.h" -#include "arg-parser.h" +#include "arg_parser.h" typedef std::vector wstr_vec; class user_request From 9192d13e453dfa4e4125bb1182cdca3d3a7736c4 Mon Sep 17 00:00:00 2001 From: Nader Zouaoui Date: Fri, 29 Nov 2024 10:56:41 +0100 Subject: [PATCH 15/21] feat: add export_perf_data argument --- wperf/arg_parser.h | 8 +++++++- wperf/user_request.cpp | 7 +------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/wperf/arg_parser.h b/wperf/arg_parser.h index 117de17..5f3a4da 100644 --- a/wperf/arg_parser.h +++ b/wperf/arg_parser.h @@ -243,7 +243,12 @@ namespace ArgParser { L"Enable timeline mode (count multiple times with specified interval). Use `-i` to specify timeline interval, and `-n` to specify number of counts.", {} ); - + arg_parser_arg_opt export_perf_data_opt = arg_parser_arg_opt::arg_parser_arg_opt( + L"--export_perf_data", + {}, + L"", + {} + ); #pragma endregion @@ -417,6 +422,7 @@ namespace ArgParser { &interval_arg, &iteration_arg, &dmc_arg, + &export_perf_data_opt, &extra_args_arg }; diff --git a/wperf/user_request.cpp b/wperf/user_request.cpp index 72777ac..f786c8e 100644 --- a/wperf/user_request.cpp +++ b/wperf/user_request.cpp @@ -604,12 +604,7 @@ void user_request::parse_raw_args(ArgParser::arg_parser& parsed_args, const stru m_outputType = TableType::JSON; m_out.m_isQuiet = true; } - // TODO: Check why This flag is not documented - //if (a == L"--export_perf_data") - //{ - // do_export_perf_data = true; - // continue; - //} + do_export_perf_data = parsed_args.export_perf_data_opt.is_set(); if (parsed_args.events_arg.is_set()) From 5584b5ad6b38eda27afdc88489fc509c846a10fa Mon Sep 17 00:00:00 2001 From: Nader Zouaoui Date: Fri, 29 Nov 2024 10:58:40 +0100 Subject: [PATCH 16/21] feat: added parsed_args vector to keep track --- wperf/arg_parser.cpp | 2 +- wperf/arg_parser.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/wperf/arg_parser.cpp b/wperf/arg_parser.cpp index 518c601..e7175aa 100644 --- a/wperf/arg_parser.cpp +++ b/wperf/arg_parser.cpp @@ -84,6 +84,7 @@ namespace ArgParser { { if (current_flag->parse(raw_args)) { raw_args.erase(raw_args.begin(), raw_args.begin() + current_flag->get_arg_count() + 1); + parsed_args.push_back(current_flag); } } catch (const std::exception& err) @@ -104,7 +105,6 @@ namespace ArgParser { void arg_parser::print_help() const { m_out.GetOutputStream() << L"NAME:\n" - << L"\twperf - Performance analysis tools for Windows on Arm\n\n" << L"\tUsage: wperf [options]\n\n" << L"SYNOPSIS:\n\n"; diff --git a/wperf/arg_parser.h b/wperf/arg_parser.h index 5f3a4da..786d5e3 100644 --- a/wperf/arg_parser.h +++ b/wperf/arg_parser.h @@ -425,7 +425,7 @@ namespace ArgParser { &export_perf_data_opt, &extra_args_arg }; - + std::vector parsed_args = {}; wstr_vec m_arg_array; #pragma endregion From 4d06b50e46383f475a5f9143d3ec41028c004a60 Mon Sep 17 00:00:00 2001 From: Nader Zouaoui Date: Fri, 29 Nov 2024 11:00:52 +0100 Subject: [PATCH 17/21] chore: remove missed comment --- wperf/arg_parser.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/wperf/arg_parser.cpp b/wperf/arg_parser.cpp index e7175aa..27910d0 100644 --- a/wperf/arg_parser.cpp +++ b/wperf/arg_parser.cpp @@ -145,11 +145,6 @@ namespace ArgParser { std::wstring indicator(pos, L'~'); indicator += L'^'; - /* - TODO: THIS function should change to use GetErrorOutputStream before migrating to wperf - - */ - std::wostringstream error_message; error_message << L"Invalid argument detected:\n" << command << L"\n" From 600d2d12233825e3a31ba735dec1c703543d6f32 Mon Sep 17 00:00:00 2001 From: Nader Zouaoui Date: Fri, 29 Nov 2024 11:33:10 +0100 Subject: [PATCH 18/21] fix: update extra arg description --- wperf/arg_parser.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wperf/arg_parser.h b/wperf/arg_parser.h index 786d5e3..0fc8b0c 100644 --- a/wperf/arg_parser.h +++ b/wperf/arg_parser.h @@ -256,7 +256,7 @@ namespace ArgParser { arg_parser_arg_pos extra_args_arg = arg_parser_arg_pos::arg_parser_arg_pos( L"--", {}, - L"-- Process name is defined by COMMAND. User can pass verbatim arguments to the process with[ARGS].", + L"Double-dash is a syntax used signify end of command options. It separates `wperf` command line options from arguments that the process spawn command operates on. Use `--` to separate `wperf.exe` command line options from the process you want to spawn followed by its verbatim arguments.", {}, -1 ); From 0ae89448baad7bf885c53edb1d48519a168e449b Mon Sep 17 00:00:00 2001 From: Nader Zouaoui Date: Fri, 29 Nov 2024 11:51:56 +0100 Subject: [PATCH 19/21] docs: add description to export_perf_data flag --- wperf/arg_parser.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wperf/arg_parser.h b/wperf/arg_parser.h index 0fc8b0c..a1ff0ef 100644 --- a/wperf/arg_parser.h +++ b/wperf/arg_parser.h @@ -246,7 +246,7 @@ namespace ArgParser { arg_parser_arg_opt export_perf_data_opt = arg_parser_arg_opt::arg_parser_arg_opt( L"--export_perf_data", {}, - L"", + L"Generate local `perf.data` file with partial profiling information (experimental only).", {} ); From dfd592fea85bb757aa3fc360305cc335f8f2f62e Mon Sep 17 00:00:00 2001 From: Nader Zouaoui Date: Fri, 29 Nov 2024 13:36:52 +0100 Subject: [PATCH 20/21] fix: rename count_command to stat_command --- wperf-test/wperf-test-arg_parser.cpp | 6 +++--- wperf/arg_parser.h | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/wperf-test/wperf-test-arg_parser.cpp b/wperf-test/wperf-test-arg_parser.cpp index 9144795..1dfcfcc 100644 --- a/wperf-test/wperf-test-arg_parser.cpp +++ b/wperf-test/wperf-test-arg_parser.cpp @@ -310,7 +310,7 @@ namespace wperftest Assert::IsFalse(parser.version_command.is_set()); Assert::IsFalse(parser.detect_command.is_set()); Assert::IsFalse(parser.sample_command.is_set()); - Assert::IsTrue(parser.count_command.is_set()); + Assert::IsTrue(parser.stat_command.is_set()); Assert::IsFalse(parser.man_command.is_set()); // Check all _arg flags setup @@ -359,7 +359,7 @@ namespace wperftest Assert::IsFalse(parser.version_command.is_set()); Assert::IsFalse(parser.detect_command.is_set()); Assert::IsFalse(parser.sample_command.is_set()); - Assert::IsFalse(parser.count_command.is_set()); + Assert::IsFalse(parser.stat_command.is_set()); Assert::IsFalse(parser.man_command.is_set()); // Check all _arg flags setup @@ -417,7 +417,7 @@ namespace wperftest Assert::IsFalse(parser.version_command.is_set()); Assert::IsFalse(parser.detect_command.is_set()); Assert::IsFalse(parser.sample_command.is_set()); - Assert::IsFalse(parser.count_command.is_set()); + Assert::IsFalse(parser.stat_command.is_set()); Assert::IsFalse(parser.man_command.is_set()); // Check all _opt flags setup diff --git a/wperf/arg_parser.h b/wperf/arg_parser.h index a1a36f9..4363667 100644 --- a/wperf/arg_parser.h +++ b/wperf/arg_parser.h @@ -162,7 +162,7 @@ namespace ArgParser { #endif } ); - arg_parser_arg_command count_command = arg_parser_arg_command::arg_parser_arg_command( + arg_parser_arg_command stat_command = arg_parser_arg_command::arg_parser_arg_command( L"stat", { L"" }, L"Counting mode, for obtaining aggregate counts of occurrences of special events.", @@ -367,7 +367,7 @@ namespace ArgParser { arg_parser_arg_pos metrics_arg = arg_parser_arg_pos::arg_parser_arg_pos( L"-m", {}, - L"Specify comma separated list of metrics to count.\n\nNote: see list of available metric names using `list` command.", + L"Specify comma separated list of metrics to count.\nNote: see list of available metric names using `list` command.", {} ); arg_parser_arg_pos events_arg = arg_parser_arg_pos::arg_parser_arg_pos( @@ -385,7 +385,7 @@ namespace ArgParser { &help_command, &version_command, &sample_command, - &count_command, + &stat_command, &record_command, &list_command, &test_command, From 60487f28988542d07426dc3f793e3f6dd071f18d Mon Sep 17 00:00:00 2001 From: Nader Zouaoui Date: Fri, 29 Nov 2024 14:11:17 +0100 Subject: [PATCH 21/21] fix: refine help output --- .../wperf-test-arg_parser_arg-utils.cpp | 6 ++--- wperf/arg_parser.cpp | 6 ++--- wperf/arg_parser.h | 22 +++++++++---------- wperf/arg_parser_arg.cpp | 3 --- wperf/main.cpp | 2 -- 5 files changed, 17 insertions(+), 22 deletions(-) diff --git a/wperf-test/wperf-test-arg_parser_arg-utils.cpp b/wperf-test/wperf-test-arg_parser_arg-utils.cpp index 26790c0..54bcf9d 100644 --- a/wperf-test/wperf-test-arg_parser_arg-utils.cpp +++ b/wperf-test/wperf-test-arg_parser_arg-utils.cpp @@ -69,21 +69,21 @@ namespace wperftest { std::wstring input = L"Line one.\nLine two is a bit longer.\nShort."; size_t max_width = 15; - std::wstring expected = L"Line one.\n\nLine two is a\nbit longer.\n\nShort."; + std::wstring expected = L"Line one.\nLine two is a\nbit longer.\nShort."; Assert::AreEqual(expected, arg_parser_format_string_to_length(input, max_width)); } TEST_METHOD(TestTrailingNewlineRemoval) { std::wstring input = L"Line one.\nLine two is a bit longer.\nShort.\n"; size_t max_width = 15; - std::wstring expected = L"Line one.\n\nLine two is a\nbit longer.\n\nShort."; + std::wstring expected = L"Line one.\nLine two is a\nbit longer.\nShort."; Assert::AreEqual(expected, arg_parser_format_string_to_length(input, max_width)); } TEST_METHOD(TestMultipleLinesAndMultipleTrailingReturnToLines) { std::wstring input = L"Line one.\nLine two is a bit longer.\nShort.\n\n\n\n\n\n\n"; size_t max_width = 15; - std::wstring expected = L"Line one.\n\nLine two is a\nbit longer.\n\nShort.\n\n\n\n\n\n"; + std::wstring expected = L"Line one.\nLine two is a\nbit longer.\nShort.\n\n\n\n\n\n"; Assert::AreEqual(expected, arg_parser_format_string_to_length(input, max_width)); } TEST_METHOD(MultipleRetrunToLines) diff --git a/wperf/arg_parser.cpp b/wperf/arg_parser.cpp index 27910d0..dd7eb3f 100644 --- a/wperf/arg_parser.cpp +++ b/wperf/arg_parser.cpp @@ -116,13 +116,13 @@ namespace ArgParser { m_out.GetOutputStream() << L"OPTIONS:\n\n"; for (auto& flag : m_flags_list) { - m_out.GetOutputStream() << L" " << flag->get_help() << L"\n"; + m_out.GetOutputStream() << flag->get_help() << L"\n\n"; } m_out.GetOutputStream() << L"EXAMPLES:\n\n"; for (auto& command : m_commands_list) { if (command->get_examples().empty()) continue; - m_out.GetOutputStream() << L" " << command->get_examples() << L"\n"; + m_out.GetOutputStream() << command->get_examples() << L"\n\n"; } } @@ -168,7 +168,7 @@ namespace ArgParser { { std::wstring example_output; for (auto& example : m_examples) { - example_output += example + L"\n"; + example_output += example + L"\n\n"; } return arg_parser_add_wstring_behind_multiline_text(arg_parser_format_string_to_length(example_output), L"\t"); } diff --git a/wperf/arg_parser.h b/wperf/arg_parser.h index 4363667..407aa9e 100644 --- a/wperf/arg_parser.h +++ b/wperf/arg_parser.h @@ -104,7 +104,7 @@ namespace ArgParser { L"wperf list [-v] [--json] [--force-lock]", COMMAND_CLASS::LIST, { - L"> wperf list -v List all events and metrics available on your host with extended information." + L"> wperf list -v \nList all events and metrics available on your host with extended information." } ); arg_parser_arg_command test_command = arg_parser_arg_command::arg_parser_arg_command( @@ -142,23 +142,23 @@ namespace ArgParser { arg_parser_arg_command sample_command = arg_parser_arg_command::arg_parser_arg_command( L"sample", { L"" }, - L"Sampling mode, for determining the frequencies of event occurrences produced by program locations at the function, basic block, and /or instruction levels.", + L"Sampling mode, for determining the frequencies of event occurrences produced by program locations at the function, basic block, and/or instruction levels.", L"wperf sample [-e] [--timeout] [-c] [-C] [-E] [-q] [--json] [--output] [--config] [--image_name] [--pe_file] [--pdb_file] [--sample-display-long] [--force-lock] [--sample-display-row] [--symbol] [--record_spawn_delay] [--annotate] [--disassemble]", COMMAND_CLASS::SAMPLE, { - L"> wperf sample -e ld_spec:100000 --pe_file python_d.exe -c 1 Sample event `ld_spec` with frequency `100000` already running process `python_d.exe` on core #1. Press Ctrl + C to stop sampling and see the results.", + L"> wperf sample -e ld_spec:100000 --pe_file python_d.exe -c 1 \nSample event `ld_spec` with frequency `100000` already running process `python_d.exe` on core #1. Press Ctrl + C to stop sampling and see the results.", } ); arg_parser_arg_command record_command = arg_parser_arg_command::arg_parser_arg_command( L"record", { L"" }, - L"Same as sample but also automatically spawns the process and pins it to the core specified by `-c`. Process name is defined by COMMAND.User can pass verbatim arguments to the process with[ARGS].", + L"Same as sample but also automatically spawns the process and pins it to the core specified by `-c`. Process name is defined by COMMAND. User can pass verbatim arguments to the process with[ARGS].", L"wperf record [-e] [--timeout] [-c] [-C] [-E] [-q] [--json] [--output] [--config] [--image_name] [--pe_file] [--pdb_file] [--sample-display-long] [--force-lock] [--sample-display-row] [--symbol] [--record_spawn_delay] [--annotate] [--disassemble] --COMMAND[ARGS]", COMMAND_CLASS::RECORD, { - L"> wperf record -e ld_spec:100000 -c 1 --timeout 30 -- python_d.exe -c 10**10**100 Launch `python_d.exe - c 10 * *10 * *100` process and start sampling event `ld_spec` with frequency `100000` on core #1 for 30 seconds. Hint: add `--annotate` or `--disassemble` to `wperf record` command line parameters to increase sampling \"resolution\"." + L"> wperf record -e ld_spec:100000 -c 1 --timeout 30 -- python_d.exe -c 10**10**100 \nLaunch `python_d.exe - c 10 * *10 * *100` process and start sampling event `ld_spec` with frequency `100000` on core #1 for 30 seconds. \nHint: add `--annotate` or `--disassemble` to `wperf record` command line parameters to increase sampling \"resolution\"." #ifdef ENABLE_SPE - ,L"> wperf record -e arm_spe_0/ld=1/ -c 8 --cpython\\PCbuild\\arm64\\python_d.exe -c 10**10**100 Launch `python_d.exe -c 10**10**100` process on core no. 8 and start SPE sampling, enable collection of load sampled operations, including atomic operations that return a value to a register. Hint: add `--annotate` or `--disassemble` to `wperf record` command." + ,L"> wperf record -e arm_spe_0/ld=1/ -c 8 -- python_d.exe -c 10**10**100 \nLaunch `python_d.exe -c 10**10**100` process on core no. 8 and start SPE sampling, enable collection of load sampled operations, including atomic operations that return a value to a register. Hint: add `--annotate` or `--disassemble` to `wperf record` command." #endif } ); @@ -166,12 +166,12 @@ namespace ArgParser { L"stat", { L"" }, L"Counting mode, for obtaining aggregate counts of occurrences of special events.", - L"wperf stat [-e] [-m] [-t] [-i] [-n] [-c] [-C] [-E] [-k] [--dmc] [-q] [--json] [--output][--config] [--force-lock] --COMMAND[ARGS]", + L"wperf stat [-e] [-m] [-t] [-i] [-n] [-c] [-C] [-E] [-k] [--dmc] [-q] [--json] [--output][--config] [--force-lock] --COMMAND [ARGS]", COMMAND_CLASS::STAT, { - L"> wperf stat -e inst_spec,vfp_spec,ase_spec,ld_spec -c 0 --timeout 3 Count events `inst_spec`, `vfp_spec`, `ase_spec` and `ld_spec` on core #0 for 3 seconds.", - L"> wperf stat -m imix -e l1i_cache -c 7 --timeout 10.5 Count metric `imix` (metric events will be grouped) and additional event `l1i_cache` on core #7 for 10.5 seconds.", - L"> wperf stat -m imix -c 1 -t -i 2 -n 3 --timeout 5 Count in timeline mode(output counting to CSV file) metric `imix` 3 times on core #1 with 2 second intervals(delays between counts).Each count will last 5 seconds." + L"> wperf stat -e inst_spec,vfp_spec,ase_spec,ld_spec -c 0 --timeout 3 \nCount events `inst_spec`, `vfp_spec`, `ase_spec` and `ld_spec` on core #0 for 3 seconds.", + L"> wperf stat -m imix -e l1i_cache -c 7 --timeout 10.5 \nCount metric `imix` (metric events will be grouped) and additional event `l1i_cache` on core #7 for 10.5 seconds.", + L"> wperf stat -m imix -c 1 -t -i 2 -n 3 --timeout 5 \nCount in timeline mode(output counting to CSV file) metric `imix` 3 times on core #1 with 2 second intervals(delays between counts). Each count will last 5 seconds." } ); arg_parser_arg_command man_command = arg_parser_arg_command::arg_parser_arg_command( @@ -373,7 +373,7 @@ namespace ArgParser { arg_parser_arg_pos events_arg = arg_parser_arg_pos::arg_parser_arg_pos( L"-e", {}, - L"Specify comma separated list of event names (or raw events) to count, for example `ld_spec,vfp_spec,r10`. Use curly braces to group events. Specify comma separated list of event names with sampling frequency to sample, for example `ld_spec:100000`. Raw events: specify raw evens with `r` where `` is a 16-bit hexadecimal event index value without leading `0x`. For example `r10` is event with index `0x10`. Note: see list of available event names using `list` command.", + L"Specify comma separated list of event names (or raw events) to count, for example `ld_spec,vfp_spec,r10`. Use curly braces to group events. \nSpecify comma separated list of event names with sampling frequency to sample, for example `ld_spec:100000`. \nRaw events: specify raw evens with `r` where `` is a 16-bit hexadecimal event index value without leading `0x`. For example `r10` is event with index `0x10`. \nNote: see list of available event names using `list` command.", {} ); #pragma endregion diff --git a/wperf/arg_parser_arg.cpp b/wperf/arg_parser_arg.cpp index 8754e51..929cbd0 100644 --- a/wperf/arg_parser_arg.cpp +++ b/wperf/arg_parser_arg.cpp @@ -182,9 +182,6 @@ namespace ArgParserArg { formatted_str += L"\n"; continue; } - if (!formatted_str.empty()) { - formatted_str += L"\n"; - } std::wstring current_line; std::wistringstream word_stream(line); std::wstring word; diff --git a/wperf/main.cpp b/wperf/main.cpp index c63fd2d..8bd1b81 100644 --- a/wperf/main.cpp +++ b/wperf/main.cpp @@ -1328,8 +1328,6 @@ wmain( #if defined(ENABLE_ETW_TRACING_APP) EventUnregisterWindowsPerf_App(); #endif - std::wstring hellp; - std::wcin >> hellp; if(spawned_process) { TerminateProcess(pi.hProcess, 0);