mirror of
https://github.com/openai/codex.git
synced 2026-11-13 14:46:14 +00:00
Parallelize environment skill loading (#29990)
## Why Avoid a request waterfall for loading lots of skills at once by hiding latency in concurrent tasks. ## What changed Poll the per-skill parse futures concurrently with an order-preserving stream capped at 64 in-flight loads. Results retain discovery order, and the existing filtering, warnings, and final catalog sorting are unchanged.
This commit is contained in:
1 parent
ab80d4d484
commit
5579792b3b
1 file changed
+26
-16
@@ -10,6 +10,7 @@ use codex_utils_path_uri::PathUri;
|
|||||||
use codex_utils_plugins::DISCOVERABLE_PLUGIN_MANIFEST_PATHS;
|
use codex_utils_plugins::DISCOVERABLE_PLUGIN_MANIFEST_PATHS;
|
||||||
use codex_utils_plugins::plugin_namespace_for_root_uri;
|
use codex_utils_plugins::plugin_namespace_for_root_uri;
|
||||||
use codex_utils_plugins::plugin_namespace_for_skill_uri;
|
use codex_utils_plugins::plugin_namespace_for_skill_uri;
|
||||||
|
use futures::StreamExt;
|
||||||
use futures::future::join_all;
|
use futures::future::join_all;
|
||||||
|
|
||||||
use crate::model::SkillDependencies;
|
use crate::model::SkillDependencies;
|
||||||
@@ -31,6 +32,7 @@ use super::sanitize_single_line;
|
|||||||
use super::validate_len;
|
use super::validate_len;
|
||||||
|
|
||||||
const MAX_SKILLS_ENTRIES_PER_ROOT: usize = 20_000;
|
const MAX_SKILLS_ENTRIES_PER_ROOT: usize = 20_000;
|
||||||
|
const MAX_CONCURRENT_SKILL_LOADS: usize = 64;
|
||||||
|
|
||||||
/// URI-native metadata for one skill owned by an execution environment.
|
/// URI-native metadata for one skill owned by an execution environment.
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
@@ -220,24 +222,32 @@ pub async fn load_environment_skills_from_root(
|
|||||||
.filter_map(|(plugin_root, namespace)| namespace.map(|namespace| (plugin_root, namespace)))
|
.filter_map(|(plugin_root, namespace)| namespace.map(|namespace| (plugin_root, namespace)))
|
||||||
.collect::<HashMap<_, _>>();
|
.collect::<HashMap<_, _>>();
|
||||||
|
|
||||||
for path in discovery.skill_files {
|
// Remote executors can multiplex these independent per-skill reads, so polling a bounded
|
||||||
let mut ancestor = path.parent();
|
// number together allows the I/O for each skill and its metadata to happen concurrently.
|
||||||
let plugin_namespace = loop {
|
let skill_results = futures::stream::iter(discovery.skill_files)
|
||||||
let Some(current) = ancestor else {
|
.map(|path| {
|
||||||
break None;
|
let mut ancestor = path.parent();
|
||||||
|
let plugin_namespace = loop {
|
||||||
|
let Some(current) = ancestor else {
|
||||||
|
break None;
|
||||||
|
};
|
||||||
|
if let Some(namespace) = plugin_namespaces.get(¤t) {
|
||||||
|
break Some(namespace.as_str());
|
||||||
|
}
|
||||||
|
ancestor = current.parent();
|
||||||
};
|
};
|
||||||
if let Some(namespace) = plugin_namespaces.get(¤t) {
|
async move {
|
||||||
break Some(namespace.as_str());
|
let result =
|
||||||
|
EnvironmentSkillMetadata::parse(file_system, &path, plugin_namespace).await;
|
||||||
|
(path, result)
|
||||||
}
|
}
|
||||||
ancestor = current.parent();
|
})
|
||||||
};
|
.buffered(MAX_CONCURRENT_SKILL_LOADS)
|
||||||
match EnvironmentSkillMetadata::parse(
|
.collect::<Vec<_>>()
|
||||||
file_system,
|
.await;
|
||||||
&path,
|
|
||||||
/*plugin_namespace*/ plugin_namespace,
|
for (path, result) in skill_results {
|
||||||
)
|
match result {
|
||||||
.await
|
|
||||||
{
|
|
||||||
Ok(skill) if skill.matches_product_restriction(restriction_product) => {
|
Ok(skill) if skill.matches_product_restriction(restriction_product) => {
|
||||||
outcome.skills.push(skill);
|
outcome.skills.push(skill);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user