Skip to content

feat(lazy-barrel): support incremental build mode#8112

Closed
shulaoda wants to merge 1 commit intomainfrom
01-29-feat_lazy-barrel_support_incremental_build_mode
Closed

feat(lazy-barrel): support incremental build mode#8112
shulaoda wants to merge 1 commit intomainfrom
01-29-feat_lazy-barrel_support_incremental_build_mode

Conversation

@shulaoda
Copy link
Member

No description provided.

Copy link
Member Author


How to use the Graphite Merge Queue

Add the label graphite: merge-when-ready to this PR to add it to the merge queue.

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has enabled the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

This stack of pull requests is managed by Graphite. Learn more about stacking.

@shulaoda shulaoda marked this pull request as ready for review January 29, 2026 03:28
Copilot AI review requested due to automatic review settings January 29, 2026 03:28
@netlify
Copy link

netlify bot commented Jan 29, 2026

Deploy Preview for rolldown-rs ready!

Name Link
🔨 Latest commit 8a12839
🔍 Latest deploy log https://app.netlify.com/projects/rolldown-rs/deploys/697ad3aa94365e00096e0ec9
😎 Deploy Preview https://deploy-preview-8112--rolldown-rs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds support for incremental build mode in the lazy-barrel optimization feature. The implementation enables barrel modules to be processed correctly when building from cached snapshots during incremental/watch mode rebuilds.

Changes:

  • Added resolved_barrel_modules field to BarrelState to track import resolutions that need to be deferred when working with cached snapshots
  • Modified barrel module processing in module_loader.rs to handle both live modules and cached snapshot modules
  • Added merge logic in scan_stage_cache.rs to apply deferred import resolutions to cached modules

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
crates/rolldown_common/src/types/lazy_barrel.rs Added resolved_barrel_modules field to track deferred import resolutions for incremental builds
crates/rolldown/src/types/scan_stage_cache.rs Added logic to apply deferred barrel module import resolutions during cache merge
crates/rolldown/src/module_loader/module_loader.rs Refactored barrel module processing to use raw pointers for handling both live and cached modules, with conditional logic to defer updates when working with cached snapshots

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@github-actions
Copy link
Contributor

Benchmarks Rust

  • target: main(f3cf301)
  • pr: 01-29-feat_lazy-barrel_support_incremental_build_mode(8a12839)
group                                                        pr                                     target
-----                                                        --                                     ------
bundle/bundle@multi-duplicated-top-level-symbol              1.00     66.9±3.00ms        ? ?/sec    1.04     69.4±2.27ms        ? ?/sec
bundle/bundle@multi-duplicated-top-level-symbol-sourcemap    1.00     70.4±1.24ms        ? ?/sec    1.10     77.7±3.26ms        ? ?/sec
bundle/bundle@rome_ts                                        1.00    100.1±3.57ms        ? ?/sec    1.03    103.3±2.16ms        ? ?/sec
bundle/bundle@rome_ts-sourcemap                              1.00    110.2±1.85ms        ? ?/sec    1.03    113.2±2.11ms        ? ?/sec
bundle/bundle@threejs                                        1.01     36.2±0.69ms        ? ?/sec    1.00     35.9±2.23ms        ? ?/sec
bundle/bundle@threejs-sourcemap                              1.01     41.1±1.26ms        ? ?/sec    1.00     40.8±1.18ms        ? ?/sec
bundle/bundle@threejs10x                                     1.00    354.6±4.19ms        ? ?/sec    1.02    361.3±6.00ms        ? ?/sec
bundle/bundle@threejs10x-sourcemap                           1.00    417.2±5.36ms        ? ?/sec    1.00    418.5±8.26ms        ? ?/sec
scan/scan@rome_ts                                            1.00     80.9±1.74ms        ? ?/sec    1.04     84.0±2.23ms        ? ?/sec
scan/scan@threejs                                            1.02     28.9±2.27ms        ? ?/sec    1.00     28.3±0.46ms        ? ?/sec
scan/scan@threejs10x                                         1.00    287.8±5.55ms        ? ?/sec    1.00    288.4±5.88ms        ? ?/sec

if !needed_records.contains_key(&rec_idx) {
return true;
}
let barrel_normal_module = unsafe { &mut *barrel_module_ptr };
Copy link
Member

Choose a reason for hiding this comment

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

Is this unsafe necessary?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, dereference of raw pointer is unsafe and requires an unsafe function or block

Copy link
Member

Choose a reason for hiding this comment

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

I think I knew that. What I'm asking is does the logic have to be implemented with using unsafe?

Copy link
Member Author

@shulaoda shulaoda Jan 29, 2026

Choose a reason for hiding this comment

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

Yes, this is necessary. As shown below, barrel_normal_module and self.try_spawn_new_task conflict due to a &mut vs & borrow. In addition, barrel_normal_module is immutably borrowed both before and after the call to self.try_spawn_new_task and also mutably borrowed after in full build.

let new_idx = self.try_spawn_new_task(
  resolved_id.clone(),
  Some(ModuleTaskOwnerRef::new(barrel_normal_module, import_record_state.span)),
  false,
  import_record_state.asserted_module_type.as_ref(),
  user_defined_entries,
)

Copy link
Member Author

@shulaoda shulaoda Jan 29, 2026

Choose a reason for hiding this comment

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

Using a raw pointer is the simplest solution. Otherwise, we would need to refactor and add a significant amount of extra code to work around this. And they ultimately achieve the same result.

Copy link
Member

Choose a reason for hiding this comment

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

Don't feel so. I looked into the code and I think the current design has issues.

Copy link
Member Author

Choose a reason for hiding this comment

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

Another safe implementation: #8114

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants