mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-27 23:58:12 +08:00
Make vector mesh branch detection and free-point click targets O(n) instead of O(n^2) (#4255)
* Make is_branching and free-point click targets O(n) instead of O(n^2) * usize -> u8 * Fix profiling CI treating performance improvements as regressions
This commit is contained in:
@@ -137,6 +137,7 @@ jobs:
|
|||||||
const sectionTitles = ['Compilation', 'Update', 'Run Once', 'Cached Execution'];
|
const sectionTitles = ['Compilation', 'Update', 'Run Once', 'Cached Execution'];
|
||||||
|
|
||||||
let hasSignificantChanges = false;
|
let hasSignificantChanges = false;
|
||||||
|
let hasRegressions = false;
|
||||||
let regressionDetails = [];
|
let regressionDetails = [];
|
||||||
|
|
||||||
for (let i = 0; i < allOutputs.length; i++) {
|
for (let i = 0; i < allOutputs.length; i++) {
|
||||||
@@ -153,19 +154,25 @@ jobs:
|
|||||||
|
|
||||||
if (isSignificantChange(diffPct, absoluteChange, outputName)) {
|
if (isSignificantChange(diffPct, absoluteChange, outputName)) {
|
||||||
hasSignificantChanges = true;
|
hasSignificantChanges = true;
|
||||||
regressionDetails.push({
|
|
||||||
module_path: benchmark.module_path,
|
// Only an increase in instruction count is a regression; improvements must not fail CI.
|
||||||
id: benchmark.id,
|
if (diffPct > 0) {
|
||||||
diffPct,
|
hasRegressions = true;
|
||||||
absoluteChange,
|
regressionDetails.push({
|
||||||
sectionTitle
|
module_path: benchmark.module_path,
|
||||||
});
|
id: benchmark.id,
|
||||||
|
diffPct,
|
||||||
|
absoluteChange,
|
||||||
|
sectionTitle
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
core.setOutput('has-significant-changes', hasSignificantChanges);
|
core.setOutput('has-significant-changes', hasSignificantChanges);
|
||||||
|
core.setOutput('has-regressions', hasRegressions);
|
||||||
core.setOutput('regression-details', JSON.stringify(regressionDetails));
|
core.setOutput('regression-details', JSON.stringify(regressionDetails));
|
||||||
|
|
||||||
- name: Comment PR
|
- name: Comment PR
|
||||||
@@ -319,7 +326,7 @@ jobs:
|
|||||||
}
|
}
|
||||||
|
|
||||||
- name: Fail on significant regressions
|
- name: Fail on significant regressions
|
||||||
if: steps.analyze.outputs.has-significant-changes == 'true'
|
if: steps.analyze.outputs.has-regressions == 'true'
|
||||||
uses: actions/github-script@v8
|
uses: actions/github-script@v8
|
||||||
with:
|
with:
|
||||||
script: |
|
script: |
|
||||||
|
|||||||
@@ -1714,8 +1714,14 @@ fn extend_targets_from_vector(targets: &mut Vec<ClickTarget>, vector_list: &List
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn extend_free_point_targets(vector: &Vector, transform: DAffine2) -> impl Iterator<Item = ClickTarget> + '_ {
|
fn extend_free_point_targets(vector: &Vector, transform: DAffine2) -> impl Iterator<Item = ClickTarget> + '_ {
|
||||||
vector.point_domain.ids().iter().filter_map(move |&point_id| {
|
// Mark every point index touched by a segment endpoint in one `O(points + segments)` pass, avoiding a per-point `any_connected` scan
|
||||||
if vector.any_connected(point_id) {
|
let mut connected = vec![false; vector.point_domain.len()];
|
||||||
|
for &point_index in vector.segment_domain.start_point().iter().chain(vector.segment_domain.end_point()) {
|
||||||
|
connected[point_index] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
vector.point_domain.ids().iter().enumerate().filter_map(move |(point_index, &point_id)| {
|
||||||
|
if connected[point_index] {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1223,7 +1223,15 @@ impl Vector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_branching(&self) -> bool {
|
pub fn is_branching(&self) -> bool {
|
||||||
(0..self.point_domain.len()).any(|point_index| self.segment_domain.connected_count(point_index) > 2)
|
// Tally segment endpoints per point in one `O(points + segments)` pass, short-circuiting once any point exceeds two
|
||||||
|
let mut connected_count = vec![0_u8; self.point_domain.len()];
|
||||||
|
for &point_index in self.segment_domain.start_point().iter().chain(self.segment_domain.end_point()) {
|
||||||
|
connected_count[point_index] += 1;
|
||||||
|
if connected_count[point_index] > 2 {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn has_regions(&self) -> bool {
|
pub fn has_regions(&self) -> bool {
|
||||||
|
|||||||
Reference in New Issue
Block a user