Skip to content

Conversation

@quantizor
Copy link
Contributor

@quantizor quantizor commented Mar 16, 2025

Claude and I jammed on some potential improvements...

base base - best of 3
adjusted, size 500 cache 500 - best of 3

Rationale for increasing cache size is the partials it's storing are quite small and a medium-complexity website may have thousands of them. They probably won't take up much space even in volume.

Roughly a 9% improvement in the cached example and 11% overall in the heavy case.

@github-actions github-actions bot added the context-v3 Related to tailwind-merge v3 label Mar 16, 2025
@dcastil
Copy link
Owner

dcastil commented Mar 21, 2025

Hey @quantizor, thanks for optimizing the runtime!

Just took a brief look at the diff and I think it would be good to split this into multiple PRs so I can verify some changes in isolation. If you're up to it, I'll review your changes in more detail tomorrow, probably leave a bunch of comments and let you know how to best split it up.

@quantizor
Copy link
Contributor Author

Hey @quantizor, thanks for optimizing the runtime!

Just took a brief look at the diff and I think it would be good to split this into multiple PRs so I can verify some changes in isolation. If you're up to it, I'll review your changes in more detail tomorrow, probably leave a bunch of comments and let you know how to best split it up.

Sure thing!

Copy link
Owner

@dcastil dcastil left a comment

Choose a reason for hiding this comment

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

Cool stuff! I added some comments around some details. At the scale of tailwind-merge it makes sense to pay attention to every small thing to not introduce potential regressions.

@quantizor quantizor mentioned this pull request Sep 1, 2025
@quantizor
Copy link
Contributor Author

@dcastil updated per your suggestions

@quantizor quantizor requested a review from dcastil September 1, 2025 03:46
Copy link
Owner

@dcastil dcastil left a comment

Choose a reason for hiding this comment

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

Hey @quantizor, thanks for the really long wait!

Thanks for addressing all the comments. I added a few commits fixing some minor things as well, hope you don't mind.

I checked everything and it looks good, I could also verify the speed improvements. 👍 There is just one thing in sort-modifiers.ts we should address before merging (#547 (comment)). Could you take a look at it?

After addressing it I consider this to be ready for merge. 🙂

@quantizor
Copy link
Contributor Author

Bench results after tweaks:

OLD

 ✓ tests/tw-merge.benchmark.ts > twMerge 3061ms
     name                            hz     min      max     mean      p75      p99     p995     p999     rme  samples
   · init                      4,210.32  0.2087   2.7886   0.2375   0.2364   0.5238   0.5781   0.9083  ±1.45%     2106
   · simple                    4,499.52  0.2101   0.5602   0.2222   0.2208   0.3823   0.3990   0.4524  ±0.54%     2250   fastest
   · heavy                     4,086.20  0.2217   2.6981   0.2447   0.2420   0.4962   0.5524   0.6520  ±1.25%     2044
   · collection with cache       608.18  1.4067   7.9597   1.6442   1.5477   5.7333   7.4706   7.9597  ±4.68%      305
   · collection without cache   98.5241  9.5441  10.7708  10.1498  10.4183  10.7708  10.7708  10.7708  ±0.93%       50   slowest

NEW

 ✓ tests/tw-merge.benchmark.ts > twMerge 3054ms
     name                            hz     min      max    mean     p75      p99     p995     p999     rme  samples
   · init                      4,620.76  0.1933   1.3782  0.2164  0.2208   0.3966   0.5028   1.0336  ±1.04%     2311
   · simple                    4,840.87  0.1938   0.5355  0.2066  0.2077   0.3755   0.3942   0.4328  ±0.48%     2421   fastest
   · heavy                     4,616.99  0.2045   0.4501  0.2166  0.2178   0.3655   0.3987   0.4243  ±0.43%     2309
   · collection with cache       724.81  1.2980   3.5978  1.3797  1.3907   1.7990   2.0750   3.5978  ±1.09%      363
   · collection without cache    103.79  8.9342  19.0420  9.6348  9.5288  19.0420  19.0420  19.0420  ±4.38%       52   slowest

@quantizor
Copy link
Contributor Author

quantizor commented Oct 29, 2025

Best of 3 with memory info from #620

main branch

Memory Usage Summary:
  init: 1.57 MB heap
  simple: 1016.39 KB heap
  heavy: 1.01 MB heap
  collection with cache: 2.52 MB heap
    Total footprint: 234.75 MB
    Operations: 1322
  collection without cache: 16.99 MB heap
    Total footprint: 235.13 MB
    Operations: 1322


 ✓ tests/tw-merge.benchmark.ts > twMerge 3136ms
     name                            hz     min      max    mean     p75      p99     p995     p999     rme  samples
   · init                      4,065.35  0.2175   1.8490  0.2460  0.2450   0.4969   0.5517   0.8136  ±1.12%     2033
   · simple                    4,062.11  0.2270   0.7383  0.2462  0.2448   0.4628   0.4756   0.5714  ±0.70%     2032
   · heavy                     3,837.87  0.2374   2.3023  0.2606  0.2597   0.4791   0.5047   0.8659  ±1.06%     1919
   · collection with cache       688.97  1.3773   2.2432  1.4514  1.4654   1.7979   1.9276   2.2432  ±0.68%      345
   · collection without cache    109.09  8.8340  10.2709  9.1664  9.2940  10.2709  10.2709  10.2709  ±0.73%       55

perf branch

Memory Usage Summary:
  init: 1.22 MB heap
  simple: 838.82 KB heap
  heavy: 647.81 KB heap
  collection with cache: 1.79 MB heap
    Total footprint: 171.70 MB
    Operations: 1322
  collection without cache: 13.72 MB heap
    Total footprint: 238.06 MB
    Operations: 1322


 ✓ tests/tw-merge.benchmark.ts > twMerge 3130ms
     name                            hz     min      max    mean     p75      p99     p995     p999     rme  samples
   · init                      4,581.74  0.1975   1.3568  0.2183  0.2220   0.3657   0.4523   0.6930  ±0.89%     2291
   · simple                    4,396.86  0.2133   0.5638  0.2274  0.2274   0.4307   0.4576   0.5137  ±0.55%     2199
   · heavy                     4,182.74  0.2232   0.5723  0.2391  0.2393   0.4502   0.4675   0.5242  ±0.58%     2092
   · collection with cache       724.98  1.3007   3.3782  1.3793  1.4092   1.6660   2.2602   3.3782  ±1.02%      363
   · collection without cache    110.72  8.6614  10.1187  9.0318  9.2184  10.1187  10.1187  10.1187  ±1.10%       56

@codspeed-hq
Copy link

codspeed-hq bot commented Nov 2, 2025

CodSpeed Performance Report

Merging #547 will improve performances by 19.21%

Comparing quantizor:perf (16f0482) with main (db06f11)

Summary

⚡ 4 improvements
✅ 1 untouched

Benchmarks breakdown

Benchmark BASE HEAD Change
collection with cache 19.2 ms 17.2 ms +11.56%
heavy 5 ms 4.2 ms +18.89%
init 5.7 ms 5 ms +13.45%
simple 4.7 ms 3.9 ms +19.21%

@dcastil
Copy link
Owner

dcastil commented Nov 2, 2025

Just noting here:

Size of total ESM bundle increased from 6.68 kB to 6.96 kB minified + Brotli-compressed which is a 4.2% increase. I think this is fine for the 10-20% perf boost.

Copy link
Owner

@dcastil dcastil left a comment

Choose a reason for hiding this comment

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

LGTM. Great work, thanks!

@dcastil dcastil merged commit 660b993 into dcastil:main Nov 2, 2025
5 checks passed
@dcastil dcastil added the feature Is new feature label Nov 2, 2025
@github-actions
Copy link

github-actions bot commented Nov 9, 2025

This was addressed in release v3.4.0.

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

Labels

context-v3 Related to tailwind-merge v3 feature Is new feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants