187 lines
7.6 KiB
Rust
187 lines
7.6 KiB
Rust
//! 所有性能组共用正式生成器、锁定依赖和 release 构建参数。
|
|
|
|
use crate::auth_build;
|
|
mod collections;
|
|
pub(crate) use collections::run as collections;
|
|
use dever::compiler::{emit, project::Project};
|
|
use dever::process::{child::output::require_success, command};
|
|
use std::path::Path;
|
|
|
|
pub(crate) fn compare(
|
|
core: &Path,
|
|
fixture: &str,
|
|
name: &str,
|
|
reference: &str,
|
|
functions: &[(&str, &str)],
|
|
definitions: &[(&str, &str)],
|
|
) {
|
|
let path = core.join(format!("test/rust/fixtures/{fixture}"));
|
|
let path = if path.is_dir() {
|
|
path
|
|
} else {
|
|
path.with_extension("dever")
|
|
};
|
|
let project = Project::load(&path).unwrap();
|
|
let program = project.check().unwrap();
|
|
let mut comparison = auth_build::metadata(name, &program, reference);
|
|
if name == "decimal-extra" {
|
|
for (marker, path) in [
|
|
("DECIMAL_CODEC_SOURCE", "codec/numeric.rs"),
|
|
("DECIMAL_SCALAR_SOURCE", "scalar/decimal.rs"),
|
|
] {
|
|
comparison = comparison.replace(
|
|
&format!("\"{marker}\""),
|
|
&format!("{:?}", core.join("rust/src/runtime/database").join(path)),
|
|
);
|
|
}
|
|
}
|
|
let memory = std::env::args().any(|argument| argument == "--memory");
|
|
if memory {
|
|
assert!(
|
|
comparison.contains("fn compare_output<"),
|
|
"memory requires the shared sample harness"
|
|
);
|
|
comparison = comparison.replacen("fn compare_output<", "fn timed_compare_output<", 1);
|
|
comparison.push_str(include_str!("../memory.rs"));
|
|
}
|
|
let mut roots = Vec::new();
|
|
for (marker, name) in functions {
|
|
if let Some(index) = program
|
|
.commands
|
|
.iter()
|
|
.position(|command| command.name == *name)
|
|
{
|
|
comparison = comparison.replace(marker, &format!("command{index}"));
|
|
roots.push(program.commands[index].function);
|
|
continue;
|
|
}
|
|
let (package, name) = name
|
|
.rsplit_once('.')
|
|
.map_or((None, *name), |(package, name)| (Some(package), name));
|
|
let position = program
|
|
.functions
|
|
.iter()
|
|
.position(|function| {
|
|
function.signature.name == name
|
|
&& package.is_none_or(|package| {
|
|
program.packages[function.signature.source] == package
|
|
})
|
|
})
|
|
.unwrap();
|
|
comparison = comparison.replace(marker, &format!("function{position}"));
|
|
roots.push(position);
|
|
}
|
|
for (marker, name) in definitions {
|
|
let position = program
|
|
.definitions
|
|
.iter()
|
|
.position(|definition| definition.name == *name)
|
|
.unwrap();
|
|
comparison = comparison.replace(marker, &format!("Type{position}"));
|
|
}
|
|
let task_dependencies = if name == "rest-json" {
|
|
"chrono = { version = \"=0.4.45\", default-features = false, features = [\"std\"] }\n"
|
|
} else if name == "tasks" {
|
|
"tokio = { version = \"=1.53.1\", features = [\"rt-multi-thread\", \"sync\", \"time\", \"macros\"] }\ntokio-util = { version = \"=0.7.19\", features = [\"rt\"] }\nfutures-util = { version = \"=0.3.34\", default-features = false, features = [\"std\"] }\n"
|
|
} else if matches!(name, "websocket" | "websocket-protocol") {
|
|
"tokio = { version = \"=1.53.1\", features = [\"rt-multi-thread\", \"net\", \"sync\", \"time\", \"macros\"] }\ntokio-util = { version = \"=0.7.19\", features = [\"rt\"] }\nfutures-util = { version = \"=0.3.34\", default-features = false, features = [\"std\", \"sink\"] }\ntokio-tungstenite = { version = \"=0.30.0\", default-features = false, features = [\"handshake\"] }\n"
|
|
} else if name == "query" {
|
|
"axum = { version = \"=0.8.9\", default-features = false, features = [\"query\"] }\nserde = { version = \"=1.0.228\", features = [\"derive\"] }\nserde_urlencoded = \"=0.7.1\"\n"
|
|
} else if name == "transport" {
|
|
crate::transport::DEPENDENCIES
|
|
} else if matches!(name, "auth" | "auth-http") {
|
|
"tokio = { version = \"=1.53.1\", features = [\"sync\"] }\n"
|
|
} else if name == "extended-primitives" {
|
|
"sha2 = \"=0.10.9\"\nuuid = { version = \"=1.28.0\", default-features = false }\n"
|
|
} else if name == "decimal-extra" {
|
|
"serde = \"=1.0.228\"\nserde_json = \"=1.0.145\"\nbytes = \"=1.12.1\"\n"
|
|
} else if name == "api-wire" {
|
|
"serde_json = \"=1.0.145\"\nhyper = \"=1.11.1\"\n"
|
|
} else if matches!(name, "database" | "database-postgres" | "application") {
|
|
"serde_json = \"=1.0.145\"\n"
|
|
} else {
|
|
""
|
|
};
|
|
let name = if memory {
|
|
format!("{name}-memory")
|
|
} else {
|
|
name.to_owned()
|
|
};
|
|
let directory = core.join(format!("rust/target/performance/{name}"));
|
|
std::fs::create_dir_all(&directory).unwrap();
|
|
roots.extend(program.commands.iter().map(|command| command.function));
|
|
if matches!(
|
|
name.trim_end_matches("-memory"),
|
|
"auth" | "auth-http" | "jobs" | "api-wire" | "rest-wire" | "rest-json"
|
|
) {
|
|
roots.extend(program.entries());
|
|
}
|
|
let roots = roots.into_iter().collect::<std::collections::BTreeSet<_>>();
|
|
let functions = program.reachable(roots.iter().copied());
|
|
let mut source = emit::generate(&program, &project.sources, &roots);
|
|
source.push_str(&auth_build::application(
|
|
name.trim_end_matches("-memory"),
|
|
&program,
|
|
));
|
|
source.push_str(&comparison);
|
|
write(&directory.join("main.rs"), &source);
|
|
let mut features = dever::compiler::build::runtime_features(&program, &functions);
|
|
if name.trim_end_matches("-memory") == "query" {
|
|
features.push("api");
|
|
}
|
|
if matches!(
|
|
name.trim_end_matches("-memory"),
|
|
"database-postgres" | "decimal-extra"
|
|
) {
|
|
features.push("postgres");
|
|
}
|
|
let features = format!(", features = {features:?}");
|
|
write(
|
|
&directory.join("Cargo.toml"),
|
|
&format!(
|
|
"[package]\nname = \"dever-comparison-{name}\"\nversion = \"0.0.1\"\nedition = \"2024\"\n[workspace]\n[[bin]]\nname = \"dever-comparison-{name}\"\npath = \"main.rs\"\n[dependencies]\ndever-runtime = {{ path = {:?}{features} }}\nindexmap = \"=2.14.0\"\ndec = \"=0.4.11\"\n{task_dependencies}[profile.release]\nlto = \"fat\"\ncodegen-units = 1\noverflow-checks = true\n",
|
|
core.join("rust/src/runtime").to_string_lossy()
|
|
),
|
|
);
|
|
// 基准清单随候选运行库变化;只刷新这个生成项目的离线依赖锁。
|
|
let arguments = ["+1.95.0", "generate-lockfile", "--offline"];
|
|
let child = command::start("cargo".as_ref(), &arguments, &directory, true).unwrap();
|
|
require_success(child.output().unwrap()).unwrap();
|
|
let result = command::start(
|
|
"cargo".as_ref(),
|
|
&[
|
|
"+1.95.0",
|
|
"build",
|
|
"--offline",
|
|
"--locked",
|
|
"--release",
|
|
"--target-dir",
|
|
"../../programs",
|
|
],
|
|
&directory,
|
|
true,
|
|
)
|
|
.unwrap()
|
|
.output()
|
|
.unwrap();
|
|
require_success(result).unwrap();
|
|
let binary = core.join(format!(
|
|
"rust/target/programs/release/dever-comparison-{name}"
|
|
));
|
|
if memory || std::env::args().any(|argument| argument == "--build-only") {
|
|
println!("{}", binary.display());
|
|
return;
|
|
}
|
|
let status = command::start(binary.as_os_str(), &[] as &[&str], &directory, false)
|
|
.unwrap()
|
|
.wait()
|
|
.unwrap();
|
|
assert!(status.success());
|
|
}
|
|
|
|
fn write(path: &Path, contents: &str) {
|
|
if std::fs::read_to_string(path).ok().as_deref() != Some(contents) {
|
|
std::fs::write(path, contents).unwrap();
|
|
}
|
|
}
|