Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 367
Performance measurements: Add Global Performance Measurements#9186
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
9f355467a92fb019f0a98fc73ecd59eea9fac590b6ecc69e46988d62229033bFile filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -22,7 +22,9 @@ | ||
| #include <sof/audio/module_adapter/module/generic.h> | ||
| #include <sof/schedule/dp_schedule.h> | ||
| #include <sof/schedule/ll_schedule.h> | ||
| #include <sof/debug/telemetry/performance_monitor.h> | ||
| #include <sof/debug/telemetry/telemetry.h> | ||
| #include <sof/debug/telemetry/performance_monitor.h> | ||
| /* FIXME: | ||
| * Builds for some platforms like tgl fail because their defines related to memory windows are | ||
| * already defined somewhere else. Remove this ifdef after it's cleaned up | ||
| @@ -406,20 +408,23 @@ int set_perf_meas_state(const char *data) | ||
| #ifdef CONFIG_SOF_TELEMETRY | ||
| enum ipc4_perf_measurements_state_set state = *data; | ||
| struct telemetry_wnd_data *wnd_data = | ||
| (struct telemetry_wnd_data *)ADSP_DW->slots[SOF_DW_TELEMETRY_SLOT]; | ||
| struct system_tick_info *systick_info = | ||
| (struct system_tick_info *)wnd_data->system_tick_info; | ||
| switch (state) { | ||
| case IPC4_PERF_MEASUREMENTS_DISABLED: | ||
| disable_performance_counters(); | ||
| perf_meas_set_state(IPC4_PERF_MEASUREMENTS_DISABLED); | ||
| break; | ||
| case IPC4_PERF_MEASUREMENTS_STOPPED: | ||
| for (int i = 0; i < CONFIG_MAX_CORE_COUNT; i++) | ||
| systick_info[i].peak_utilization = 0; | ||
| enable_performance_counters(); | ||
| reset_performance_counters(); | ||
| perf_meas_set_state(IPC4_PERF_MEASUREMENTS_STOPPED); | ||
| break; | ||
| case IPC4_PERF_MEASUREMENTS_STARTED: | ||
| enable_performance_counters(); | ||
| perf_meas_set_state(IPC4_PERF_MEASUREMENTS_STARTED); | ||
| break; | ||
| case IPC4_PERF_MEASUREMENTS_PAUSED: | ||
| enable_performance_counters(); | ||
| perf_meas_set_state(IPC4_PERF_MEASUREMENTS_PAUSED); | ||
| break; | ||
| default: | ||
| return -EINVAL; | ||
| @@ -428,6 +433,42 @@ int set_perf_meas_state(const char *data) | ||
| return IPC4_SUCCESS; | ||
| } | ||
| static int extended_global_perf_data_get(uint32_t *data_off_size, char *data) | ||
| { | ||
| #ifdef CONFIG_SOF_TELEMETRY_PERFORMANCE_MEASUREMENTS | ||
| int ret; | ||
| struct extended_global_perf_data *perf_data = (struct extended_global_perf_data *)data; | ||
| ret = get_extended_performance_data(perf_data); | ||
| if (ret < 0) | ||
| return IPC4_ERROR_INVALID_PARAM; | ||
| *data_off_size = sizeof(*perf_data) | ||
| + perf_data->perf_item_count * sizeof(*perf_data->perf_items); | ||
| return IPC4_SUCCESS; | ||
tobonex marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| #else | ||
| return IPC4_UNAVAILABLE; | ||
| #endif | ||
| } | ||
| static int global_perf_data_get(uint32_t *data_off_size, char *data) | ||
| { | ||
| #ifdef CONFIG_SOF_TELEMETRY_PERFORMANCE_MEASUREMENTS | ||
| int ret; | ||
| struct global_perf_data *perf_data = (struct global_perf_data *)data; | ||
| ret = get_performance_data(perf_data); | ||
| if (ret < 0) | ||
| return IPC4_ERROR_INVALID_PARAM; | ||
| *data_off_size = sizeof(*perf_data) | ||
| + perf_data->perf_item_count * sizeof(*perf_data->perf_items); | ||
| return IPC4_SUCCESS; | ||
tobonex marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| #else | ||
| return IPC4_UNAVAILABLE; | ||
| #endif | ||
| } | ||
| static int basefw_get_large_config(struct comp_dev *dev, | ||
| uint32_t param_id, | ||
| bool first_block, | ||
| @@ -467,13 +508,16 @@ static int basefw_get_large_config(struct comp_dev *dev, | ||
| return basefw_modules_info_get(data_offset, data); | ||
| case IPC4_LIBRARIES_INFO_GET: | ||
| return basefw_libraries_info_get(data_offset, data); | ||
| case IPC4_EXTENDED_GLOBAL_PERF_DATA: | ||
| return extended_global_perf_data_get(data_offset, data); | ||
| case IPC4_GLOBAL_PERF_DATA: | ||
| return global_perf_data_get(data_offset, data); | ||
| /* TODO: add more support */ | ||
| case IPC4_DSP_RESOURCE_STATE: | ||
| case IPC4_NOTIFICATION_MASK: | ||
| case IPC4_PIPELINE_PROPS_GET: | ||
| case IPC4_GATEWAYS_INFO_GET: | ||
| case IPC4_PERF_MEASUREMENTS_STATE: | ||
| case IPC4_GLOBAL_PERF_DATA: | ||
| COMPILER_FALLTHROUGH; | ||
| default: | ||
| break; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -6,6 +6,7 @@ | ||
| #include <sof/audio/component_ext.h> | ||
| #include <sof/common.h> | ||
| #include <sof/debug/telemetry/performance_monitor.h> | ||
| #include <rtos/panic.h> | ||
| #include <rtos/interrupt.h> | ||
| #include <sof/ipc/msg.h> | ||
| @@ -495,8 +496,18 @@ int comp_copy(struct comp_dev *dev) | ||
| perf_cnt_init(&dev->pcd); | ||
| #endif | ||
| #ifdef CONFIG_SOF_TELEMETRY_PERFORMANCE_MEASUREMENTS | ||
| const uint32_t begin_stamp = (uint32_t)sof_cycle_get_64(); | ||
| #endif | ||
| ret = dev->drv->ops.copy(dev); | ||
| #ifdef CONFIG_SOF_TELEMETRY_PERFORMANCE_MEASUREMENTS | ||
| const uint32_t cycles_consumed = (uint32_t)sof_cycle_get_64() - begin_stamp; | ||
| comp_update_performance_data(dev, cycles_consumed); | ||
| #endif | ||
| #if CONFIG_PERFORMANCE_COUNTERS | ||
| perf_cnt_stamp(&dev->pcd, perf_trace_null, dev); | ||
| perf_cnt_average(&dev->pcd, comp_perf_avg_info, dev); | ||
| @@ -505,3 +516,97 @@ int comp_copy(struct comp_dev *dev) | ||
| return ret; | ||
| } | ||
| #ifdef CONFIG_SOF_TELEMETRY_PERFORMANCE_MEASUREMENTS | ||
| void comp_init_performance_data(struct comp_dev *dev) | ||
Collaborator There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. does this all new code really belong to component.c? ContributorAuthor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well... it doesn't need to be here, but those were the methods in "component" class in reference FW. | ||
| { | ||
| struct perf_data_item_comp *item = dev->perf_data.perf_data_item; | ||
| if (item) | ||
| perf_data_item_comp_init(item, dev->ipc_config.id, 0); | ||
| } | ||
| /* returns true if budget violation occurred */ | ||
| static bool update_peak_of_measured_cpc(struct comp_dev *dev, size_t measured_cpc) | ||
| { | ||
| if (measured_cpc <= dev->perf_data.peak_of_measured_cpc) | ||
| return false; | ||
| dev->perf_data.peak_of_measured_cpc = measured_cpc; | ||
| return measured_cpc > dev->cpc; | ||
| } | ||
| bool comp_update_performance_data(struct comp_dev *dev, uint32_t cycles_used) | ||
| { | ||
| struct perf_data_item_comp *item = dev->perf_data.perf_data_item; | ||
| if (perf_meas_get_state() == IPC4_PERF_MEASUREMENTS_STARTED) { | ||
| /* we divide by ibs so we need to check if its set */ | ||
| if (item && dev->ibs != 0) { | ||
tobonex marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| item->total_iteration_count++; | ||
Collaborator There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. how often does this run? If this runs every millisecond, then in a couple of days this will overflow and the division below will divide by zero ContributorAuthor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah it may as well be every ms. Doubt it will be used for a couple of days , but still I should add some check here, true. | ||
| if (item->total_iteration_count == 0) { | ||
| /* We can't allow count to overflow to 0. Overflow will also make | ||
| * some of the results incorrect. We don't want to crash in this | ||
| * case, so we just log it. We also reset cycles counter to make | ||
| * avg correct again. | ||
| */ | ||
| item->total_iteration_count = 1; | ||
| item->total_cycles_consumed = 0; | ||
| tr_err(&ipc_tr, | ||
| "overflow for module %#x, performance measurement incorrect", | ||
| dev_comp_id(dev)); | ||
Collaborator There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. but like this after such an overflow they'll stay incorrect? Can we reset ContributorAuthor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hm, we can either do that, or zero everything and set a flag to stop the measurement to further indicate that something went wrong. | ||
| } | ||
| item->total_cycles_consumed += cycles_used; | ||
| item->item.avg_kcps = item->total_cycles_consumed * dev->ll_chunk_size | ||
| / (dev->ibs * item->total_iteration_count); | ||
| item->item.peak_kcps = | ||
| MAX(item->item.peak_kcps, (cycles_used * dev->ll_chunk_size) | ||
| / dev->ibs); | ||
| } | ||
| } | ||
| return update_peak_of_measured_cpc(dev, cycles_used); | ||
| } | ||
| #endif | ||
| #if CONFIG_IPC_MAJOR_4 | ||
| static uint32_t get_sample_group_size_in_bytes(const struct ipc4_audio_format fmt) | ||
| { | ||
| return (fmt.depth >> 3) * fmt.channels_count; | ||
| } | ||
| static uint32_t get_one_ms_in_bytes(const struct ipc4_audio_format fmt) | ||
| { | ||
| /* TODO Reference Firmware also has systick multiplier and divider in this equation */ | ||
| return get_sample_group_size_in_bytes(fmt) * | ||
| SOF_DIV_ROUND_UP(fmt.sampling_frequency, 1000); | ||
| } | ||
| #endif | ||
| void comp_update_ibs_obs_cpc(struct comp_dev *dev) | ||
| { | ||
| #if CONFIG_IPC_MAJOR_4 | ||
| int ret; | ||
| struct ipc4_base_module_cfg dev_cfg; | ||
| ret = comp_get_attribute(dev, COMP_ATTR_BASE_CONFIG, &dev_cfg); | ||
| if (ret < 0) { | ||
| tr_err(&ipc_tr, "failed to get base config for module %#x", | ||
| dev_comp_id(dev)); | ||
| /* set neutral values */ | ||
| dev->ll_chunk_size = 0; | ||
| dev->cpc = 0; | ||
| dev->obs = 0; | ||
| dev->ibs = 0; | ||
| } | ||
| dev->ll_chunk_size = get_one_ms_in_bytes(dev_cfg.audio_fmt); | ||
| dev->obs = dev_cfg.obs; | ||
| dev->ibs = dev_cfg.ibs; | ||
| dev->cpc = dev_cfg.cpc; | ||
| #else | ||
| /* set neutral values */ | ||
| dev->ll_chunk_size = 0; | ||
| dev->cpc = 0; | ||
| dev->obs = 0; | ||
| dev->ibs = 0; | ||
| #endif | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,4 @@ | ||
| # SPDX-License-Identifier: BSD-3-Clause | ||
| add_local_sources_ifdef(CONFIG_SOF_TELEMETRY sof telemetry.c) | ||
| add_local_sources_ifdef(CONFIG_SOF_TELEMETRY_PERFORMANCE_MEASUREMENTS sof performance_monitor.c) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -9,3 +9,12 @@ config SOF_TELEMETRY | ||
| systick_info measurement which measures scheduler task performance and may | ||
| slightly affect overall performance. | ||
| config SOF_TELEMETRY_PERFORMANCE_MEASUREMENTS | ||
| bool "enable performance measurements" | ||
| default n | ||
| help | ||
| Enables performance measurements. Requires ADSP_MW interface. Each created component | ||
| can have its performance checked by measuring execution time of copy function. | ||
| Performance records are stored in the limited number of slots in Memory Window 3, | ||
| so only a certain number (PERFORMANCE_DATA_ENTRIES_COUNT) of components can be measured. | ||
kv2019i marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
with these changes performance measurements would be unconditionally enabled on MTL and LNL? Is this desirable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, the performance measurement itself is enabled by IPC, so there's little to no overhead. But now that you mention it, disabling only CONFIG_SOF_TELEMETRY may break the build. It would be good if performance measurements could be enabled regardless of telemetry, I'll think about it.