Skip to content

Commit

Permalink
use prehash to avoid rehashing the key in the task cache (vercel/turb…
Browse files Browse the repository at this point in the history
…orepo#8174)

### Description

This avoids hashing the task type multiple times, e. g. for inserting
after lookup or on rehashing of the hash map

### Testing Instructions

<!--
  Give a quick description of steps to test your changes.
-->
  • Loading branch information
sokra authored Jun 3, 2024
1 parent 0d6a13d commit 7074834
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 9 deletions.
1 change: 1 addition & 0 deletions crates/turbo-tasks-memory/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ rustc-hash = { workspace = true }
smallvec = { workspace = true }
tokio = { workspace = true }
tracing = { workspace = true }
turbo-prehash = { workspace = true }
turbo-tasks = { workspace = true }
turbo-tasks-hash = { workspace = true }
turbo-tasks-malloc = { workspace = true, default-features = false }
Expand Down
14 changes: 11 additions & 3 deletions crates/turbo-tasks-memory/src/memory_backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use dashmap::{mapref::entry::Entry, DashMap};
use rustc_hash::FxHasher;
use tokio::task::futures::TaskLocalFuture;
use tracing::trace_span;
use turbo_prehash::{BuildHasherExt, PassThroughHash, PreHashed};
use turbo_tasks::{
backend::{
Backend, BackendJobId, CellContent, PersistentTaskType, TaskExecutionSpec,
Expand All @@ -34,11 +35,16 @@ use crate::{
task::{Task, TaskDependency, TaskDependencySet, DEPENDENCIES_TO_TRACK},
};

fn prehash_task_type(task_type: PersistentTaskType) -> PreHashed<PersistentTaskType> {
BuildHasherDefault::<FxHasher>::prehash(&Default::default(), task_type)
}

pub struct MemoryBackend {
memory_tasks: NoMoveVec<Task, 13>,
backend_jobs: NoMoveVec<Job>,
backend_job_id_factory: IdFactory<BackendJobId>,
task_cache: DashMap<Arc<PersistentTaskType>, TaskId, BuildHasherDefault<FxHasher>>,
task_cache:
DashMap<Arc<PreHashed<PersistentTaskType>>, TaskId, BuildHasherDefault<PassThroughHash>>,
memory_limit: usize,
gc_queue: Option<GcQueue>,
idle_gc_active: AtomicBool,
Expand Down Expand Up @@ -513,10 +519,11 @@ impl Backend for MemoryBackend {

fn get_or_create_persistent_task(
&self,
mut task_type: PersistentTaskType,
task_type: PersistentTaskType,
parent_task: TaskId,
turbo_tasks: &dyn TurboTasksBackendApi<MemoryBackend>,
) -> TaskId {
let task_type = prehash_task_type(task_type);
if let Some(task) =
self.lookup_and_connect_task(parent_task, &self.task_cache, &task_type, turbo_tasks)
{
Expand All @@ -525,8 +532,9 @@ impl Backend for MemoryBackend {
} else {
// It's important to avoid overallocating memory as this will go into the task
// cache and stay there forever. We can to be as small as possible.
let (task_type_hash, mut task_type) = PreHashed::into_parts(task_type);
task_type.shrink_to_fit();
let task_type = Arc::new(task_type);
let task_type = Arc::new(PreHashed::new(task_type_hash, task_type));
// slow pass with key lock
let id = turbo_tasks.get_fresh_task_id();
let task = Task::new_persistent(
Expand Down
18 changes: 12 additions & 6 deletions crates/turbo-tasks-memory/src/task.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use rustc_hash::FxHasher;
use smallvec::SmallVec;
use tokio::task_local;
use tracing::Span;
use turbo_prehash::PreHashed;
use turbo_tasks::{
backend::{PersistentTaskType, TaskExecutionSpec},
event::{Event, EventListener},
Expand Down Expand Up @@ -76,13 +77,15 @@ enum TaskType {
Once(Box<OnceTaskFn>),

/// A normal persistent task
Persistent { ty: Arc<PersistentTaskType> },
Persistent {
ty: Arc<PreHashed<PersistentTaskType>>,
},
}

enum TaskTypeForDescription {
Root,
Once,
Persistent(Arc<PersistentTaskType>),
Persistent(Arc<PreHashed<PersistentTaskType>>),
}

impl TaskTypeForDescription {
Expand Down Expand Up @@ -406,7 +409,10 @@ use self::{
};

impl Task {
pub(crate) fn new_persistent(id: TaskId, task_type: Arc<PersistentTaskType>) -> Self {
pub(crate) fn new_persistent(
id: TaskId,
task_type: Arc<PreHashed<PersistentTaskType>>,
) -> Self {
let ty = TaskType::Persistent { ty: task_type };
let description = Self::get_event_description_static(id, &ty);
Self {
Expand Down Expand Up @@ -516,7 +522,7 @@ impl Task {

pub(crate) fn get_function_name(&self) -> Option<Cow<'static, str>> {
if let TaskType::Persistent { ty, .. } = &self.ty {
match &**ty {
match &***ty {
PersistentTaskType::Native(native_fn, _)
| PersistentTaskType::ResolveNative(native_fn, _) => {
return Some(Cow::Borrowed(&registry::get_function(*native_fn).name));
Expand All @@ -539,7 +545,7 @@ impl Task {
match ty {
TaskTypeForDescription::Root => format!("[{}] root", id),
TaskTypeForDescription::Once => format!("[{}] once", id),
TaskTypeForDescription::Persistent(ty) => match &**ty {
TaskTypeForDescription::Persistent(ty) => match &***ty {
PersistentTaskType::Native(native_fn, _) => {
format!("[{}] {}", id, registry::get_function(*native_fn).name)
}
Expand Down Expand Up @@ -742,7 +748,7 @@ impl Task {
tracing::trace_span!("turbo_tasks::once_task"),
)
}
TaskType::Persistent { ty, .. } => match &**ty {
TaskType::Persistent { ty, .. } => match &***ty {
PersistentTaskType::Native(native_fn, inputs) => {
let result =
if let PrepareTaskType::Native(func, bound_fn) = &state.prepared_type {
Expand Down

0 comments on commit 7074834

Please sign in to comment.