perf(lsp): collect counts and durations of all requests (#21540)

In addition to collecting details per-request metrics of the last 3000
request this commit adds aggregate metrics for all requests.
This commit is contained in:
Bartek Iwańczuk 2023-12-12 08:18:10 +01:00 committed by GitHub
parent 8ea35de158
commit 49a6daaa83
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 43 additions and 2 deletions

View file

@ -3807,14 +3807,30 @@ impl Inner {
.join("\n - ")
)
.unwrap();
contents
.push_str("\n## Performance\n\n|Name|Duration|Count|\n|---|---|---|\n");
.push_str("\n## Performance (last 3 000 entries)\n\n|Name|Count|Duration|\n|---|---|---|\n");
let mut averages = self.performance.averages_as_f64();
averages.sort_by(|a, b| a.0.cmp(&b.0));
for (name, count, average_duration) in averages {
writeln!(contents, "|{}|{}ms|{}|", name, average_duration, count)
writeln!(contents, "|{}|{}|{}ms|", name, count, average_duration)
.unwrap();
}
contents.push_str(
"\n## Performance (total)\n\n|Name|Count|Duration|\n|---|---|---|\n",
);
let mut measurements_by_type = self.performance.measurements_by_type();
measurements_by_type.sort_by(|a, b| a.0.cmp(&b.0));
for (name, total_count, total_duration) in measurements_by_type {
writeln!(
contents,
"|{}|{}|{:.3}ms|",
name, total_count, total_duration
)
.unwrap();
}
Some(contents)
} else {
let asset_or_doc = self.get_maybe_asset_or_document(&specifier);

View file

@ -79,6 +79,8 @@ impl From<PerformanceMark> for PerformanceMeasure {
#[derive(Debug)]
pub struct Performance {
counts: Mutex<HashMap<String, u32>>,
measurements_by_type:
Mutex<HashMap<String, (/* count */ u32, /* duration */ f64)>>,
max_size: usize,
measures: Mutex<VecDeque<PerformanceMeasure>>,
}
@ -87,6 +89,7 @@ impl Default for Performance {
fn default() -> Self {
Self {
counts: Default::default(),
measurements_by_type: Default::default(),
max_size: 3_000,
measures: Default::default(),
}
@ -137,6 +140,14 @@ impl Performance {
.collect()
}
pub fn measurements_by_type(&self) -> Vec<(String, u32, f64)> {
let measurements_by_type = self.measurements_by_type.lock();
measurements_by_type
.iter()
.map(|(name, (count, duration))| (name.to_string(), *count, *duration))
.collect::<Vec<_>>()
}
pub fn averages_as_f64(&self) -> Vec<(String, u32, f64)> {
let mut averages: HashMap<String, Vec<Duration>> = HashMap::new();
for measure in self.measures.lock().iter() {
@ -164,6 +175,13 @@ impl Performance {
let mut counts = self.counts.lock();
let count = counts.entry(name.to_string()).or_insert(0);
*count += 1;
{
let mut measurements_by_type = self.measurements_by_type.lock();
let measurement = measurements_by_type
.entry(name.to_string())
.or_insert((0, 0.0));
measurement.0 += 1;
}
let msg = if let Some(args) = maybe_args {
json!({
"type": "mark",
@ -218,6 +236,13 @@ impl Performance {
})
);
let duration = measure.duration;
{
let mut measurements_by_type = self.measurements_by_type.lock();
let measurement = measurements_by_type
.entry(measure.name.to_string())
.or_insert((0, 0.0));
measurement.1 += duration.as_micros() as f64 / 1000.0;
}
let mut measures = self.measures.lock();
measures.push_front(measure);
while measures.len() > self.max_size {