Skip to content

refactor: restore endsWith usage #19554

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

Merged
merged 1 commit into from
Mar 5, 2025

Conversation

OnlyWick
Copy link
Contributor

@OnlyWick OnlyWick commented Mar 3, 2025

Description

refs: #12539 (comment)

@patak-dev patak-dev added the p1-chore Doesn't change code behavior (priority) label Mar 3, 2025
@bluwy
Copy link
Member

bluwy commented Mar 3, 2025

Could we also compare the performance first with https://perf.link or a local script to double-confirm that it's fixed now?

@OnlyWick
Copy link
Contributor Author

OnlyWick commented Mar 3, 2025

Try this!

const data = "abcdefg";

const total = 100000;

let start = performance.now();
for (let i = 0; i < total; i++) {
  data[data.length - 1] === "a";
}
console.log("index", performance.now() - start);

start = performance.now();
for (let i = 0; i < total; i++) {
  data.endsWith("a");
}
console.log("endsWith", performance.now() - start);

Node.js v18
image

@OnlyWick
Copy link
Contributor Author

OnlyWick commented Mar 3, 2025

I have tested in Node.js V12, endsWith is still faster than index accessor.

image

After testing in the browser, the performance difference between endsWith and the index accessor has indeed become smaller, Moreover, the performance of startsWith and endsWith may even be better. Additionally, aren't we in a Node.js environment? Perhaps we can ignore the differences in the browser?

endsWith VS index accessor

startsWith VS index accessor

Note: You need to RUN the tests multiple times to see the difference. Now they basically have little performance difference. Sometimes the index accessor is faster, sometimes starts/endsWith is faster.

But, if you run the test code I wrote in the Chrome console, index accessor will be faster. Could it be that there are some additional things being executed in the browser console that affect this?

@bluwy
Copy link
Member

bluwy commented Mar 5, 2025

I think the perf test should use a benchmarking tool to properly measure it, as I'm able to reproduce the slower perf for endsWith before. Node v18 is also using an older version of v8 which doesn't include the fix linked. Using node v22 would include the fix. I've adapted your benchmark like so:

import { bench, do_not_optimize, run } from 'mitata'

const data = 'abcdefg'

bench('index', function* () {
  yield () => do_not_optimize(data[data.length - 1] === 'a')
})

bench('endsWith', function* () {
  yield () => do_not_optimize(data.endsWith('a'))
})

run()
Node 18 Node 22
image image

So it does show that endsWith is now close to and sometimes faster than index now. Using the browser should yield similar results as we're mainly testing v8.

I was curious of a comparison as the chromium issue mentioned that they optimized endsWith the same way as startsWith, so theoretically [0] is still faster than startsWith which we changed in the past. And it seems to still be true:

Node 18 Node 22
image image

So we may want to still stick with [0]. (Though personally I think these micro-optimizations aren't necessarily something we have to stick to forever)

@patak-dev patak-dev merged commit 6113a96 into vitejs:main Mar 5, 2025
16 checks passed
renovate bot added a commit to andrei-picus-tink/auto-renovate that referenced this pull request Mar 8, 2025
| datasource | package | from  | to    |
| ---------- | ------- | ----- | ----- |
| npm        | vite    | 6.1.0 | 6.2.1 |


## [v6.2.1](https://github.com/vitejs/vite/blob/HEAD/packages/vite/CHANGELOG.md#small621-2025-03-07-small)

-   refactor: remove `isBuild` check from preAliasPlugin ([#19587](vitejs/vite#19587)) ([c9e086d](vitejs/vite@c9e086d)), closes [#19587](vitejs/vite#19587)
-   refactor: restore endsWith usage ([#19554](vitejs/vite#19554)) ([6113a96](vitejs/vite@6113a96)), closes [#19554](vitejs/vite#19554)
-   refactor: use `applyToEnvironment` in internal plugins ([#19588](vitejs/vite#19588)) ([f678442](vitejs/vite@f678442)), closes [#19588](vitejs/vite#19588)
-   fix(css): stabilize css module hashes with lightningcss in dev mode ([#19481](vitejs/vite#19481)) ([92125b4](vitejs/vite@92125b4)), closes [#19481](vitejs/vite#19481)
-   fix(deps): update all non-major dependencies ([#19555](vitejs/vite#19555)) ([f612e0f](vitejs/vite@f612e0f)), closes [#19555](vitejs/vite#19555)
-   fix(reporter): fix incorrect bundle size calculation with non-ASCII characters ([#19561](vitejs/vite#19561)) ([437c0ed](vitejs/vite@437c0ed)), closes [#19561](vitejs/vite#19561)
-   fix(sourcemap): combine sourcemaps with multiple sources without matched source ([#18971](vitejs/vite#18971)) ([e3f6ae1](vitejs/vite@e3f6ae1)), closes [#18971](vitejs/vite#18971)
-   fix(ssr): named export should overwrite export all ([#19534](vitejs/vite#19534)) ([2fd2fc1](vitejs/vite@2fd2fc1)), closes [#19534](vitejs/vite#19534)
-   feat: add `*?url&no-inline` type and warning for `.json?inline` / `.json?no-inline` ([#19566](vitejs/vite#19566)) ([c0d3667](vitejs/vite@c0d3667)), closes [#19566](vitejs/vite#19566)
-   test: add glob import test case ([#19516](vitejs/vite#19516)) ([aa1d807](vitejs/vite@aa1d807)), closes [#19516](vitejs/vite#19516)
-   test: convert config playground to unit tests ([#19568](vitejs/vite#19568)) ([c0e68da](vitejs/vite@c0e68da)), closes [#19568](vitejs/vite#19568)
-   test: convert resolve-config playground to unit tests ([#19567](vitejs/vite#19567)) ([db5fb48](vitejs/vite@db5fb48)), closes [#19567](vitejs/vite#19567)
-   perf: flush compile cache after 10s ([#19537](vitejs/vite#19537)) ([6c8a5a2](vitejs/vite@6c8a5a2)), closes [#19537](vitejs/vite#19537)
-   chore(css): move environment destructuring after condition check ([#19492](vitejs/vite#19492)) ([c9eda23](vitejs/vite@c9eda23)), closes [#19492](vitejs/vite#19492)
-   chore(html): remove unnecessary value check ([#19491](vitejs/vite#19491)) ([797959f](vitejs/vite@797959f)), closes [#19491](vitejs/vite#19491)


## [v6.2.0](https://github.com/vitejs/vite/blob/HEAD/packages/vite/CHANGELOG.md#620-2025-02-25)

-   fix(deps): update all non-major dependencies ([#19501](vitejs/vite#19501)) ([c94c9e0](vitejs/vite@c94c9e0)), closes [#19501](vitejs/vite#19501)
-   fix(worker): string interpolation in dynamic worker options ([#19476](vitejs/vite#19476)) ([07091a1](vitejs/vite@07091a1)), closes [#19476](vitejs/vite#19476)
-   chore: use unicode cross icon instead of x ([#19497](vitejs/vite#19497)) ([5c70296](vitejs/vite@5c70296)), closes [#19497](vitejs/vite#19497)


## [v6.1.1](https://github.com/vitejs/vite/blob/HEAD/packages/vite/CHANGELOG.md#small611-2025-02-19-small)

-   fix: ensure `.[cm]?[tj]sx?` static assets are JS mime ([#19453](vitejs/vite#19453)) ([e7ba55e](vitejs/vite@e7ba55e)), closes [#19453](vitejs/vite#19453)
-   fix: ignore `*.ipv4` address in cert ([#19416](vitejs/vite#19416)) ([973283b](vitejs/vite@973283b)), closes [#19416](vitejs/vite#19416)
-   fix(css): run rewrite plugin if postcss plugin exists ([#19371](vitejs/vite#19371)) ([bcdb51a](vitejs/vite@bcdb51a)), closes [#19371](vitejs/vite#19371)
-   fix(deps): bump tsconfck ([#19375](vitejs/vite#19375)) ([746a583](vitejs/vite@746a583)), closes [#19375](vitejs/vite#19375)
-   fix(deps): update all non-major dependencies ([#19392](vitejs/vite#19392)) ([60456a5](vitejs/vite@60456a5)), closes [#19392](vitejs/vite#19392)
-   fix(deps): update all non-major dependencies ([#19440](vitejs/vite#19440)) ([ccac73d](vitejs/vite@ccac73d)), closes [#19440](vitejs/vite#19440)
-   fix(html): ignore malformed src attrs ([#19397](vitejs/vite#19397)) ([aff7812](vitejs/vite@aff7812)), closes [#19397](vitejs/vite#19397)
-   fix(worker): fix web worker type detection ([#19462](vitejs/vite#19462)) ([edc65ea](vitejs/vite@edc65ea)), closes [#19462](vitejs/vite#19462)
-   refactor: remove custom .jxl mime ([#19457](vitejs/vite#19457)) ([0c85464](vitejs/vite@0c85464)), closes [#19457](vitejs/vite#19457)
-   feat: add support for injecting debug IDs ([#18763](vitejs/vite#18763)) ([0ff556a](vitejs/vite@0ff556a)), closes [#18763](vitejs/vite#18763)
-   chore: update 6.1.0 changelog ([#19363](vitejs/vite#19363)) ([fa7c211](vitejs/vite@fa7c211)), closes [#19363](vitejs/vite#19363)
renovate bot added a commit to andrei-picus-tink/auto-renovate that referenced this pull request Mar 8, 2025
| datasource | package | from  | to    |
| ---------- | ------- | ----- | ----- |
| npm        | vite    | 6.1.0 | 6.2.1 |


## [v6.2.1](https://github.com/vitejs/vite/blob/HEAD/packages/vite/CHANGELOG.md#small621-2025-03-07-small)

-   refactor: remove `isBuild` check from preAliasPlugin ([#19587](vitejs/vite#19587)) ([c9e086d](vitejs/vite@c9e086d)), closes [#19587](vitejs/vite#19587)
-   refactor: restore endsWith usage ([#19554](vitejs/vite#19554)) ([6113a96](vitejs/vite@6113a96)), closes [#19554](vitejs/vite#19554)
-   refactor: use `applyToEnvironment` in internal plugins ([#19588](vitejs/vite#19588)) ([f678442](vitejs/vite@f678442)), closes [#19588](vitejs/vite#19588)
-   fix(css): stabilize css module hashes with lightningcss in dev mode ([#19481](vitejs/vite#19481)) ([92125b4](vitejs/vite@92125b4)), closes [#19481](vitejs/vite#19481)
-   fix(deps): update all non-major dependencies ([#19555](vitejs/vite#19555)) ([f612e0f](vitejs/vite@f612e0f)), closes [#19555](vitejs/vite#19555)
-   fix(reporter): fix incorrect bundle size calculation with non-ASCII characters ([#19561](vitejs/vite#19561)) ([437c0ed](vitejs/vite@437c0ed)), closes [#19561](vitejs/vite#19561)
-   fix(sourcemap): combine sourcemaps with multiple sources without matched source ([#18971](vitejs/vite#18971)) ([e3f6ae1](vitejs/vite@e3f6ae1)), closes [#18971](vitejs/vite#18971)
-   fix(ssr): named export should overwrite export all ([#19534](vitejs/vite#19534)) ([2fd2fc1](vitejs/vite@2fd2fc1)), closes [#19534](vitejs/vite#19534)
-   feat: add `*?url&no-inline` type and warning for `.json?inline` / `.json?no-inline` ([#19566](vitejs/vite#19566)) ([c0d3667](vitejs/vite@c0d3667)), closes [#19566](vitejs/vite#19566)
-   test: add glob import test case ([#19516](vitejs/vite#19516)) ([aa1d807](vitejs/vite@aa1d807)), closes [#19516](vitejs/vite#19516)
-   test: convert config playground to unit tests ([#19568](vitejs/vite#19568)) ([c0e68da](vitejs/vite@c0e68da)), closes [#19568](vitejs/vite#19568)
-   test: convert resolve-config playground to unit tests ([#19567](vitejs/vite#19567)) ([db5fb48](vitejs/vite@db5fb48)), closes [#19567](vitejs/vite#19567)
-   perf: flush compile cache after 10s ([#19537](vitejs/vite#19537)) ([6c8a5a2](vitejs/vite@6c8a5a2)), closes [#19537](vitejs/vite#19537)
-   chore(css): move environment destructuring after condition check ([#19492](vitejs/vite#19492)) ([c9eda23](vitejs/vite@c9eda23)), closes [#19492](vitejs/vite#19492)
-   chore(html): remove unnecessary value check ([#19491](vitejs/vite#19491)) ([797959f](vitejs/vite@797959f)), closes [#19491](vitejs/vite#19491)


## [v6.2.0](https://github.com/vitejs/vite/blob/HEAD/packages/vite/CHANGELOG.md#620-2025-02-25)

-   fix(deps): update all non-major dependencies ([#19501](vitejs/vite#19501)) ([c94c9e0](vitejs/vite@c94c9e0)), closes [#19501](vitejs/vite#19501)
-   fix(worker): string interpolation in dynamic worker options ([#19476](vitejs/vite#19476)) ([07091a1](vitejs/vite@07091a1)), closes [#19476](vitejs/vite#19476)
-   chore: use unicode cross icon instead of x ([#19497](vitejs/vite#19497)) ([5c70296](vitejs/vite@5c70296)), closes [#19497](vitejs/vite#19497)


## [v6.1.1](https://github.com/vitejs/vite/blob/HEAD/packages/vite/CHANGELOG.md#small611-2025-02-19-small)

-   fix: ensure `.[cm]?[tj]sx?` static assets are JS mime ([#19453](vitejs/vite#19453)) ([e7ba55e](vitejs/vite@e7ba55e)), closes [#19453](vitejs/vite#19453)
-   fix: ignore `*.ipv4` address in cert ([#19416](vitejs/vite#19416)) ([973283b](vitejs/vite@973283b)), closes [#19416](vitejs/vite#19416)
-   fix(css): run rewrite plugin if postcss plugin exists ([#19371](vitejs/vite#19371)) ([bcdb51a](vitejs/vite@bcdb51a)), closes [#19371](vitejs/vite#19371)
-   fix(deps): bump tsconfck ([#19375](vitejs/vite#19375)) ([746a583](vitejs/vite@746a583)), closes [#19375](vitejs/vite#19375)
-   fix(deps): update all non-major dependencies ([#19392](vitejs/vite#19392)) ([60456a5](vitejs/vite@60456a5)), closes [#19392](vitejs/vite#19392)
-   fix(deps): update all non-major dependencies ([#19440](vitejs/vite#19440)) ([ccac73d](vitejs/vite@ccac73d)), closes [#19440](vitejs/vite#19440)
-   fix(html): ignore malformed src attrs ([#19397](vitejs/vite#19397)) ([aff7812](vitejs/vite@aff7812)), closes [#19397](vitejs/vite#19397)
-   fix(worker): fix web worker type detection ([#19462](vitejs/vite#19462)) ([edc65ea](vitejs/vite@edc65ea)), closes [#19462](vitejs/vite#19462)
-   refactor: remove custom .jxl mime ([#19457](vitejs/vite#19457)) ([0c85464](vitejs/vite@0c85464)), closes [#19457](vitejs/vite#19457)
-   feat: add support for injecting debug IDs ([#18763](vitejs/vite#18763)) ([0ff556a](vitejs/vite@0ff556a)), closes [#18763](vitejs/vite#18763)
-   chore: update 6.1.0 changelog ([#19363](vitejs/vite#19363)) ([fa7c211](vitejs/vite@fa7c211)), closes [#19363](vitejs/vite#19363)
renovate bot added a commit to andrei-picus-tink/auto-renovate that referenced this pull request Mar 9, 2025
| datasource | package | from  | to    |
| ---------- | ------- | ----- | ----- |
| npm        | vite    | 6.1.0 | 6.2.1 |


## [v6.2.1](https://github.com/vitejs/vite/blob/HEAD/packages/vite/CHANGELOG.md#small621-2025-03-07-small)

-   refactor: remove `isBuild` check from preAliasPlugin ([#19587](vitejs/vite#19587)) ([c9e086d](vitejs/vite@c9e086d)), closes [#19587](vitejs/vite#19587)
-   refactor: restore endsWith usage ([#19554](vitejs/vite#19554)) ([6113a96](vitejs/vite@6113a96)), closes [#19554](vitejs/vite#19554)
-   refactor: use `applyToEnvironment` in internal plugins ([#19588](vitejs/vite#19588)) ([f678442](vitejs/vite@f678442)), closes [#19588](vitejs/vite#19588)
-   fix(css): stabilize css module hashes with lightningcss in dev mode ([#19481](vitejs/vite#19481)) ([92125b4](vitejs/vite@92125b4)), closes [#19481](vitejs/vite#19481)
-   fix(deps): update all non-major dependencies ([#19555](vitejs/vite#19555)) ([f612e0f](vitejs/vite@f612e0f)), closes [#19555](vitejs/vite#19555)
-   fix(reporter): fix incorrect bundle size calculation with non-ASCII characters ([#19561](vitejs/vite#19561)) ([437c0ed](vitejs/vite@437c0ed)), closes [#19561](vitejs/vite#19561)
-   fix(sourcemap): combine sourcemaps with multiple sources without matched source ([#18971](vitejs/vite#18971)) ([e3f6ae1](vitejs/vite@e3f6ae1)), closes [#18971](vitejs/vite#18971)
-   fix(ssr): named export should overwrite export all ([#19534](vitejs/vite#19534)) ([2fd2fc1](vitejs/vite@2fd2fc1)), closes [#19534](vitejs/vite#19534)
-   feat: add `*?url&no-inline` type and warning for `.json?inline` / `.json?no-inline` ([#19566](vitejs/vite#19566)) ([c0d3667](vitejs/vite@c0d3667)), closes [#19566](vitejs/vite#19566)
-   test: add glob import test case ([#19516](vitejs/vite#19516)) ([aa1d807](vitejs/vite@aa1d807)), closes [#19516](vitejs/vite#19516)
-   test: convert config playground to unit tests ([#19568](vitejs/vite#19568)) ([c0e68da](vitejs/vite@c0e68da)), closes [#19568](vitejs/vite#19568)
-   test: convert resolve-config playground to unit tests ([#19567](vitejs/vite#19567)) ([db5fb48](vitejs/vite@db5fb48)), closes [#19567](vitejs/vite#19567)
-   perf: flush compile cache after 10s ([#19537](vitejs/vite#19537)) ([6c8a5a2](vitejs/vite@6c8a5a2)), closes [#19537](vitejs/vite#19537)
-   chore(css): move environment destructuring after condition check ([#19492](vitejs/vite#19492)) ([c9eda23](vitejs/vite@c9eda23)), closes [#19492](vitejs/vite#19492)
-   chore(html): remove unnecessary value check ([#19491](vitejs/vite#19491)) ([797959f](vitejs/vite@797959f)), closes [#19491](vitejs/vite#19491)


## [v6.2.0](https://github.com/vitejs/vite/blob/HEAD/packages/vite/CHANGELOG.md#620-2025-02-25)

-   fix(deps): update all non-major dependencies ([#19501](vitejs/vite#19501)) ([c94c9e0](vitejs/vite@c94c9e0)), closes [#19501](vitejs/vite#19501)
-   fix(worker): string interpolation in dynamic worker options ([#19476](vitejs/vite#19476)) ([07091a1](vitejs/vite@07091a1)), closes [#19476](vitejs/vite#19476)
-   chore: use unicode cross icon instead of x ([#19497](vitejs/vite#19497)) ([5c70296](vitejs/vite@5c70296)), closes [#19497](vitejs/vite#19497)


## [v6.1.1](https://github.com/vitejs/vite/blob/HEAD/packages/vite/CHANGELOG.md#small611-2025-02-19-small)

-   fix: ensure `.[cm]?[tj]sx?` static assets are JS mime ([#19453](vitejs/vite#19453)) ([e7ba55e](vitejs/vite@e7ba55e)), closes [#19453](vitejs/vite#19453)
-   fix: ignore `*.ipv4` address in cert ([#19416](vitejs/vite#19416)) ([973283b](vitejs/vite@973283b)), closes [#19416](vitejs/vite#19416)
-   fix(css): run rewrite plugin if postcss plugin exists ([#19371](vitejs/vite#19371)) ([bcdb51a](vitejs/vite@bcdb51a)), closes [#19371](vitejs/vite#19371)
-   fix(deps): bump tsconfck ([#19375](vitejs/vite#19375)) ([746a583](vitejs/vite@746a583)), closes [#19375](vitejs/vite#19375)
-   fix(deps): update all non-major dependencies ([#19392](vitejs/vite#19392)) ([60456a5](vitejs/vite@60456a5)), closes [#19392](vitejs/vite#19392)
-   fix(deps): update all non-major dependencies ([#19440](vitejs/vite#19440)) ([ccac73d](vitejs/vite@ccac73d)), closes [#19440](vitejs/vite#19440)
-   fix(html): ignore malformed src attrs ([#19397](vitejs/vite#19397)) ([aff7812](vitejs/vite@aff7812)), closes [#19397](vitejs/vite#19397)
-   fix(worker): fix web worker type detection ([#19462](vitejs/vite#19462)) ([edc65ea](vitejs/vite@edc65ea)), closes [#19462](vitejs/vite#19462)
-   refactor: remove custom .jxl mime ([#19457](vitejs/vite#19457)) ([0c85464](vitejs/vite@0c85464)), closes [#19457](vitejs/vite#19457)
-   feat: add support for injecting debug IDs ([#18763](vitejs/vite#18763)) ([0ff556a](vitejs/vite@0ff556a)), closes [#18763](vitejs/vite#18763)
-   chore: update 6.1.0 changelog ([#19363](vitejs/vite#19363)) ([fa7c211](vitejs/vite@fa7c211)), closes [#19363](vitejs/vite#19363)
@OnlyWick OnlyWick deleted the refactor-vite-2025-03-03 branch March 10, 2025 10:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
p1-chore Doesn't change code behavior (priority)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants