Skip to content
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

Aperf: Add support for analytics #241

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open

Conversation

janaknat
Copy link
Contributor

@janaknat janaknat commented Dec 9, 2024

Add base support for Aperf Analytics. The stats are formed and created in the Aperf Rust backend. These values are then acted on by the rules in the Javascript frontend. Basic implementation for the keys in 'SystemInfo' and 'CPU Utilization' show how the rules can operate using the API provided.

Attached is a report comparing two runs. The output of the rules are shown in the landing page 'SystemInfo' tab.

build_metrics.tar.gz

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@janaknat janaknat requested a review from a team as a code owner December 9, 2024 19:09
src/lib.rs Outdated
@@ -180,6 +187,7 @@ impl PerformanceData {
let meta_data_handle = fs::OpenOptions::new()
.create(true)
.write(true)
.truncate(true)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given it's an error when any output directory already exists, in what scenario is this code encountering an existing file?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. Removed. It was a suggestion from a different version of clippy.

src/utils.rs Outdated
Comment on lines 16 to 17
pub p50: f64,
pub mean: f64,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mean and p50 are virtually interchangeable, I'd dump p50 and add p90.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay. Changing it to p90.


class Finding {
text: string;
status: string;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is the type 'string' instead of 'Status'?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah. Good catch. It's simpler to have the Status everywhere.

Comment on lines 56 to 57
function is_unique_map(values_map) {
return new Set([...values_map.values()]).size == 1;
}

function is_unique_array(values_array) {
return new Set(values_array).size == 1;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are odd definitions of 'unique'. It suggests that somewhere else you're using the wrong data type if you have to call into something to de-duplicate and check the size.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah. We're using arrays everywhere now. We were using arrays and maps. This is cleaner.

Comment on lines 7 to 29
rules: [
{
name: "User",
func: function (ruleOpts: RuleOpts) {
let system_util = get_data_key(ruleOpts.data_type, "System");
let findings = [];
let init_key = ruleOpts.runs[0];
let init_total_util: number = ruleOpts.per_run_data.get(init_key) + system_util.get(init_key);
for (const [key, value] of ruleOpts.per_run_data) {
if (key == init_key) {
continue;
}
let run_total_util: number = value + system_util.get(key);
let cpu_diff = Math.ceil(Math.abs(run_total_util - init_total_util));
findings.push(new Finding(
`Average CPU Utilization difference between ${init_key} and ${key} is ${cpu_diff}%.`,
cpu_diff > 10 ? Status.NotGood : Status.Good,
));
}
return findings;
},
good: "",
bad: "",
},
{
name: "idle",
func: function (ruleOpts: RuleOpts) {
let findings = [];
let init_key = ruleOpts.runs[0];
for (const [key, value] of ruleOpts.per_run_data) {
if (key == init_key) {
continue;
}
let idle_diff = Math.abs(ruleOpts.per_run_data.get(key) - ruleOpts.per_run_data.get(init_key));
if (idle_diff > 10) {
findings.push(new Finding(
`Difference in Average 'Idle time' between ${key} and ${init_key} is ${idle_diff}.`,
));
}
}
return findings;
},
good: "",
bad: "",
}
],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So rules don't start turning into copy-and-paste-fests of eachother, start refactoring this now so that things as simple as comparing aggregates across runs is not duplicated in multiple rules's 'func's.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm splitting it up into 3 types of rules.

  1. Runs == 1, Rules to point out things. Rules are implemented in single_run_rules[].
  2. Runs > 1,
    a. Set base run = Runs[0]. Iterate over the other runs and pass in base_run and other run to a function. Prevents needing repeat for loops for all rules. Rules are implemented in per_run_rules[].
    b. Provide all details to a different set of functions which needs all the details. Rules are implemented in all_run_rules[].

Comment on lines 17 to 27
func: function (ruleOpts: RuleOpts) {
return is_unique_map(ruleOpts.per_run_data);
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The cpu utilization rules are returning arrays of Findings, and this is returning boolean. Lock this function signature down or it will be a nightmare to maintain having to support a wide variety of return types.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay. I'm changing it so that only Finding should be returned.

This is in preparation for adding rules for SystemInfo and CPU
Utilization.
Form the metrics which will be used by the front-end for analytics work.
Generate it for SystemInfo and CPU Utilization.
@janaknat
Copy link
Contributor Author

Attached a newer version of the report. The SUT Config and Findings are now clubbed together in a single tab.

cmp.tar.gz

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants