-
Notifications
You must be signed in to change notification settings - Fork 327
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
Performance measurements: Add Global Performance Measurements #9186
Changes from all commits
9f35546
7a92fb0
19f0a98
fc73ecd
59eea9f
ac590b6
ecc69e4
6988d62
229033b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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) | ||
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? 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.
Show resolved
Hide resolved
|
||
item->total_iteration_count++; | ||
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 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)); | ||
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 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) |
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.