Skip to content

Comments

feat: use PIFE for callbacks passed to __esmMin wrapper#5319

Merged
hyf0 merged 1 commit intomainfrom
07-17-feat_use_pife_for_callbacks_passed_to___esmmin_wrapper
Jul 24, 2025
Merged

feat: use PIFE for callbacks passed to __esmMin wrapper#5319
hyf0 merged 1 commit intomainfrom
07-17-feat_use_pife_for_callbacks_passed_to___esmmin_wrapper

Conversation

@sapphi-red
Copy link
Member

@sapphi-red sapphi-red commented Jul 17, 2025

This PR changes the generated code to use PIFE for callbacks passed to __esmMin wrapper. This improved the start up runtime performance by 2.1x in the case I tested.

I tested this change on https://github.com/rolldown/benchmarks/tree/main/apps/10000 with the following config:

import { defineConfig } from "vite";

export default defineConfig({
  build: {
    rollupOptions: {
      output: {
        advancedChunks: {
          groups: [
            {
              name: 'some'
            }
          ]
        }
      }
    }
  },
  experimental: {
    enableNativePlugin: true,
  },
  esbuild: false,
});

I also updated the HTML to measure the render time.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vite + React</title>
  </head>
  <body>
    <div id="root"></div>
    <script type="module">
      globalThis.start = performance.now()
    </script>
    <script type="module" src="./src/index.jsx"></script>
    <script type="module">
      const end = performance.now()
      console.log('render time:', end - globalThis.start)
    </script>
  </body>
</html>

The results were (average of 5 times):

before after
dev (no minify, hmr=true) 295.3 ms 139.7 ms
build (minified) 190.1 ms 97.2 ms

I tested this on Chrome 138.0.7204.101.
Also note that this change increases the output code size slightly:

Before: 6,338.19 kB (gzip: 1,871.28 kB)
After: 6,376.20 kB (gzip: 1,874.64 kB)

requires oxc-project/oxc#12353


Note: The same optimization can be applied to __commonJSMin, __esm, __commonJS, createEsmInitializer.

@netlify
Copy link

netlify bot commented Jul 17, 2025

Deploy Preview for rolldown-rs canceled.

Name Link
🔨 Latest commit 5d80e7e
🔍 Latest deploy log https://app.netlify.com/projects/rolldown-rs/deploys/6882216c5be44a0007c6d7fa

graphite-app bot pushed a commit to oxc-project/oxc that referenced this pull request Jul 20, 2025
PIFE is the abbreviation of "Possibly-Invoked Function Expressions". It is a function expression wrapped with a parenthesized expression.
PIFEs annotate functions that are likely to be invoked eagerly. When v8 encounters such expressions, it compiles them eagerly (rather than compiling it later). See [v8's blog post](https://v8.dev/blog/preparser#pife) for more details.

The blog post only mentions regular FunctionExpressions, but ArrowFunctions are also supported. The cases that will be eagerly compiled are:

- when `!` comes before function literals ([code](https://github.com/v8/v8/blob/328f6c467b940f322544567740c9c871064d045c/src/parsing/parser-base.h#L3730-L3733)) (e.g. `!function(){}`)
- when a function expression is wrapped with parenthesis ([code](https://github.com/v8/v8/blob/328f6c467b940f322544567740c9c871064d045c/src/parsing/parser-base.h#L2243-L2248)) (e.g. `(function () {})`, `(async function () {})`)
- when an arrow function is wrapped with parenthesis ([code1](https://github.com/v8/v8/blob/328f6c467b940f322544567740c9c871064d045c/src/parsing/parser-base.h#L2173-L2174), [code2](https://github.com/v8/v8/blob/328f6c467b940f322544567740c9c871064d045c/src/parsing/parser-base.h#L2232-L2259), [code3](https://github.com/v8/v8/blob/328f6c467b940f322544567740c9c871064d045c/src/parsing/parser-base.h#L3297-L3298)) (e.g. `console.log((() => {}))`)
- when `()` or ``` `` ``` (tagged templates) comes after function literals (only in some cases) ([code1](https://github.com/v8/v8/blob/328f6c467b940f322544567740c9c871064d045c/src/parsing/parser-base.h#L3987-L3992), [code2](https://github.com/v8/v8/blob/328f6c467b940f322544567740c9c871064d045c/src/parsing/parser-base.h#L4344-L4348)) (e.g. `~function(){}()`, ```~function(){}`` ```)
- when [explicit compile hints](https://v8.dev/blog/explicit-compile-hints) are used ([code1](https://github.com/v8/v8/blob/328f6c467b940f322544567740c9c871064d045c/src/parsing/parser.cc#L2717-L2720), [code2](https://github.com/v8/v8/blob/328f6c467b940f322544567740c9c871064d045c/src/parsing/parser-base.h#L5070-L5073)) (e.g. `//# allFunctionsCalledOnLoad`)

Keeping PIFEs as-is in the code generation will unlock optimizations like rolldown/rolldown#5319.

_Note: this PR only implements arrow function PIFEs for now._
@sapphi-red sapphi-red force-pushed the 07-17-feat_use_pife_for_callbacks_passed_to___esmmin_wrapper branch from 7d888e2 to 74b7e91 Compare July 23, 2025 05:29
@github-actions
Copy link
Contributor

github-actions bot commented Jul 23, 2025

Benchmarks Rust

  • target: main(fce0763)
  • pr: 07-17-feat_use_pife_for_callbacks_passed_to___esmmin_wrapper(5d80e7e)
group                                                        pr                                     target
-----                                                        --                                     ------
bundle/bundle@multi-duplicated-top-level-symbol              1.00     77.2±2.26ms        ? ?/sec    1.01     77.6±2.79ms        ? ?/sec
bundle/bundle@multi-duplicated-top-level-symbol-sourcemap    1.01     87.0±1.90ms        ? ?/sec    1.00     86.5±2.34ms        ? ?/sec
bundle/bundle@rome_ts                                        1.01    115.5±4.36ms        ? ?/sec    1.00    113.8±2.70ms        ? ?/sec
bundle/bundle@rome_ts-sourcemap                              1.01    136.4±1.69ms        ? ?/sec    1.00    135.3±2.33ms        ? ?/sec
bundle/bundle@threejs                                        1.00     41.8±1.63ms        ? ?/sec    1.00     41.6±1.08ms        ? ?/sec
bundle/bundle@threejs-sourcemap                              1.01     52.3±1.68ms        ? ?/sec    1.00     52.0±0.99ms        ? ?/sec
bundle/bundle@threejs10x                                     1.02    441.8±6.43ms        ? ?/sec    1.00    433.6±4.04ms        ? ?/sec
bundle/bundle@threejs10x-sourcemap                           1.01    524.9±4.12ms        ? ?/sec    1.00    521.5±4.21ms        ? ?/sec
scan/scan@rome_ts                                            1.00     87.9±1.73ms        ? ?/sec    1.00     88.1±1.38ms        ? ?/sec
scan/scan@threejs                                            1.00     31.1±1.96ms        ? ?/sec    1.00     31.0±2.17ms        ? ?/sec
scan/scan@threejs10x                                         1.00    320.9±3.64ms        ? ?/sec    1.00    321.5±3.55ms        ? ?/sec

@sapphi-red sapphi-red force-pushed the 07-17-feat_use_pife_for_callbacks_passed_to___esmmin_wrapper branch from 74b7e91 to 71e0985 Compare July 24, 2025 11:38
@sapphi-red sapphi-red marked this pull request as ready for review July 24, 2025 11:39
@sapphi-red sapphi-red marked this pull request as draft July 24, 2025 11:48
@sapphi-red sapphi-red force-pushed the 07-17-feat_use_pife_for_callbacks_passed_to___esmmin_wrapper branch from 71e0985 to 5d80e7e Compare July 24, 2025 12:04
@sapphi-red sapphi-red marked this pull request as ready for review July 24, 2025 12:06
@hyf0 hyf0 added this pull request to the merge queue Jul 24, 2025
Merged via the queue into main with commit e7da269 Jul 24, 2025
23 checks passed
@hyf0 hyf0 deleted the 07-17-feat_use_pife_for_callbacks_passed_to___esmmin_wrapper branch July 24, 2025 17:05
github-merge-queue bot pushed a commit that referenced this pull request Jul 25, 2025
Same with #5319 but for `__esm`.

This change causes many diffs against esbuild. Should I add something to
reduce the diff?
github-merge-queue bot pushed a commit that referenced this pull request Jul 25, 2025
github-merge-queue bot pushed a commit that referenced this pull request Jul 25, 2025
…wrapper (#5426)

Same with #5319 but for `__commonJSMin` / `_commonJS`.
github-merge-queue bot pushed a commit that referenced this pull request Jul 25, 2025
Boshen pushed a commit that referenced this pull request Jul 30, 2025
## [1.0.0-beta.30] - 2025-07-30

### 💥 BREAKING CHANGES

- rolldown: remove unfinished module federation support (#5471) by @Boshen
- disable `strictExecutionOrder` by default (#5436) by @hyf0

### 🚀 Features

- hmr: multiple changes should result to multiple updates (#5500) by @hyf0
- binding: add memory adjustment hint in fn write (#5375) by @Brooooooklyn
- store sideEffects information about global var access (#5495) by @IWANABETHATGUY
- merge side effects detail (#5486) by @IWANABETHATGUY
- plugin/vite-resolve: add warn / debug logs (#5476) by @sapphi-red
- plugin/vite-resolve: avoid wrapping errors with napi errors (#5483) by @sapphi-red
- add `this.fs` support (#5475) by @sapphi-red
- rolldown_plugin_asset: align `generate_bundle` logic (#5480) by @shulaoda
- hmr: prepare to launch that batched edits should result to multiple hmr output (#5458) by @hyf0
- hmr: support `import.meta.hot.invalidate` (#5457) by @hyf0
- mark all `toESM` as pure (#5461) by @IWANABETHATGUY
- rolldown_plugin_asset: align load hook logic (#5452) by @shulaoda
- rolldown_plugin_utils: align `file_to_built_url` (#5450) by @shulaoda
- rolldown_plugin_utils: align `should_inline` logic (#5308) by @AliceLanniste
- rolldown_plugin_asset: add partial `file_to_built_url` support (#5445) by @shulaoda
- expose `optimization.pifeForModuleWrappers` option (#5433) by @sapphi-red
- add `optimization.pifeForModuleWrappers` option (#5432) by @sapphi-red
- use PIFE for callback passed to `createCjsInitializer` (#5427) by @sapphi-red
- use PIFE for callbacks passed to `__commonJSMin` / `_commonJS` wrapper (#5426) by @sapphi-red
- use PIFE for callback passed to `createEsmInitializer` (#5425) by @sapphi-red
- use PIFE for callbacks passed to `__esm` wrapper (#5424) by @sapphi-red
- use PIFE for callbacks passed to `__esmMin` wrapper (#5319) by @sapphi-red
- rolldown: oxc v0.78.0 (#5421) by @Boshen
- rolldown: support `output.sourcemapBaseUrl` (#5413) by @situ2001
- mark all `__commonJS` CallExpression as **Pure** (#5419) by @IWANABETHATGUY
- rolldown_plugin_alias: warn if alias resolves to non-absolute path (#5417) by @shulaoda
- rolldown_plugin_asset: align `encode_uri_path` logic (#5410) by @shulaoda
- add warning and conversion for `import.meta` for non-`esm` output format (#5378) by @7086cmd

### 🐛 Bug Fixes

- use uuid_v4 to generate unique id for hook calls (#5501) by @hyf0
- modules that are sideeffect free but relies on the execution order is not wrapped (#5498) by @IWANABETHATGUY
- missing_export warning should not be an hard error (#5493) by @sapphi-red
- cli: remove unnecessary `await` (#5487) by @situ2001
- browser: stub fs/promises for browser build (#5484) by @sapphi-red
- indirect requiring external module  is not wrapped by `__toESM` in cjs format (#5454) by @IWANABETHATGUY
- Panic on reexport external module in  CJS format (#5430) by @IWANABETHATGUY
- handle top-level return statements in CommonJS modules (#5437) by @hyf0
- panic when using preserveModules: true and certain dependencies (#5415) by @IWANABETHATGUY
- rolldown_plugin_alias: only replace the first matched alias (#5412) by @shulaoda
- canonical name not found panic happens with treeshake.commonjs=true (#5409) by @IWANABETHATGUY
- hmr: shouldn't consider self-accepting module as hmr boundary for its importee (#5405) by @hyf0
- hmr: should detect hmr boundary correctly (#5400) by @hyf0
- optimization.inlineConst: true generates invalid code when importing a module statically and dynamically (#5398) by @IWANABETHATGUY
- top level VarDeclaration is not hoisted when wrapped in `__esm` (#5396) by @IWANABETHATGUY

### 🚜 Refactor

- use pascal case when naming bitflags field (#5497) by @IWANABETHATGUY
- test/hmr: use sensible time to wait (#5490) by @hyf0
- hmr: update message types to use 'hmr:update' (#5489) by @hyf0
- hmr: replace `HmrOutput` with `HmrUpdate` (#5488) by @hyf0
- node/hmr: re-organize file structures (#5485) by @hyf0
- rolldown_plugin_utils: improve `asset_to_data_url` (#5481) by @shulaoda
- replace pattern match for SideEffectsDetail with bitflags api (#5479) by @IWANABETHATGUY
- rename stmtSideEffect to SideEffectDetail (#5478) by @IWANABETHATGUY
- use bitflags store more details about side effects (#5477) by @IWANABETHATGUY
- node/hmr: tweak package `test-dev-server` (#5462) by @hyf0
- hmr: tweak naming and add comments (#5459) by @hyf0
- test/hmr: remove hard-code edited content (#5189) by @hyf0
- rust: make `Log#code` an `Option` (#5416) by @shulaoda
- hmr: should mark self-accept module correctly (#5406) by @hyf0
- hmr: remove unnecessary data during `propagate_update` (#5402) by @hyf0
- hmr: make hmr patch output less changeable (#5401) by @hyf0
- `__esm` top level bindings hoisted (#5397) by @IWANABETHATGUY
- skip fast in  esm format when transform import.meta (#5395) by @IWANABETHATGUY

### 📚 Documentation

- clarify rolldown-rollup behavior difference around output generation (#5439) by @sapphi-red

### ⚡ Performance

- reduce runtime symbol memory usage and hashtable lookup (#5460) by @IWANABETHATGUY

### 🧪 Testing

- hmr: support to run mutiple test fixtures (#5456) by @hyf0
- basic tests for `optimization.pifeForModuleWrappers` (#5435) by @sapphi-red

### ⚙️ Miscellaneous Tasks

- deps: update github-actions (#5509) by @renovate[bot]
- debug: update default session ID to meaningful `unknown-session` (#5502) by @hyf0
- deps: update dependency rolldown-plugin-dts to v0.14.2 (#5492) by @renovate[bot]
- auto generated runtime_helper bitflags (#5474) by @IWANABETHATGUY
- fix wasi build failed (#5470) by @IWANABETHATGUY
- deps: lock file maintenance (#5467) by @renovate[bot]
- deps: lock file maintenance (#5466) by @renovate[bot]
- deps: lock file maintenance rust crates (#5465) by @renovate[bot]
- deps: lock file maintenance npm packages (#5464) by @renovate[bot]
- deps: update github-actions (#5463) by @renovate[bot]
- export `__commonJSMin` in runtime-base.js (#5455) by @IWANABETHATGUY
- rolldown_plugin_utils: remove `file_to_dev_url` temporarily (#5446) by @shulaoda
- rolldown_plugin_asset: move `remove_url_query` into `rolldown_plugin_utils` (#5444) by @shulaoda
- rolldown: disable aarch64 atomics (#5447) by @Brooooooklyn
- remove diff with esbuild (#5428) by @IWANABETHATGUY
- dx/ai: add deepwiki badge to enable automatic refresh (#5423) by @hyf0
- dx/ai: Use `.cursorignore` to ignore meaningless files for AI (#5422) by @hyf0
- rolldown_plugin_alias: inline matches and remove redundant comment (#5418) by @shulaoda
- rolldown_plugin_asset: remove unnecessary comments (#5411) by @shulaoda
- rolldown_plugin_manifest: remove unnecessary code (#5408) by @shulaoda
- deps: update dependency tsdown to v0.13.0 (#5392) by @renovate[bot]
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