Merge pull request #5 from peoplemiau1/master

refactor: optimize parallel build and fix architectural issues
This commit is contained in:
2026-05-14 21:35:36 +08:00
committed by GitHub
5 changed files with 59 additions and 151 deletions

View File

@@ -153,6 +153,49 @@ pub fn has_glob_magic(value: &str) -> bool {
value.chars().any(|c| matches!(c, '*' | '?' | '[')) value.chars().any(|c| matches!(c, '*' | '?' | '['))
} }
pub fn parallel_build<F>(total_tasks: usize, task_fn: F) -> Result<(), String>
where
F: Fn(usize) -> Result<(), String> + Sync + Send,
{
let num_threads = std::thread::available_parallelism()
.map(|n| n.get())
.unwrap_or(1);
let counter = std::sync::atomic::AtomicUsize::new(0);
let err_msg = std::sync::Mutex::new(None);
std::thread::scope(|s| {
for _ in 0..num_threads {
s.spawn(|| {
loop {
if err_msg.lock().unwrap().is_some() {
break;
}
let i = counter.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
if i >= total_tasks {
break;
}
if let Err(e) = task_fn(i) {
let mut err = err_msg.lock().unwrap();
if err.is_none() {
*err = Some(e);
}
break;
}
}
});
}
});
if let Some(err) = err_msg.into_inner().unwrap() {
return Err(err);
}
Ok(())
}
pub fn normalize_source_path(path: &Path) -> String { pub fn normalize_source_path(path: &Path) -> String {
if !path.is_absolute() { if !path.is_absolute() {
return path.to_string_lossy().to_string(); return path.to_string_lossy().to_string();

View File

@@ -112,44 +112,9 @@ fn build_objects(
.map(|s| common::object_path(obj_dir, s, obj_ext)) .map(|s| common::object_path(obj_dir, s, obj_ext))
.collect(); .collect();
let num_threads = std::thread::available_parallelism() common::parallel_build(sources.len(), |i| {
.map(|n| n.get()) build_object(assembler, &sources[i], &objects[i], ctx)
.unwrap_or(1); })?;
let counter = std::sync::atomic::AtomicUsize::new(0);
let err_msg = std::sync::Mutex::new(None);
std::thread::scope(|s| {
for _ in 0..num_threads {
s.spawn(|| {
loop {
if err_msg.lock().unwrap().is_some() {
break;
}
let i = counter.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
if i >= sources.len() {
break;
}
let source = &sources[i];
let obj_path = &objects[i];
if let Err(e) = build_object(assembler, source, obj_path, ctx) {
let mut err = err_msg.lock().unwrap();
if err.is_none() {
*err = Some(e);
}
break;
}
}
});
}
});
if let Some(err) = err_msg.into_inner().unwrap() {
return Err(err);
}
Ok(objects) Ok(objects)
} }

View File

@@ -185,6 +185,8 @@ fn default_flags(profile: &str) -> &'static [&'static str] {
} }
} }
static OUTPUT_MUTEX: std::sync::Mutex<()> = std::sync::Mutex::new(());
fn build_objects( fn build_objects(
compiler: &str, compiler: &str,
sources: &[String], sources: &[String],
@@ -197,44 +199,9 @@ fn build_objects(
.map(|s| common::object_path(obj_dir, s, obj_ext)) .map(|s| common::object_path(obj_dir, s, obj_ext))
.collect(); .collect();
let num_threads = std::thread::available_parallelism() common::parallel_build(sources.len(), |i| {
.map(|n| n.get()) build_object(compiler, &sources[i], &objects[i], ctx)
.unwrap_or(1); })?;
let counter = std::sync::atomic::AtomicUsize::new(0);
let err_msg = std::sync::Mutex::new(None);
std::thread::scope(|s| {
for _ in 0..num_threads {
s.spawn(|| {
loop {
if err_msg.lock().unwrap().is_some() {
break;
}
let i = counter.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
if i >= sources.len() {
break;
}
let source = &sources[i];
let obj_path = &objects[i];
if let Err(e) = build_object(compiler, source, obj_path, ctx) {
let mut err = err_msg.lock().unwrap();
if err.is_none() {
*err = Some(e);
}
break;
}
}
});
}
});
if let Some(err) = err_msg.into_inner().unwrap() {
return Err(err);
}
Ok(objects) Ok(objects)
} }
@@ -315,6 +282,8 @@ fn build_object(
} }
} }
let _lock = OUTPUT_MUTEX.lock().unwrap();
if !output.status.success() { if !output.status.success() {
eprint!("{}", clean_stdout); eprint!("{}", clean_stdout);
eprint!("{}", stderr); eprint!("{}", stderr);

View File

@@ -112,45 +112,11 @@ fn build_objects(
.map(|s| common::object_path(obj_dir, s, obj_ext)) .map(|s| common::object_path(obj_dir, s, obj_ext))
.collect(); .collect();
let num_threads = std::thread::available_parallelism()
.map(|n| n.get())
.unwrap_or(1);
let counter = std::sync::atomic::AtomicUsize::new(0);
let err_msg = std::sync::Mutex::new(None);
let format = nasm_format(ctx.platform); let format = nasm_format(ctx.platform);
std::thread::scope(|s| { common::parallel_build(sources.len(), |i| {
for _ in 0..num_threads { build_object(assembler, &sources[i], &objects[i], format, ctx)
s.spawn(|| { })?;
loop {
if err_msg.lock().unwrap().is_some() {
break;
}
let i = counter.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
if i >= sources.len() {
break;
}
let source = &sources[i];
let obj_path = &objects[i];
if let Err(e) = build_object(assembler, source, obj_path, format, ctx) {
let mut err = err_msg.lock().unwrap();
if err.is_none() {
*err = Some(e);
}
break;
}
}
});
}
});
if let Some(err) = err_msg.into_inner().unwrap() {
return Err(err);
}
Ok(objects) Ok(objects)
} }

View File

@@ -137,44 +137,9 @@ fn build_objects(
.map(|s| common::object_path(obj_dir, s, obj_ext)) .map(|s| common::object_path(obj_dir, s, obj_ext))
.collect(); .collect();
let num_threads = std::thread::available_parallelism() common::parallel_build(sources.len(), |i| {
.map(|n| n.get()) build_object(compiler, &sources[i], &objects[i], ctx)
.unwrap_or(1); })?;
let counter = std::sync::atomic::AtomicUsize::new(0);
let err_msg = std::sync::Mutex::new(None);
std::thread::scope(|s| {
for _ in 0..num_threads {
s.spawn(|| {
loop {
if err_msg.lock().unwrap().is_some() {
break;
}
let i = counter.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
if i >= sources.len() {
break;
}
let source = &sources[i];
let obj_path = &objects[i];
if let Err(e) = build_object(compiler, source, obj_path, ctx) {
let mut err = err_msg.lock().unwrap();
if err.is_none() {
*err = Some(e);
}
break;
}
}
});
}
});
if let Some(err) = err_msg.into_inner().unwrap() {
return Err(err);
}
Ok(objects) Ok(objects)
} }