use std::time::Instant;
use zerolaunch_plugin_api::services::IconRequest;
use zerolaunch_plugin_api::{
CachedCandidateData, ExecutionTarget, ScoreDetail, ScoreDetailKind, ScoredCandidate,
SearchCandidate,
};
use zerolaunch_plugin_protocol::messages::{BoosterBoostParams, CalculateScoresParams};
fn make_candidate(i: u64) -> SearchCandidate {
SearchCandidate {
id: i,
name: format!("示例应用/文件名称{:04}.exe", i),
icon: IconRequest::Path(format!(
"C:\\Program Files\\ZeroLaunch\\apps\\item{}.exe",
i
)),
target: ExecutionTarget::Path(format!(
"C:\\Program Files\\ZeroLaunch\\apps\\item{}.exe",
i
)),
keywords: vec!["keyword".into(), format!("kw{}", i % 100)],
bias: 0.5,
trigger_keywords: Vec::new(),
}
}
fn make_scored(i: u64) -> ScoredCandidate {
ScoredCandidate {
candidate_id: i,
score: 3.5,
detailed_score: vec![
ScoreDetail {
score: 2.0,
weight: 1.0,
description: "名称相似度".into(),
kind: ScoreDetailKind::Add,
},
ScoreDetail {
score: 1.5,
weight: 1.0,
description: "关键词命中".into(),
kind: ScoreDetailKind::Add,
},
],
}
}
fn fmt_us(d: std::time::Duration) -> String {
format!("{:.0}µs", d.as_secs_f64() * 1e6)
}
fn main() {
tracing_subscriber::fmt()
.with_max_level(tracing::Level::INFO)
.with_writer(std::io::stdout)
.init();
for n in [500usize, 2000, 10000] {
let candidates: Vec<SearchCandidate> = (1..=n as u64).map(make_candidate).collect();
let mut cache = CachedCandidateData::new();
for c in candidates {
cache.add_candidate(c);
}
let t = Instant::now();
let params = CalculateScoresParams {
component_id: "com.example.engine".into(),
candidates: cache.to_data(),
query: "示例查询词".into(),
};
let to_data = t.elapsed();
let t = Instant::now();
let payload = serde_json::to_vec(¶ms).unwrap();
let req_ser = t.elapsed();
let t = Instant::now();
let back: CalculateScoresParams = serde_json::from_slice(&payload).unwrap();
let req_de = t.elapsed();
let t = Instant::now();
let plugin_cache = CachedCandidateData::from_data(back.candidates);
let from_data = t.elapsed();
assert_eq!(plugin_cache.get_candidates().len(), n);
let scored: Vec<ScoredCandidate> = (1..=n as u64).map(make_scored).collect();
let t = Instant::now();
let resp = serde_json::to_vec(&scored).unwrap();
let resp_ser = t.elapsed();
let t = Instant::now();
let boost_params = BoosterBoostParams {
component_id: "com.example.booster".into(),
candidates: cache.to_data(),
scored: scored.clone(),
query: "示例查询词".into(),
};
let boost_payload = serde_json::to_vec(&boost_params).unwrap();
let boost_ser = t.elapsed();
tracing::info!(
n = n,
req_bytes = payload.len(),
resp_bytes = resp.len(),
boost_bytes = boost_payload.len(),
to_data_us = format_args!("{}", fmt_us(to_data)),
req_ser_us = format_args!("{}", fmt_us(req_ser)),
req_de_us = format_args!("{}", fmt_us(req_de)),
from_data_us = format_args!("{}", fmt_us(from_data)),
resp_ser_us = format_args!("{}", fmt_us(resp_ser)),
boost_ser_us = format_args!("{}", fmt_us(boost_ser)),
"payload perf"
);
}
}