mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-15 14:18:04 +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:
23
.github/workflows/comment-profiling-changes.yaml
vendored
23
.github/workflows/comment-profiling-changes.yaml
vendored
@@ -137,6 +137,7 @@ jobs:
|
||||
const sectionTitles = ['Compilation', 'Update', 'Run Once', 'Cached Execution'];
|
||||
|
||||
let hasSignificantChanges = false;
|
||||
let hasRegressions = false;
|
||||
let regressionDetails = [];
|
||||
|
||||
for (let i = 0; i < allOutputs.length; i++) {
|
||||
@@ -153,19 +154,25 @@ jobs:
|
||||
|
||||
if (isSignificantChange(diffPct, absoluteChange, outputName)) {
|
||||
hasSignificantChanges = true;
|
||||
regressionDetails.push({
|
||||
module_path: benchmark.module_path,
|
||||
id: benchmark.id,
|
||||
diffPct,
|
||||
absoluteChange,
|
||||
sectionTitle
|
||||
});
|
||||
|
||||
// Only an increase in instruction count is a regression; improvements must not fail CI.
|
||||
if (diffPct > 0) {
|
||||
hasRegressions = true;
|
||||
regressionDetails.push({
|
||||
module_path: benchmark.module_path,
|
||||
id: benchmark.id,
|
||||
diffPct,
|
||||
absoluteChange,
|
||||
sectionTitle
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
core.setOutput('has-significant-changes', hasSignificantChanges);
|
||||
core.setOutput('has-regressions', hasRegressions);
|
||||
core.setOutput('regression-details', JSON.stringify(regressionDetails));
|
||||
|
||||
- name: Comment PR
|
||||
@@ -319,7 +326,7 @@ jobs:
|
||||
}
|
||||
|
||||
- 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
|
||||
with:
|
||||
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> + '_ {
|
||||
vector.point_domain.ids().iter().filter_map(move |&point_id| {
|
||||
if vector.any_connected(point_id) {
|
||||
// Mark every point index touched by a segment endpoint in one `O(points + segments)` pass, avoiding a per-point `any_connected` scan
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -1223,7 +1223,15 @@ impl Vector {
|
||||
}
|
||||
|
||||
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 {
|
||||
|
||||
Reference in New Issue
Block a user