vanilla-extract-css / vanilla-extract

Zero-runtime Stylesheets-in-TypeScript
https://vanilla-extract.style
MIT License
9.51k stars 288 forks source link

Slow compilation time in Apple M1 #1126

Open samithaf opened 1 year ago

samithaf commented 1 year ago

Describe the bug

It looks like @vanilla-extract/next-plugin is extremely slow on Apple M1 + Next.js latest Apps.

I saw this issue describing the same problem but it's now closed. Is there any plan to fix the performance issue?

Reproduction

.

System Info

System:
    OS: macOS 13.4
    CPU: (10) arm64 Apple M1 Max
    Memory: 6.83 GB / 32.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 18.3.0 - ~/.nvm/versions/node/v18.3.0/bin/node
    Yarn: 1.22.19 - ~/.nvm/versions/node/v18.3.0/bin/yarn
    npm: 8.11.0 - ~/.nvm/versions/node/v18.3.0/bin/npm
    pnpm: 8.3.1 - ~/.homebrew/bin/pnpm
  Browsers:
    Chrome: 114.0.5735.198
    Edge: 114.0.1823.58
    Safari: 16.5

Used Package Manager

pnpm

Logs

No response

Validations

askoufis commented 1 year ago

@samithaf Thanks for opening this issue.

The issue you mentioned was closed because this PR improved the performance of the code that was causing the issue. If you have found another performance issue, please provide a reproduction so we can diagnose it.

AlexGalays commented 11 months ago

I revisited this issue while trying to upgrade to vite 4.5, which makes this perf problem even more visible. It's still an issue for us, on both M1 and M2.

Chip: Apple M1 Pro
      Total Number of Cores: 10 (8 performance and 2 efficiency)
      Memory: 16 GB
      System Firmware Version: 8422.121.1
      OS Loader Version: 8422.121.1

Chrome Version 117.0.5938.149 (Official Build) (arm64)

vite: 4.5
yarn 3.6.3 with PnP 
@vanilla-extract/vite-plugin: 3.9.0
@vanilla-extract/css: 1.13.0
@vanilla-extract/sprinkles: 1.6.1

vite-build finishes reasonably fast (40s); it's purely a dev mode issue. Our app has like 700 modules and it starts to choke early on vanilla-extract heavy modules and it only gets worse over time. The cold load doesn't even finish in 10 minutes (might as well be infinite given how starved it looks) and I always have to kill node which sits at 100% cpu.

Node profile: vite-profile-0.cpuprofile

You can see most of the time is spent searching classNames with AhoCorasick; localClassnames.length is around 14000 but it's called so many times.

AlexGalays commented 10 months ago

Any news at all? Any pointer to help someone fix this in a PR?

A bit more info: Out of those 14,000 classNames, the majority comes from sprinkles. Indeed we have 54 colors, 9 color properties and 22 color selectors = 10,692 classNames; we of course have many other non color related classNames.

Since the sprinkles set of classNames is pretty much a static, known set at compilation time, what do you think about creating a Set with all sprinkles classNames, building a new AhoCorasick for just that set, a single time then append these results with any local Stylesheet search results?

askoufis commented 10 months ago

Any news at all? Any pointer to help someone fix this in a PR?

A bit more info: Out of those 14,000 classNames, the majority comes from sprinkles. Indeed we have 54 colors, 9 color properties and 22 color selectors = 10,692 classNames; we of course have many other non color related classNames.

Since the sprinkles set of classNames is pretty much a static, known set at compilation time, what do you think about creating a Set with all sprinkles classNames, building a new AhoCorasick for just that set, a single time then append these results with any local Stylesheet search results?

Sorry for taking a while to respond. I think the issue is to do with how Vanilla Extract transforms CSS. We transform every .css.ts file to get the resulting CSS, but we don't cache the result in the vite plugin, so every import of a sprinkles file requires a new AhoCorasick call. I think the way vite loads files in dev mode causes a bottleneck where every sprinkles file transform has to be resolved before your app can load.

This is exacerbated by the large amount of sprinkles classnames you're generating, so the first thing I'd suggest would be to re-evaluate what you expose in your sprinkles function. Does every property need to be conditional across all your selectors? Can some of these just be static styles?

The good news is that I think our experimental vite-node-based compiler (currently only used in @vanilla-extract/esbuild-plugin-next) is smarter about caching transformed CSS, so it might alleviate the issue. We haven't gotten around to putting the new compiler into other bundler plugins, but now might be a good time to do so.

There's also potentially some room to speed up the AhoCorasick implementation.

I'll report back if there's any movement on either of these fronts.

askoufis commented 10 months ago

@samithaf I would appreciate some kind of reproduction of your issue. I'm unsure if this is related only to NextJS/vite/both bundlers.

supernaut commented 9 months ago

This makes Vanilla extract practically unusable on Apple silicon at the moment. In my current project dev mode takes over 7 minutes cold, if it even starts. This on a M1 Max with 64GB RAM. Same code runs in 9 seconds on a colleagues Intel based old Mac.

EDIT: Nevermind, same slow speed on Intel based Mac in my branch. Every condition seems to add a lot of time.