in mozperftest_tools/mozperftest_tools/profile_enhancer.py [0:0]
def detect_changes(self, vismet_before_ns, vismet_after_ns, threshold=5):
"""Returns the changes (improvements, AND regressions) found.
We go through both lists and once we find a mismatch, we begin
marking either a regression, OR, an improvment and then store it
once we hit an equalization point.
DO NOT use approximations here because the visual completeness
can absolutely change in flash. This means that we begin counting
a regression, then stop when we hit a point that is unregressed
in the other.
Use the threshold to determine how large the distance in progress
must be to be classified as a change.
"""
changes = []
# Standardize the timestamps
vismet_before = []
vismet_after = []
for prog in vismet_before_ns:
new_prog = copy.deepcopy(prog)
new_prog["timestamp"] = prog["timestamp"] - vismet_before_ns[0]["timestamp"]
vismet_before.append(new_prog)
for prog in vismet_after_ns:
new_prog = copy.deepcopy(prog)
new_prog["timestamp"] = prog["timestamp"] - vismet_after_ns[0]["timestamp"]
vismet_after.append(new_prog)
start_ts = None
end_ts = None
curr_ind = 0
for i, prog in enumerate(vismet_before):
if prog["percent"] == vismet_after[curr_ind]["percent"]:
curr_ind += 1
elif (
prog["percent"] > vismet_after[curr_ind]["percent"] and
prog["timestamp"] <= vismet_after[curr_ind]["timestamp"]
):
# Create a regression
# From this point until we find an inflection in the progress
# we no longer care about the timestamp. This is because we already
# know we're slower in the vismet_after starting from now, and
# until the progress flips again. The same is true for an improvement.
start_ts = vismet_after[curr_ind]["timestamp"]
while (
prog["percent"] > vismet_after[curr_ind]["percent"] and
curr_ind + 1 < len(vismet_after)
):
curr_ind += 1
end_ts = vismet_after[curr_ind]["timestamp"]
changes.append({
"type": "regression",
"start": start_ts + vismet_after_ns[0]["timestamp"],
"end": end_ts + vismet_after_ns[0]["timestamp"],
})
elif (
prog["percent"] < vismet_after[curr_ind]["percent"] and
prog["timestamp"] >= vismet_after[curr_ind]["timestamp"]
):
# Create an improvement
start_ts = vismet_after[curr_ind]["timestamp"]
while (
prog["percent"] < vismet_after[curr_ind]["percent"] and
curr_ind + 1 < len(vismet_after)
):
curr_ind += 1
end_ts = vismet_after[curr_ind]["timestamp"]
changes.append({
"type": "improvement",
"start": start_ts + vismet_after_ns[0]["timestamp"],
"end": end_ts + vismet_after_ns[0]["timestamp"],
})
if curr_ind >= len(vismet_after):
# Finished searching
break
# Merge the changes we've found in case there's overlap,
# this could be resolved above but I prefer getting steps
# of regressions as an intermediate value for debugging
merged_changes = []
curr_change = None
for change in changes:
if curr_change is None:
curr_change = change
elif (
curr_change["type"] == change["type"] and
curr_change["end"] == change["start"]
):
curr_change["end"] = change["end"]
else:
merged_changes.append(curr_change)
curr_change = change
if curr_change:
merged_changes.append(curr_change)
return merged_changes