Файли
l0ng-ai 3b78d15d6d refactor(plugins): drop the Kubernetes plugin, samples become test fixtures
- Remove the Kubernetes official plugin.
- `hello` and `language-toy` move from `plugins/` to
  `crates/ide-plugin/tests/fixtures/`: they stay what the host's tests run
  against, but are no longer listed as plugins of the repository.
- A `jobs` fixture takes over what only Kubernetes exercised: a tree view
  filled by a pinned program, a terminal for the activated entry in the
  invoking window, string and number settings, locally and in remote
  projects.
- `plugins/` now holds only the official plugins; `build.sh`, CI and the
  debug plugin catalog follow.
2026-11-04 02:41:46 +08:00

150 рядки
5.8 KiB
Rust
Неформатований Постійне посилання Анотація Історія

Цей файл містить неоднозначні символи Юнікоду
Цей файл містить символи Юнікоду, які можна сплутати з іншими символами. Якщо ви вважаєте, що це зроблено навмисно, можете сміливо ігнорувати це попередження. Щоб показати їх, скористайтеся кнопкою Escape.
//! `cargo bench -p ide-host`: the plugin runtime budgets, checked by `pnpm perf:rust` against
//! `perf/budgets.json` › rust (`plugins/…`).
//!
//! - `load_50`: start-up load of 50 installed plugins (20 with code, 10
//! languages with a syntax provider, 10 icon themes, 10 declarations only),
//! from the contribution index; no Wasm is instantiated.
//! - `cold_activation`: an idle-reclaimed plugin's next command: activation
//! from the precompiled component plus the call.
//! - `syntax_highlights_2k_lines`: an edit-path call (Solidity highlighting).
use criterion::{Criterion, black_box, criterion_group, criterion_main};
use ide_core::LanguageId;
use ide_host::plugins::{Consent, PluginHost};
use ide_plugin::{Invocation, Limits};
use std::path::{Path, PathBuf};
use std::sync::Arc;
use std::time::Duration;
fn repo() -> PathBuf {
Path::new(env!("CARGO_MANIFEST_DIR")).join("../..").canonicalize().unwrap()
}
fn copy_dir(from: &Path, to: &Path) {
std::fs::create_dir_all(to).unwrap();
for e in std::fs::read_dir(from).unwrap().flatten() {
let name = e.file_name();
if matches!(name.to_str(), Some("target" | "src" | "Cargo.lock" | ".gitignore")) {
continue;
}
let dst = to.join(&name);
if e.path().is_dir() { copy_dir(&e.path(), &dst) } else { std::fs::copy(e.path(), &dst).map(|_| ()).unwrap() }
}
}
/// A copy of `src` installed under a new id (and new language / theme ids).
fn variant(work: &Path, src: &Path, n: usize, rename: &[(&str, String)]) -> PathBuf {
let dir = work.join(format!("pkg{n}"));
copy_dir(src, &dir);
for file in ["plugin.toml", "languages/solidity.toml"] {
let path = dir.join(file);
if let Ok(mut text) = std::fs::read_to_string(&path) {
for (from, to) in rename {
text = text.replace(from, to);
}
std::fs::write(&path, text).unwrap();
}
}
dir
}
fn sink() -> Arc<dyn ide_host::plugins::PluginEventSink> {
Arc::new(|_: Option<&str>, _| {})
}
fn install_50(plugins: &Path, work: &Path) {
let host = PluginHost::new(plugins.to_path_buf(), sink(), Limits::default()).unwrap();
host.load_all();
let root = repo();
let mut n = 0;
let mut install = |src: PathBuf, rename: Vec<(&str, String)>| {
let pkg = variant(work, &src, n, &rename);
n += 1;
host.install_from_dir(&pkg, &Consent::default()).unwrap();
};
for i in 0..20 {
install(
root.join("crates/ide-plugin/tests/fixtures/hello"),
vec![("id = \"hello\"", format!("id = \"bench.hello{i}\""))],
);
}
for i in 0..10 {
install(
root.join("plugins/official/solidity"),
vec![
("openidea.solidity", format!("bench.solidity{i}")),
("id = \"solidity\"", format!("id = \"solidity{i}\"")),
("extensions = [\"sol\"]", format!("extensions = [\"sol{i}\"]")),
("on-language:solidity", format!("on-language:solidity{i}")),
("id = \"forge-", format!("id = \"f{i}-")),
("id = \"hardhat-", format!("id = \"h{i}-")),
],
);
}
for i in 0..10 {
install(
root.join("plugins/official/material-icons"),
vec![
("openidea.material-icons", format!("bench.icons{i}")),
("id = \"material\"", format!("id = \"material{i}\"")),
],
);
}
for i in 0..10 {
let dir = work.join(format!("static{i}"));
std::fs::create_dir_all(&dir).unwrap();
std::fs::write(
dir.join("plugin.toml"),
format!(
"id = \"bench.static{i}\"\nname = \"Static {i}\"\nversion = \"1.0.0\"\nengines.openidea = \"^1.0\"\n\
[[contributes.commands]]\nid = \"a\"\ntitle = \"Static {i}: A\"\nwhen = \"editorLang == rust\"\n"
),
)
.unwrap();
host.install_from_dir(&dir, &Consent::default()).unwrap();
}
}
fn bench(c: &mut Criterion) {
let tmp = tempfile::tempdir().unwrap();
let plugins = tmp.path().join("plugins");
install_50(&plugins, &tmp.path().join("work"));
let mut g = c.benchmark_group("plugins");
g.sample_size(20);
g.bench_function("load_50", |b| {
b.iter(|| {
let host = PluginHost::new(plugins.clone(), sink(), Limits::default()).unwrap();
host.load_all();
assert_eq!(host.instances(), 0, "start-up instantiates no Wasm");
black_box(host.list(None).plugins.len())
})
});
let limits = Limits { idle_timeout: Some(Duration::ZERO), ..Limits::default() };
let host = Arc::new(PluginHost::new(plugins.clone(), sink(), limits).unwrap());
host.load_all();
host.warm_component_cache();
g.bench_function("cold_activation", |b| {
b.iter(|| {
host.tick();
// Fails for want of an editor, after activating and running.
let r = host.run_command("bench.hello0", "word-count", None, Invocation::default());
black_box(r.is_err())
})
});
let provider = host.syntax_provider();
let lang = LanguageId::new("solidity0");
let unit = "contract Token {\n uint256 public total;\n mapping(address => uint256) balances;\n event Sent(address to, uint256 v);\n function send(address to, uint256 v) public returns (bool) {\n // move funds\n balances[to] += v;\n emit Sent(to, v);\n return true;\n }\n}\n";
let text = unit.repeat(2000 / unit.lines().count());
assert!(provider.highlights(&lang, &text).is_some());
g.bench_function("syntax_highlights_2k_lines", |b| {
b.iter(|| black_box(provider.highlights(&lang, &text).map(|t| t.len())))
});
g.finish();
}
criterion_group!(benches, bench);
criterion_main!(benches);