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

perf(reactivity): ports alien-signals #12349

Open
wants to merge 76 commits into
base: minor
Choose a base branch
from

Conversation

johnsoncodehk
Copy link
Member

@johnsoncodehk johnsoncodehk commented Nov 9, 2024

alien-signals(https://github.com/stackblitz/alien-signals) is a research-oriented signal library rewritten based on Vue 3.4's reactivity system. It sets several constraints to ensure the high-performance implementation of a reactivity system. (Currently, it is the fastest implementation among all signal libraries)

This PR ports the https://github.com/stackblitz/alien-signals/blob/master/src/system.ts code to https://github.com/vuejs/core/blob/main/packages/reactivity/src/effect.ts to leverage all the optimizations discovered by alien-signals.

Benefits

  • Lower memory usage: Memory usage is reduced by ~13% (2.3MB -> 2.0MB) when creating a large number of ref, computed, and effect instances.
  • Higher performance: Various performance tests now generally yield better results, especially in scenarios where a large number of computeds are read after changing a ref. Vue 3.5 had significant performance drawbacks in this case (a characteristic of pull-model reactivity systems, it can be reproduced in https://github.com/transitive-bullshit/js-reactivity-benchmark), and the current implementation resolves this issue, achieving over 30x performance improvement (proportional to scale).
  • Better code abstraction: The previous scheduling logic had coupling with external implementations (such as Dep cleanup, debug events, recurse effect handling). The current implementation eliminates these couplings.

Benchmark Results

computed

     name                                                                    hz     min     max    mean     p75     p99    p995    p999     rme  samples
   · create computed                                               6,111,709.97  0.0000  0.3307  0.0002  0.0002  0.0002  0.0002  0.0003  ±0.53%  3055856  [1.28x] ⇑
     create computed                                               4,790,560.55  0.0001  2.8602  0.0002  0.0002  0.0003  0.0003  0.0005  ±1.19%  2395281  (baseline)
   · write ref, don't read computed (without effect)               3,725,946.87  0.0002  0.1777  0.0003  0.0003  0.0003  0.0003  0.0004  ±0.16%  1862974  [1.19x] ⇑
     write ref, don't read computed (without effect)               3,138,437.74  0.0002  1.4873  0.0003  0.0003  0.0004  0.0004  0.0005  ±1.21%  1569219  (baseline)
   · write ref, don't read computed (with effect)                  1,629,737.97  0.0005  0.1867  0.0006  0.0006  0.0007  0.0007  0.0008  ±0.11%   814869  [1.20x] ⇑
     write ref, don't read computed (with effect)                  1,362,345.64  0.0006  0.1455  0.0007  0.0008  0.0008  0.0008  0.0010  ±0.13%   681173  (baseline)
   · write ref, read computed (without effect)                     1,961,824.76  0.0004  0.1808  0.0005  0.0005  0.0005  0.0006  0.0007  ±0.12%   980913  [1.06x] ⇑
     write ref, read computed (without effect)                     1,848,260.85  0.0004  0.1488  0.0005  0.0005  0.0006  0.0006  0.0007  ±0.13%   924131  (baseline)
   · write ref, read computed (with effect)                        1,475,801.43  0.0005  0.2211  0.0007  0.0007  0.0008  0.0008  0.0010  ±0.12%   737901  [1.14x] ⇑
     write ref, read computed (with effect)                        1,296,434.21  0.0007  0.2508  0.0008  0.0008  0.0008  0.0009  0.0011  ±0.16%   648218  (baseline)
   · write ref, don't read 1000 computeds (without effect)         3,300,382.44  0.0002  0.1930  0.0003  0.0003  0.0003  0.0004  0.0004  ±0.14%  1650192  [1.03x] ⇑
     write ref, don't read 1000 computeds (without effect)         3,189,502.88  0.0002  0.1763  0.0003  0.0003  0.0003  0.0004  0.0005  ±0.14%  1594752  (baseline)
   · write ref, don't read 1000 computeds (with multiple effects)      3,222.67  0.3063  0.5532  0.3103  0.3108  0.3488  0.3917  0.5250  ±0.19%     1612  [1.38x] ⇑
     write ref, don't read 1000 computeds (with multiple effects)      2,329.65  0.4206  0.6286  0.4292  0.4292  0.4997  0.5215  0.5671  ±0.19%     1165  (baseline)
   · write ref, don't read 1000 computeds (with single effect)         3,734.95  0.2648  0.3821  0.2677  0.2683  0.2855  0.2986  0.3510  ±0.09%     1868  [1.71x] ⇑
     write ref, don't read 1000 computeds (with single effect)         2,186.19  0.4434  0.6528  0.4574  0.4565  0.5061  0.5221  0.5846  ±0.16%     1094  (baseline)
   · write ref, read 1000 computeds (no effect)                        4,694.97  0.2105  0.3849  0.2130  0.2142  0.2301  0.2382  0.3271  ±0.12%     2348  [1.26x] ⇑
     write ref, read 1000 computeds (no effect)                        3,718.71  0.2292  9.4632  0.2689  0.2329  1.0790  2.5163  6.3315  ±5.98%     1860  (baseline)
   · write ref, read 1000 computeds (with multiple effects)            2,845.64  0.3453  0.6213  0.3514  0.3512  0.4014  0.4358  0.5546  ±0.21%     1423  [1.33x] ⇑
     write ref, read 1000 computeds (with multiple effects)            2,142.70  0.4569  0.7351  0.4667  0.4664  0.5183  0.5565  0.6951  ±0.22%     1072  (baseline)
   · write ref, read 1000 computeds (with single effect)               2,265.62  0.4338  0.9382  0.4414  0.4392  0.5991  0.6087  0.6304  ±0.36%     1133  [1.48x] ⇑
     write ref, read 1000 computeds (with single effect)               1,529.78  0.6415  0.8937  0.6537  0.6526  0.7195  0.7378  0.8937  ±0.18%      765  (baseline)
   · 1000 refs, read 1 computed (without effect)                      19,686.23  0.0490  0.1665  0.0508  0.0495  0.0595  0.0631  0.0935  ±0.16%     9844  [3.41x] ⇑
     1000 refs, read 1 computed (without effect)                       5,775.97  0.1611  0.3445  0.1731  0.1746  0.2057  0.2170  0.2689  ±0.18%     2888  (baseline)
   · 1000 refs, read 1 computed (with effect)                         22,764.26  0.0427  0.1713  0.0439  0.0430  0.0534  0.0585  0.0983  ±0.16%    11383  [3.63x] ⇑
     1000 refs, read 1 computed (with effect)                          6,268.22  0.1492  0.3157  0.1595  0.1620  0.1907  0.2024  0.2408  ±0.18%     3135  (baseline)

effect

     name                                                       hz      min      max     mean      p75      p99     p995     p999     rme  samples
   · single ref invoke                                2,422,374.37   0.0003   0.1300   0.0004   0.0004   0.0005   0.0005   0.0006  ±0.12%  1211188  [1.08x] ⇑
     single ref invoke                                2,253,296.36   0.0003   0.1473   0.0004   0.0005   0.0005   0.0005   0.0006  ±0.15%  1126649  (baseline)
   · create an effect that tracks 1 refs              3,041,716.41   0.0002   0.2316   0.0003   0.0003   0.0004   0.0005   0.0006  ±0.39%  1520859  [1.32x] ⇑
     create an effect that tracks 1 refs              2,305,307.54   0.0003   0.1655   0.0004   0.0004   0.0005   0.0005   0.0008  ±0.32%  1152654  (baseline)
   · create an effect that tracks 10 refs               477,709.54   0.0019   0.2655   0.0021   0.0021   0.0023   0.0025   0.0036  ±0.38%   238855  [1.57x] ⇑
     create an effect that tracks 10 refs               303,939.27   0.0031   0.2318   0.0033   0.0032   0.0035   0.0037   0.0183  ±0.34%   151970  (baseline)
   · create an effect that tracks 100 refs               51,529.46   0.0188   0.2940   0.0194   0.0190   0.0267   0.0342   0.1052  ±0.38%    25765  [1.62x] ⇑
     create an effect that tracks 100 refs               31,753.65   0.0306   0.2372   0.0315   0.0309   0.0464   0.0528   0.1848  ±0.34%    15877  (baseline)
   · create an effect that tracks 1000 refs               5,185.44   0.1884   0.4357   0.1928   0.1896   0.3253   0.3712   0.4210  ±0.41%     2593  [1.65x] ⇑
     create an effect that tracks 1000 refs               3,135.25   0.3067   1.2006   0.3190   0.3107   0.5374   0.7059   1.1851  ±0.83%     1568  (baseline)
   · create and stop an effect that tracks 1 refs     2,643,923.29   0.0003   0.2466   0.0004   0.0004   0.0005   0.0006   0.0008  ±0.40%  1321998  [1.25x] ⇑
     create and stop an effect that tracks 1 refs     2,108,885.94   0.0003   0.1770   0.0005   0.0005   0.0005   0.0006   0.0008  ±0.35%  1054443  (baseline)
   · create and stop an effect that tracks 10 refs      434,027.52   0.0022   0.2420   0.0023   0.0023   0.0024   0.0026   0.0038  ±0.28%   217014  [1.59x] ⇑
     create and stop an effect that tracks 10 refs      272,235.14   0.0035   0.3079   0.0037   0.0036   0.0040   0.0041   0.0193  ±0.36%   136118  (baseline)
   · create and stop an effect that tracks 100 refs      46,683.59   0.0209   0.2881   0.0214   0.0212   0.0246   0.0315   0.0809  ±0.33%    23342  [1.66x] ⇑
     create and stop an effect that tracks 100 refs      28,075.59   0.0343   3.7334   0.0356   0.0348   0.0508   0.0602   0.1706  ±1.48%    14038  (baseline)
   · create and stop an effect that tracks 1000 refs      4,674.21   0.2099   0.5031   0.2139   0.2114   0.2932   0.3995   0.4782  ±0.38%     2338  [1.65x] ⇑
     create and stop an effect that tracks 1000 refs      2,829.92   0.3445   0.5768   0.3534   0.3499   0.4938   0.5118   0.5708  ±0.34%     1415  (baseline)
   · 1 effect, mutate 10 refs                           131,308.76   0.0074   0.2790   0.0076   0.0076   0.0079   0.0081   0.0197  ±0.15%    65655  [2.37x] ⇑
     1 effect, mutate 10 refs                            55,475.14   0.0177   0.1079   0.0180   0.0179   0.0215   0.0318   0.0527  ±0.14%    27738  (baseline)
   · 1 effect, mutate 100 refs                            2,163.50   0.4568   0.8003   0.4622   0.4609   0.5471   0.6069   0.7550  ±0.26%     1082  [3.27x] ⇑
     1 effect, mutate 100 refs                              660.75   1.4944   1.8873   1.5134   1.5197   1.6387   1.7310   1.8873  ±0.24%      331  (baseline)
   · 1 effect, mutate 1000 refs                            23.1906  42.8559  43.6757  43.1209  43.1839  43.6757  43.6757  43.6757  ±0.39%       12  [3.47x] ⇑
     1 effect, mutate 1000 refs                             6.6868   149.16   149.78   149.55   149.71   149.78   149.78   149.78  ±0.10%       10  (baseline)
   · 10 refs branch toggle                            1,186,713.31   0.0004   6.0071   0.0008   0.0010   0.0011   0.0014   0.0015  ±4.92%   593357  [1.75x] ⇑
     10 refs branch toggle                              678,007.23   0.0007   0.2123   0.0015   0.0022   0.0022   0.0023   0.0049  ±0.23%   339004  (baseline)
   · 100 refs branch toggle                             303,335.02   0.0009   0.1054   0.0033   0.0055   0.0057   0.0057   0.0110  ±0.37%   151669  [3.03x] ⇑
     100 refs branch toggle                              99,958.91   0.0029   1.4980   0.0100   0.0166   0.0173   0.0242   0.0396  ±0.88%    49981  (baseline)
   · 1000 refs branch toggle                             33,959.34   0.0069   0.1933   0.0294   0.0513   0.0547   0.0595   0.0819  ±1.14%    16981  [3.26x] ⇑
     1000 refs branch toggle                             10,416.41   0.0265   0.4061   0.0960   0.1623   0.1861   0.2043   0.3517  ±1.97%     5209  (baseline)
   · 1 ref invoking 10 effects                          946,141.80   0.0009   0.0576   0.0011   0.0011   0.0011   0.0012   0.0014  ±0.08%   473071  [1.53x] ⇑
     1 ref invoking 10 effects                          617,154.17   0.0013   2.1592   0.0016   0.0014   0.0020   0.0020   0.0193  ±2.15%   308578  (baseline)
   · 1 ref invoking 100 effects                         137,515.93   0.0069   0.1466   0.0073   0.0073   0.0075   0.0078   0.0228  ±0.13%    68758  [1.51x] ⇑
     1 ref invoking 100 effects                          91,193.89   0.0105   0.2659   0.0110   0.0110   0.0114   0.0187   0.0313  ±0.16%    45597  (baseline)
   · 1 ref invoking 1000 effects                         13,791.02   0.0704   0.1650   0.0725   0.0727   0.0858   0.0947   0.1325  ±0.13%     6896  [1.48x] ⇑
     1 ref invoking 1000 effects                          9,339.78   0.1047   0.1980   0.1071   0.1069   0.1265   0.1379   0.1740  ±0.13%     4670  (baseline)

ref

     name                       hz     min     max    mean     p75     p99    p995    p999     rme  samples
   · create ref       4,648,340.74  0.0001  1.8655  0.0002  0.0002  0.0003  0.0003  0.0004  ±0.89%  2324171  [1.09x] ⇑
     create ref       4,261,204.35  0.0001  0.1899  0.0002  0.0003  0.0003  0.0003  0.0005  ±0.15%  2130603  (baseline)
   · write ref        3,817,925.50  0.0002  0.1143  0.0003  0.0003  0.0003  0.0003  0.0004  ±0.08%  1908963  [1.18x] ⇑
     write ref        3,248,551.04  0.0002  0.2231  0.0003  0.0003  0.0003  0.0004  0.0005  ±0.16%  1624276  (baseline)
   · read ref        11,485,907.61  0.0000  0.1316  0.0001  0.0001  0.0001  0.0001  0.0002  ±0.13%  5742954  [1.02x] ⇑
     read ref        11,264,635.57  0.0000  0.1458  0.0001  0.0001  0.0001  0.0001  0.0002  ±0.18%  5632318  (baseline)
   · write/read ref   3,576,071.66  0.0002  0.2868  0.0003  0.0003  0.0003  0.0003  0.0004  ±0.12%  1788036  [1.33x] ⇑
     write/read ref   2,694,391.71  0.0002  1.0205  0.0004  0.0004  0.0004  0.0005  0.0008  ±0.94%  1347196  (baseline)

Potential Improvements

  • Merging dirtyLevel, canPropagate, pauseLevel, and allowRecurse into one attribute should further reduce memory usage. Reaching the lowest memory usage is not the purpose of this PR, so we will not implement it here currently.

Copy link

github-actions bot commented Nov 9, 2024

Size Report

Bundles

File Size Gzip Brotli
runtime-dom.global.prod.js 101 kB (+733 B) 38 kB (+46 B) 34.2 kB (+23 B)
vue.global.prod.js 159 kB (+730 B) 57.8 kB (+55 B) 51.5 kB (+48 B)

Usages

Name Size Gzip Brotli
createApp (CAPI only) 47.3 kB (+155 B) 18.3 kB (-23 B) 16.7 kB (-23 B)
createApp 55.7 kB (+519 B) 21.4 kB (+54 B) 19.5 kB (+44 B)
createSSRApp 59.8 kB (+519 B) 23.1 kB (+40 B) 21 kB (+55 B)
defineCustomElement 60.6 kB (+517 B) 23 kB (+45 B) 20.9 kB (+62 B)
overall 69.8 kB (+703 B) 26.5 kB (+62 B) 24.1 kB (+65 B)

Copy link

pkg-pr-new bot commented Nov 9, 2024

Open in Stackblitz

@vue/compiler-core

pnpm add https://pkg.pr.new/@vue/compiler-core@12349

@vue/compiler-dom

pnpm add https://pkg.pr.new/@vue/compiler-dom@12349

@vue/compiler-ssr

pnpm add https://pkg.pr.new/@vue/compiler-ssr@12349

@vue/compiler-sfc

pnpm add https://pkg.pr.new/@vue/compiler-sfc@12349

@vue/reactivity

pnpm add https://pkg.pr.new/@vue/reactivity@12349

@vue/runtime-core

pnpm add https://pkg.pr.new/@vue/runtime-core@12349

@vue/runtime-dom

pnpm add https://pkg.pr.new/@vue/runtime-dom@12349

@vue/server-renderer

pnpm add https://pkg.pr.new/@vue/server-renderer@12349

@vue/shared

pnpm add https://pkg.pr.new/@vue/shared@12349

vue

pnpm add https://pkg.pr.new/vue@12349

@vue/compat

pnpm add https://pkg.pr.new/@vue/compat@12349

commit: 5cafdba

Copy link

netlify bot commented Nov 10, 2024

Deploy Preview for vue-sfc-playground failed. Why did it fail? →

Name Link
🔨 Latest commit dffd270
🔍 Latest deploy log https://app.netlify.com/sites/vue-sfc-playground/deploys/6730c65868d1a20008fed7ba

@johnsoncodehk
Copy link
Member Author

/ecosystem-ci run

@johnsoncodehk
Copy link
Member Author

A GC regression that computed not used in effect/template cannot be released is fixed in 4114a12 (#12349) (Thanks for @JoviDeCroock bringing it up!)

@JoviDeCroock
Copy link

@johnsoncodehk this leak is present in alien-signals itself, might be worth tackling there as well for all other consumers of the package.

@johnsoncodehk
Copy link
Member Author

@JoviDeCroock Yep! This is the last problem we want to solve in alien-signals.

@johnsoncodehk johnsoncodehk changed the title perf(reactivity): ports alien-signals system perf(reactivity): ports alien-signals Nov 13, 2024
@yyx990803
Copy link
Member

Removed namespace usage in 571ba05

Previously namespace was used because it somehow showed better perf in benchmarks, but turns out it's because Vitest benchmark currently has overhead for every access of cross-module import binding due to the way modules are evaluated.

For real-world performance, we should be benching against the bundled reactivity module, where module-root level exports are scope-hoisted into local consts. This should result in better perf than namespace access. It also is more minifier friendly and can reduce bundle size increase.

Comparing the benchmark using bundled reactivity.esm-browser.prod.js, before and after 571ba05:

· create computed                                               21,076,617.75  0.0000  0.2428  0.0000  0.0000  0.0001  0.0001  0.0002  ±0.16%  10538309  [1.01x] ⇑
     create computed                                               20,871,461.37  0.0000  0.0939  0.0000  0.0000  0.0001  0.0001  0.0002  ±0.14%  10435731  (baseline)
   · write ref, don't read computed (without effect)               21,270,929.83  0.0000  0.2626  0.0000  0.0000  0.0001  0.0001  0.0002  ±0.22%  10635465  [1.00x] ⇓
     write ref, don't read computed (without effect)               21,352,721.02  0.0000  0.3770  0.0000  0.0000  0.0001  0.0001  0.0001  ±0.28%  10676361  (baseline)
   · write ref, don't read computed (with effect)                  10,561,843.24  0.0000  0.4995  0.0001  0.0001  0.0001  0.0001  0.0002  ±0.29%   5280922  [1.03x] ⇑
     write ref, don't read computed (with effect)                  10,295,067.44  0.0000  0.7905  0.0001  0.0001  0.0001  0.0002  0.0002  ±0.44%   5147534  (baseline)
   · write ref, read computed (without effect)                     13,647,038.01  0.0000  0.2687  0.0001  0.0001  0.0001  0.0001  0.0002  ±0.20%   6823520  [1.01x] ⇑
     write ref, read computed (without effect)                     13,446,011.73  0.0000  0.1222  0.0001  0.0001  0.0001  0.0001  0.0002  ±0.13%   6723006  (baseline)
   · write ref, read computed (with effect)                         9,900,825.62  0.0000  0.2127  0.0001  0.0001  0.0002  0.0002  0.0002  ±0.19%   4950413  [0.98x] ⇓
     write ref, read computed (with effect)                        10,072,543.62  0.0000  0.3119  0.0001  0.0001  0.0001  0.0002  0.0002  ±0.26%   5036273  (baseline)
   · write ref, don't read 1000 computeds (without effect)         20,749,339.38  0.0000  0.4546  0.0000  0.0000  0.0001  0.0001  0.0001  ±0.32%  10374670  [1.00x] ⇑
     write ref, don't read 1000 computeds (without effect)         20,652,327.46  0.0000  0.5293  0.0000  0.0000  0.0001  0.0001  0.0002  ±0.43%  10326164  (baseline)
   · write ref, don't read 1000 computeds (with multiple effects)       8,481.89  0.1150  0.1683  0.1179  0.1190  0.1273  0.1297  0.1494  ±0.08%      4241  [1.08x] ⇑
     write ref, don't read 1000 computeds (with multiple effects)       7,889.51  0.1205  0.1841  0.1268  0.1285  0.1488  0.1511  0.1676  ±0.14%      3945  (baseline)
   · write ref, don't read 1000 computeds (with single effect)         30,897.47  0.0312  0.0958  0.0324  0.0322  0.0406  0.0438  0.0481  ±0.08%     15449  [1.05x] ⇑
     write ref, don't read 1000 computeds (with single effect)         29,380.96  0.0329  0.0605  0.0340  0.0343  0.0378  0.0391  0.0428  ±0.04%     14691  (baseline)
   · write ref, read 1000 computeds (no effect)                        43,131.23  0.0224  0.0852  0.0232  0.0231  0.0297  0.0318  0.0360  ±0.08%     21566  [1.05x] ⇑
     write ref, read 1000 computeds (no effect)                        40,964.36  0.0235  0.0829  0.0244  0.0243  0.0318  0.0335  0.0373  ±0.08%     20483  (baseline)
   · write ref, read 1000 computeds (with multiple effects)             8,546.06  0.1138  0.1759  0.1170  0.1184  0.1287  0.1308  0.1385  ±0.08%      4274  [1.11x] ⇑
     write ref, read 1000 computeds (with multiple effects)             7,727.43  0.1265  0.1966  0.1294  0.1310  0.1427  0.1450  0.1506  ±0.09%      3864  (baseline)
   · write ref, read 1000 computeds (with single effect)               15,886.90  0.0589  0.2281  0.0629  0.0621  0.0745  0.0818  0.2199  ±0.30%      7944  [1.02x] ⇑
     write ref, read 1000 computeds (with single effect)               15,539.78  0.0616  0.1318  0.0644  0.0637  0.0760  0.0765  0.0803  ±0.09%      7770  (baseline)
   · 1000 refs, read 1 computed (without effect)                      163,839.85  0.0054  0.1293  0.0061  0.0070  0.0075  0.0086  0.0108  ±0.10%     81920  [1.04x] ⇑
     1000 refs, read 1 computed (without effect)                      157,879.98  0.0055  0.0657  0.0063  0.0073  0.0091  0.0107  0.0163  ±0.11%     78941  (baseline)
   · 1000 refs, read 1 computed (with effect)                         186,830.01  0.0051  0.0250  0.0054  0.0054  0.0060  0.0067  0.0085  ±0.03%     93416  [1.03x] ⇑
     1000 refs, read 1 computed (with effect)                         180,595.90  0.0052  0.0614  0.0055  0.0055  0.0068  0.0093  0.0151  ±0.08%     90298  (baseline)

@yyx990803 yyx990803 mentioned this pull request Nov 14, 2024
6 tasks
@yyx990803 yyx990803 changed the base branch from main to minor November 14, 2024 00:14
@johnsoncodehk
Copy link
Member Author

/ecosystem-ci run

@vue-bot
Copy link
Contributor

vue-bot commented Nov 17, 2024

📝 Ran ecosystem CI: Open

suite result latest scheduled
language-tools success success
nuxt success success
pinia success success
primevue success success
quasar success success
radix-vue success success
router success success
test-utils success success
vant success success
vite-plugin-vue success success
vitepress success success
vue-i18n success success
vue-macros success success
vuetify success success
vueuse success success
vue-simple-compiler success success

@johnsoncodehk johnsoncodehk changed the base branch from minor to main November 17, 2024 14:13
@johnsoncodehk johnsoncodehk changed the base branch from main to minor November 17, 2024 14:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants