0
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-03-03 17:34:47 -05:00

perf(core): micro-optimize OpsTracker (#13868)

This commit is contained in:
Aaron O'Mullan 2022-03-08 09:28:20 +01:00 committed by GitHub
parent 566a1493f5
commit 303d691a16
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 28 additions and 16 deletions

View file

@ -16,6 +16,7 @@ use indexmap::IndexMap;
use serde::de::DeserializeOwned; use serde::de::DeserializeOwned;
use serde::Serialize; use serde::Serialize;
use std::cell::RefCell; use std::cell::RefCell;
use std::cell::UnsafeCell;
use std::iter::once; use std::iter::once;
use std::ops::Deref; use std::ops::Deref;
use std::ops::DerefMut; use std::ops::DerefMut;
@ -170,7 +171,7 @@ impl OpState {
op_table: OpTable::default(), op_table: OpTable::default(),
get_error_class_fn: &|_| "Error", get_error_class_fn: &|_| "Error",
tracker: OpsTracker { tracker: OpsTracker {
ops: RefCell::new(Vec::with_capacity(256)), ops: UnsafeCell::new(Vec::with_capacity(256)),
}, },
gotham_state: Default::default(), gotham_state: Default::default(),
} }

View file

@ -1,8 +1,7 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use crate::serde::Serialize; use crate::serde::Serialize;
use crate::OpId; use crate::OpId;
use std::cell::RefCell; use std::cell::UnsafeCell;
use std::cell::RefMut;
// TODO(@AaronO): split into AggregateMetrics & PerOpMetrics // TODO(@AaronO): split into AggregateMetrics & PerOpMetrics
#[derive(Clone, Default, Debug, Serialize)] #[derive(Clone, Default, Debug, Serialize)]
@ -26,18 +25,18 @@ pub struct OpMetrics {
// TODO(@AaronO): track errors // TODO(@AaronO): track errors
#[derive(Default, Debug)] #[derive(Default, Debug)]
pub struct OpsTracker { pub struct OpsTracker {
pub ops: RefCell<Vec<OpMetrics>>, pub ops: UnsafeCell<Vec<OpMetrics>>,
} }
impl OpsTracker { impl OpsTracker {
pub fn per_op(&self) -> Vec<OpMetrics> { pub fn per_op(&self) -> Vec<OpMetrics> {
self.ops.borrow().clone() self.ops_mut().clone()
} }
pub fn aggregate(&self) -> OpMetrics { pub fn aggregate(&self) -> OpMetrics {
let mut sum = OpMetrics::default(); let mut sum = OpMetrics::default();
for metrics in self.ops.borrow().iter() { for metrics in self.ops_mut().iter() {
sum.ops_dispatched += metrics.ops_dispatched; sum.ops_dispatched += metrics.ops_dispatched;
sum.ops_dispatched_sync += metrics.ops_dispatched_sync; sum.ops_dispatched_sync += metrics.ops_dispatched_sync;
sum.ops_dispatched_async += metrics.ops_dispatched_async; sum.ops_dispatched_async += metrics.ops_dispatched_async;
@ -54,35 +53,47 @@ impl OpsTracker {
sum sum
} }
fn ensure_capacity(&self, op_id: OpId) { #[allow(clippy::mut_from_ref)]
let ops = &mut self.ops.borrow_mut(); #[inline]
fn ops_mut(&self) -> &mut Vec<OpMetrics> {
unsafe { &mut *self.ops.get() }
}
#[inline]
fn ensure_capacity(ops: &mut Vec<OpMetrics>, op_id: OpId) {
if op_id >= ops.len() { if op_id >= ops.len() {
let delta_len = 1 + op_id - ops.len(); ops.resize(1 + op_id, OpMetrics::default())
ops.extend(vec![OpMetrics::default(); delta_len])
} }
} }
fn metrics_mut(&self, id: OpId) -> RefMut<OpMetrics> { #[allow(clippy::mut_from_ref)]
self.ensure_capacity(id); #[inline]
RefMut::map(self.ops.borrow_mut(), |ops| ops.get_mut(id).unwrap()) fn metrics_mut(&self, id: OpId) -> &mut OpMetrics {
let ops = self.ops_mut();
// TODO(@AaronO): Pre-alloc capacity at runtime init once we forbid post-boot op registrations
Self::ensure_capacity(ops, id);
unsafe { ops.get_unchecked_mut(id) }
} }
#[inline]
pub fn track_sync(&self, id: OpId) { pub fn track_sync(&self, id: OpId) {
let metrics = &mut self.metrics_mut(id); let metrics = self.metrics_mut(id);
metrics.ops_dispatched += 1; metrics.ops_dispatched += 1;
metrics.ops_completed += 1; metrics.ops_completed += 1;
metrics.ops_dispatched_sync += 1; metrics.ops_dispatched_sync += 1;
metrics.ops_completed_sync += 1; metrics.ops_completed_sync += 1;
} }
#[inline]
pub fn track_async(&self, id: OpId) { pub fn track_async(&self, id: OpId) {
let metrics = &mut self.metrics_mut(id); let metrics = self.metrics_mut(id);
metrics.ops_dispatched += 1; metrics.ops_dispatched += 1;
metrics.ops_dispatched_async += 1; metrics.ops_dispatched_async += 1;
} }
#[inline]
pub fn track_async_completed(&self, id: OpId) { pub fn track_async_completed(&self, id: OpId) {
let metrics = &mut self.metrics_mut(id); let metrics = self.metrics_mut(id);
metrics.ops_completed += 1; metrics.ops_completed += 1;
metrics.ops_completed_async += 1; metrics.ops_completed_async += 1;
} }