|
| 1 | +use rayon::{ |
| 2 | + prelude::ParallelIterator, |
| 3 | + slice::{ParallelSlice, ParallelSliceMut}, |
| 4 | +}; |
| 5 | + |
1 | 6 | use crate::{
|
2 | 7 | asyncjob::{AsyncJob, RunParams},
|
3 | 8 | error::Result,
|
4 | 9 | sync::{self, CommitId, RepoPath, SharedCommitFilterFn},
|
5 | 10 | AsyncGitNotification, ProgressPercent,
|
6 | 11 | };
|
7 | 12 | use std::{
|
8 |
| - sync::{Arc, Mutex}, |
| 13 | + sync::{atomic::AtomicUsize, Arc, Mutex}, |
9 | 14 | time::{Duration, Instant},
|
10 | 15 | };
|
11 | 16 |
|
@@ -69,58 +74,80 @@ impl AsyncCommitFilterJob {
|
69 | 74 | commits: Vec<CommitId>,
|
70 | 75 | params: &RunParams<AsyncGitNotification, ProgressPercent>,
|
71 | 76 | ) -> JobState {
|
72 |
| - let response = sync::repo(repo_path) |
73 |
| - .map(|repo| self.filter_commits(&repo, commits, params)) |
74 |
| - .map(|(start, result)| CommitFilterResult { |
75 |
| - result, |
76 |
| - duration: start.elapsed(), |
77 |
| - }); |
78 |
| - |
79 |
| - JobState::Response(response) |
| 77 | + let (start, result) = |
| 78 | + self.filter_commits(repo_path, commits, params); |
| 79 | + |
| 80 | + //TODO: still need this to be a result? |
| 81 | + JobState::Response(Ok(CommitFilterResult { |
| 82 | + result, |
| 83 | + duration: start.elapsed(), |
| 84 | + })) |
80 | 85 | }
|
81 | 86 |
|
82 | 87 | fn filter_commits(
|
83 | 88 | &self,
|
84 |
| - repo: &git2::Repository, |
| 89 | + repo_path: &RepoPath, |
85 | 90 | commits: Vec<CommitId>,
|
86 | 91 | params: &RunParams<AsyncGitNotification, ProgressPercent>,
|
87 | 92 | ) -> (Instant, Vec<CommitId>) {
|
88 | 93 | let total_amount = commits.len();
|
89 | 94 | let start = Instant::now();
|
90 | 95 |
|
91 |
| - let mut progress = ProgressPercent::new(0, total_amount); |
92 |
| - |
93 |
| - let result = commits |
| 96 | + let idx = AtomicUsize::new(0); |
| 97 | + let mut result = commits |
94 | 98 | .into_iter()
|
95 | 99 | .enumerate()
|
96 |
| - .filter_map(|(idx, c)| { |
97 |
| - let new_progress = |
98 |
| - ProgressPercent::new(idx, total_amount); |
99 |
| - |
100 |
| - if new_progress != progress { |
101 |
| - Self::update_progress(params, new_progress); |
102 |
| - progress = new_progress; |
103 |
| - } |
104 |
| - |
105 |
| - (*self.filter)(repo, &c) |
106 |
| - .ok() |
107 |
| - .and_then(|res| res.then_some(c)) |
| 100 | + .collect::<Vec<(usize, CommitId)>>() |
| 101 | + .par_chunks(1000) |
| 102 | + .filter_map(|c| { |
| 103 | + //TODO: error log repo open errors |
| 104 | + sync::repo(repo_path).ok().map(|repo| { |
| 105 | + c.iter() |
| 106 | + .filter_map(|(e, c)| { |
| 107 | + let idx = idx.fetch_add( |
| 108 | + 1, |
| 109 | + std::sync::atomic::Ordering::Relaxed, |
| 110 | + ); |
| 111 | + |
| 112 | + Self::update_progress( |
| 113 | + params, |
| 114 | + ProgressPercent::new( |
| 115 | + idx, |
| 116 | + total_amount, |
| 117 | + ), |
| 118 | + ); |
| 119 | + |
| 120 | + (*self.filter)(&repo, c).ok().and_then( |
| 121 | + |res| res.then_some((*e, *c)), |
| 122 | + ) |
| 123 | + }) |
| 124 | + .collect::<Vec<_>>() |
| 125 | + }) |
108 | 126 | })
|
| 127 | + .flatten() |
109 | 128 | .collect::<Vec<_>>();
|
110 | 129 |
|
| 130 | + result.par_sort_by(|a, b| a.0.cmp(&b.0)); |
| 131 | + |
| 132 | + let result = result.into_iter().map(|c| c.1).collect(); |
| 133 | + |
111 | 134 | (start, result)
|
112 | 135 | }
|
113 | 136 |
|
114 | 137 | fn update_progress(
|
115 | 138 | params: &RunParams<AsyncGitNotification, ProgressPercent>,
|
116 | 139 | new_progress: ProgressPercent,
|
117 | 140 | ) {
|
118 |
| - if let Err(e) = params.set_progress(new_progress) { |
119 |
| - log::error!("progress error: {e}"); |
120 |
| - } else if let Err(e) = |
121 |
| - params.send(AsyncGitNotification::CommitFilter) |
122 |
| - { |
123 |
| - log::error!("send error: {e}"); |
| 141 | + match params.set_progress(new_progress) { |
| 142 | + Err(e) => log::error!("progress error: {e}"), |
| 143 | + Ok(result) if result => { |
| 144 | + if let Err(e) = |
| 145 | + params.send(AsyncGitNotification::CommitFilter) |
| 146 | + { |
| 147 | + log::error!("send error: {e}"); |
| 148 | + } |
| 149 | + } |
| 150 | + _ => (), |
124 | 151 | }
|
125 | 152 | }
|
126 | 153 | }
|
|
0 commit comments