Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Performance Improvements (5) #6076

Merged
merged 9 commits into from
Oct 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crates/turbo-tasks/src/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,7 @@ impl<B: Backend + 'static> TurboTasks<B> {
/// Calls a native function with arguments. Resolves arguments when needed
/// with a wrapper [Task].
pub fn dynamic_call(&self, func: FunctionId, inputs: Vec<ConcreteTaskInput>) -> RawVc {
if inputs.iter().all(|i| i.is_resolved() && !i.is_nothing()) {
if inputs.iter().all(|i| i.is_resolved()) {
ForsakenHarmony marked this conversation as resolved.
Show resolved Hide resolved
self.native_call(func, inputs)
} else {
RawVc::TaskOutput(self.backend.get_or_create_persistent_task(
Expand Down
110 changes: 107 additions & 3 deletions crates/turbopack-core/src/chunk/availability_info.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,84 @@
use std::ops::{BitOr, BitOrAssign};

use turbo_tasks::Vc;

use super::available_modules::AvailableAssets;
use crate::module::Module;

/// This specifies which information is needed from an AvailabilityInfo
#[turbo_tasks::value(shared)]
#[derive(Copy, Clone, Debug)]
pub struct AvailabilityInfoNeeds {
pub current_availability_root: bool,
pub available_modules: bool,
}

impl AvailabilityInfoNeeds {
pub fn all() -> Self {
Self {
current_availability_root: true,
available_modules: true,
}
}

pub fn none() -> Self {
Self {
current_availability_root: false,
available_modules: false,
}
}

pub fn is_complete(self) -> bool {
let Self {
current_availability_root,
available_modules,
} = self;
current_availability_root && available_modules
}
}

impl BitOr for AvailabilityInfoNeeds {
type Output = AvailabilityInfoNeeds;

fn bitor(mut self, rhs: Self) -> Self::Output {
let Self {
available_modules,
current_availability_root,
} = rhs;
self.current_availability_root |= current_availability_root;
self.available_modules |= available_modules;
self
}
}

impl BitOrAssign for AvailabilityInfoNeeds {
fn bitor_assign(&mut self, rhs: Self) {
*self = *self | rhs;
}
}

#[turbo_tasks::value(serialization = "auto_for_input")]
#[derive(PartialOrd, Ord, Hash, Clone, Copy, Debug)]
pub enum AvailabilityInfo {
sokra marked this conversation as resolved.
Show resolved Hide resolved
/// Available modules are not tracked or the information is not available
/// due to specified needs.
Untracked,
/// There are no modules available (or the information is not available due
/// to specified needs), but it's tracked for nested chunk groups
/// and the current chunk group root is defined.
Root {
current_availability_root: Vc<Box<dyn Module>>,
},
Inner {
/// There are modules already available and the current chunk group root is
/// defined.
Complete {
available_modules: Vc<AvailableAssets>,
current_availability_root: Vc<Box<dyn Module>>,
},
/// Only partial information is available, about the available modules.
OnlyAvailableModules {
available_modules: Vc<AvailableAssets>,
},
}

impl AvailabilityInfo {
Expand All @@ -23,20 +88,59 @@ impl AvailabilityInfo {
Self::Root {
current_availability_root,
} => Some(*current_availability_root),
Self::Inner {
Self::Complete {
current_availability_root,
..
} => Some(*current_availability_root),
Self::OnlyAvailableModules { .. } => None,
}
}

pub fn available_modules(&self) -> Option<Vc<AvailableAssets>> {
match self {
Self::Untracked => None,
Self::Root { .. } => None,
Self::Inner {
Self::Complete {
available_modules, ..
} => Some(*available_modules),
Self::OnlyAvailableModules {
available_modules, ..
} => Some(*available_modules),
}
}

/// Returns AvailabilityInfo, but only with the information that is needed
pub fn reduce_to_needs(self, needs: AvailabilityInfoNeeds) -> Self {
jridgewell marked this conversation as resolved.
Show resolved Hide resolved
let AvailabilityInfoNeeds {
available_modules,
current_availability_root,
} = needs;
match (current_availability_root, available_modules, self) {
(false, false, _) => Self::Untracked,
(true, true, _) => self,
(
true,
false,
Self::Root {
current_availability_root,
}
| Self::Complete {
current_availability_root,
..
},
) => Self::Root {
current_availability_root,
},
(true, false, _) => Self::Untracked,
(
false,
true,
Self::Complete {
available_modules, ..
}
| Self::OnlyAvailableModules { available_modules },
) => Self::OnlyAvailableModules { available_modules },
(false, true, _) => Self::Untracked,
}
}
}
8 changes: 4 additions & 4 deletions crates/turbopack-ecmascript/src/chunk/esm_scope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ use std::collections::HashMap;

use anyhow::{Context, Result};
use petgraph::{algo::tarjan_scc, prelude::DiGraphMap};
use turbo_tasks::{TryFlatJoinIterExt, Value, Vc};
use turbo_tasks::{TryFlatJoinIterExt, Vc};
use turbopack_core::{
chunk::{availability_info::AvailabilityInfo, available_modules::chunkable_modules_set},
chunk::available_modules::chunkable_modules_set,
module::{Module, ModulesSet},
};

Expand Down Expand Up @@ -38,8 +38,8 @@ pub(crate) struct EsmScopeSccs(Vec<Vc<EsmScopeScc>>);
impl EsmScope {
/// Create a new [EsmScope] from the availability root given.
#[turbo_tasks::function]
pub(crate) async fn new(availability_info: Value<AvailabilityInfo>) -> Result<Vc<Self>> {
let assets = if let Some(root) = availability_info.current_availability_root() {
pub(crate) async fn new(availability_root: Option<Vc<Box<dyn Module>>>) -> Result<Vc<Self>> {
let assets = if let Some(root) = availability_root {
chunkable_modules_set(root)
} else {
ModulesSet::empty()
Expand Down
9 changes: 6 additions & 3 deletions crates/turbopack-ecmascript/src/chunk/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,17 +271,20 @@ impl FromChunkableModule for Box<dyn EcmascriptChunkItem> {
AvailabilityInfo::Untracked => AvailabilityInfo::Untracked,
AvailabilityInfo::Root {
current_availability_root,
} => AvailabilityInfo::Inner {
} => AvailabilityInfo::Complete {
available_modules: AvailableAssets::new(vec![current_availability_root]),
current_availability_root: Vc::upcast(module),
},
AvailabilityInfo::Inner {
AvailabilityInfo::Complete {
available_modules,
current_availability_root,
} => AvailabilityInfo::Inner {
} => AvailabilityInfo::Complete {
available_modules: available_modules.with_roots(vec![current_availability_root]),
current_availability_root: Vc::upcast(module),
},
AvailabilityInfo::OnlyAvailableModules { .. } => {
panic!("OnlyAvailableModules should not appear here")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
panic!("OnlyAvailableModules should not appear here")
unreachable!("OnlyAvailableModules should not appear here")

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it's unreachable

}
};

let manifest_asset =
Expand Down
11 changes: 10 additions & 1 deletion crates/turbopack-ecmascript/src/code_gen.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use serde::{Deserialize, Serialize};
use swc_core::ecma::visit::{AstParentKind, VisitMut};
use turbo_tasks::{debug::ValueDebugFormat, trace::TraceRawVcs, Value, Vc};
use turbopack_core::chunk::availability_info::AvailabilityInfo;
use turbopack_core::chunk::availability_info::{AvailabilityInfo, AvailabilityInfoNeeds};

use crate::chunk::EcmascriptChunkingContext;

Expand Down Expand Up @@ -34,6 +34,15 @@ pub trait CodeGenerateable {

#[turbo_tasks::value_trait]
pub trait CodeGenerateableWithAvailabilityInfo {
/// Returns the pieces of AvailabilityInfo that are needed for
/// `code_generation`.
fn get_availability_info_needs(
jridgewell marked this conversation as resolved.
Show resolved Hide resolved
self: Vc<Self>,
_is_async_module: bool,
) -> Vc<AvailabilityInfoNeeds> {
AvailabilityInfoNeeds::all().cell()
}

fn code_generation(
self: Vc<Self>,
chunking_context: Vc<Box<dyn EcmascriptChunkingContext>>,
Expand Down
24 changes: 15 additions & 9 deletions crates/turbopack-ecmascript/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -353,11 +353,6 @@ impl EcmascriptModuleAsset {
availability_info: Value<AvailabilityInfo>,
) -> Result<Vc<EcmascriptModuleContent>> {
let this = self.await?;
let availability_info = if *self.analyze().needs_availability_info().await? {
availability_info
} else {
Value::new(AvailabilityInfo::Untracked)
};

let parsed = parse(this.source, Value::new(this.ty), this.transforms);

Expand Down Expand Up @@ -515,13 +510,24 @@ impl EcmascriptChunkItem for ModuleChunkItem {
availability_info: Value<AvailabilityInfo>,
) -> Result<Vc<EcmascriptChunkItemContent>> {
let this = self.await?;
let content = this
.module
.module_content(this.chunking_context, availability_info);
let async_module_options = this
.module
.get_async_module()
.module_options(availability_info);
.module_options(availability_info.current_availability_root());
let is_async_module = async_module_options.await?.is_some();
let availability_info_needs = *this
sokra marked this conversation as resolved.
Show resolved Hide resolved
.module
.analyze()
.get_availability_info_needs(is_async_module)
.await?;
// We reduce the availability info to the needs of the chunk item to improve
// caching of the methods that are called with availability info. e. g.
// module_content() can be cached for different availability info when it
// doesn't really need that info.
let availability_info = availability_info.reduce_to_needs(availability_info_needs);
let content = this
.module
.module_content(this.chunking_context, Value::new(availability_info));

Ok(EcmascriptChunkItemContent::new(
content,
Expand Down
Loading
Loading