chore(repo): add perf numbers to the turbo guide
This commit is contained in:
parent
2b04794a89
commit
2867c596f6
@ -10,7 +10,7 @@ This document was written on December 14, 2021. At this point Turborepo has just
|
||||
|
||||
We clearly separate Nx (the open source tool) and [Nx Cloud](https://nx.app) (the SAAS product). Turborepo doesn’t have such a separation. Hence, in this guide we compare Turborepo with Nx+Nx Cloud (so it’s apples to apples). That said, you don’t have to use Nx Cloud to get features such as distributed caching and distributed task execution. We provide public APIs so you can build your own, if you'd prefer not to use Nx Cloud.
|
||||
|
||||
We are going to compare the tools in three different ways: **features**, **tech**, and **community**.
|
||||
We are going to compare the tools in three different ways: **features**, **tech and performance**, and **community**.
|
||||
|
||||
## Features
|
||||
|
||||
@ -117,13 +117,22 @@ Nx doesn’t replace any of your tools, and it’s not “all in”. You can sta
|
||||
|
||||
Read [this guide](https://nx.dev/l/r/getting-started/nx-core) to learn more about how to only use Nx Core.
|
||||
|
||||
## Tech
|
||||
## Tech and Performance
|
||||
|
||||
Turborepo is mostly written in Golang. Nx is mostly written in TypeScript, but most of the heavy computation in Nx is done by core Node.js capabilities and node modules written in C++, so performance isn’t affected by this.
|
||||
|
||||
The one advantage the Go implementation has, is that any time you run an Nx command you pay a ~150ms penalty to boot Node.js. If you test 1 project, you pay a 150ms penalty, if you test 1000 projects, it is still a 150ms penalty. We don’t think in practice it matters because most other CLIs (e.g,. yarn) have the same penalty. The real performance gains from both Nx and Turborepo are in how intelligently they reduce, cache, and in Nx's case, distribute tasks.
|
||||
Benchmarking is hard because a lot depends on what you are trying to run, in what environment, etc. This is one benchmark we use when measuring Nx perf: [Nx and Turbo benchmark](https://github.com/vsavkin/large-monorepo/). It is a repo with 5 Next.js apps. We are measuring how quickly Nx and Turbo can figure out what needs to be restored from cache, and how quickly they can do it.
|
||||
|
||||
Benchmarking things, in general, is tricky, so we aren’t making claims that Nx is categorically faster. Based on our measurements, distributed task execution and optimizations in restoring files make Nx significantly faster for real-world scenarios, but you should do your own measurements because a lot of it is project specific.
|
||||
This is the result:
|
||||

|
||||
|
||||
Nx is 5 times faster on the latest MBP. Nx is 7.5 times faster on a Windows laptop.
|
||||
|
||||
Why is it faster? Nx is in many ways akin to React in that it's doing tree diffing when restoring files from the cache. If the right files are in the right place, Nx won't touch them. Turbo blows everything away every time. Nx's version isn't just faster, it's also more useful (again similarly to tree diffing in React). Blowing everything away on every restoration means that if any tools watch the folders (which is common when you build large apps or build microfrontends), they are going to get confused or triggered for no reason. This is similar to how recreating the DOM from scratch isn't just slower, but results in worse UX. But even if you disable tree-diffing and make Nx do what Turbo does, it is still 1.5 times faster.
|
||||
|
||||
The cache restoration Turborepo provides might be fast enough for a lot of repos (3 seconds is still plenty fast). What matters for larger repos like this one is the ability to distribute any command across say 50 machines while preserving the dev ergonomics of running it on a single machine. Nx can do it. Bazel can do it (which Nx borrows some ideas from). Turbo can't.
|
||||
|
||||
The one advantage Turbo's Go implementation has, is that any time you run an Nx command you pay a ~150ms penalty to boot Node.js. If you test 1 project, you pay a 150ms penalty, if you test 1000 projects, it is still a 150ms penalty. We don’t think in practice it matters because most other CLIs (e.g,. yarn) have the same penalty. The real performance gains from both Nx and Turborepo are in how intelligently they reduce, cache, and in Nx's case, distribute tasks.
|
||||
|
||||
**Nx and Turborepo often have different philosophies of how workspaces should be built.** Turborepo tends to think in terms of "packages", whereas Nx is focused on many lightweight projects. Large Nx Workspaces tend to be composed of hundreds or even thousands of projects, which helps the average build performance in three ways:
|
||||
|
||||
|
||||
BIN
docs/shared/nx-turbo.gif
Normal file
BIN
docs/shared/nx-turbo.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.0 MiB |
@ -147,7 +147,7 @@ The file extension or preprocessor to use for style files, or 'none' to skip gen
|
||||
|
||||
### type
|
||||
|
||||
Default: `Component`
|
||||
Default: `component`
|
||||
|
||||
Type: `string`
|
||||
|
||||
|
||||
@ -33,14 +33,6 @@ nx g application ... --dry-run
|
||||
|
||||
## Options
|
||||
|
||||
### babelJest
|
||||
|
||||
Default: `false`
|
||||
|
||||
Type: `boolean`
|
||||
|
||||
Use babel instead ts-jest
|
||||
|
||||
### compiler
|
||||
|
||||
Default: `babel`
|
||||
|
||||
@ -133,6 +133,9 @@ new ModuleFederationPlugin({
|
||||
'@angular/router': { singleton: true, strictVersion: true },
|
||||
...sharedMappings.getDescriptors(),
|
||||
},
|
||||
library: {
|
||||
type: 'module',
|
||||
},
|
||||
}),
|
||||
```
|
||||
|
||||
@ -150,7 +153,7 @@ We can see the following in Dashboard's webpack configuration:
|
||||
```js
|
||||
new ModuleFederationPlugin({
|
||||
remotes: {
|
||||
login: 'login@http://localhost:4201/remoteEntry.js',
|
||||
login: 'http://localhost:4201/remoteEntry.js',
|
||||
},
|
||||
shared: {
|
||||
'@angular/core': { singleton: true, strictVersion: true },
|
||||
@ -159,6 +162,9 @@ new ModuleFederationPlugin({
|
||||
'@angular/router': { singleton: true, strictVersion: true },
|
||||
...sharedMappings.getDescriptors(),
|
||||
},
|
||||
library: {
|
||||
type: 'module',
|
||||
},
|
||||
}),
|
||||
```
|
||||
|
||||
@ -166,10 +172,9 @@ The key difference to note with the Dashboard's configuration is the `remotes` o
|
||||
|
||||
You give it a name that you can reference in your code, in this case `login`.
|
||||
Then you assign it a string value of the following pattern:
|
||||
`{name}@{url}/{remoteEntrypointFilename}`
|
||||
`{url}/{remoteEntrypointFilename}`
|
||||
where:
|
||||
|
||||
- `name` is the name given to the remote in the remote's webpack configuration
|
||||
- `url` is the url where the remote application is hosted
|
||||
- `remoteEntrypointFilename` is the filename supplied in the remote's webpack configuration
|
||||
|
||||
@ -352,9 +357,14 @@ To make this work, however, there are some initial steps we need to take. We nee
|
||||
Open up each and replace the `sharedMappings` config _(found near the top)_ with the following:
|
||||
|
||||
```js
|
||||
sharedMappings.register(path.join(__dirname, '../../tsconfig.base.json'), [
|
||||
'@ng-mfe/shared/data-access-user',
|
||||
]);
|
||||
sharedMappings.register(
|
||||
tsConfigPath,
|
||||
[
|
||||
/* mapped paths to share */
|
||||
'@ng-mfe/shared/data-access-user',
|
||||
],
|
||||
workspaceRootPath
|
||||
);
|
||||
```
|
||||
|
||||
Now, let's delete the `app.component.html` and `app.component.css` files in the Dashboard app. They will not be needed for this tutorial.
|
||||
|
||||
@ -147,7 +147,7 @@ The file extension or preprocessor to use for style files, or 'none' to skip gen
|
||||
|
||||
### type
|
||||
|
||||
Default: `Component`
|
||||
Default: `component`
|
||||
|
||||
Type: `string`
|
||||
|
||||
|
||||
@ -33,14 +33,6 @@ nx g application ... --dry-run
|
||||
|
||||
## Options
|
||||
|
||||
### babelJest
|
||||
|
||||
Default: `false`
|
||||
|
||||
Type: `boolean`
|
||||
|
||||
Use babel instead ts-jest
|
||||
|
||||
### compiler
|
||||
|
||||
Default: `babel`
|
||||
|
||||
@ -147,7 +147,7 @@ The file extension or preprocessor to use for style files, or 'none' to skip gen
|
||||
|
||||
### type
|
||||
|
||||
Default: `Component`
|
||||
Default: `component`
|
||||
|
||||
Type: `string`
|
||||
|
||||
|
||||
@ -33,14 +33,6 @@ nx g application ... --dry-run
|
||||
|
||||
## Options
|
||||
|
||||
### babelJest
|
||||
|
||||
Default: `false`
|
||||
|
||||
Type: `boolean`
|
||||
|
||||
Use babel instead ts-jest
|
||||
|
||||
### compiler
|
||||
|
||||
Default: `babel`
|
||||
|
||||
@ -10,7 +10,7 @@ This document was written on December 14, 2021. At this point Turborepo has just
|
||||
|
||||
We clearly separate Nx (the open source tool) and [Nx Cloud](https://nx.app) (the SAAS product). Turborepo doesn’t have such a separation. Hence, in this guide we compare Turborepo with Nx+Nx Cloud (so it’s apples to apples). That said, you don’t have to use Nx Cloud to get features such as distributed caching and distributed task execution. We provide public APIs so you can build your own, if you'd prefer not to use Nx Cloud.
|
||||
|
||||
We are going to compare the tools in three different ways: **features**, **tech**, and **community**.
|
||||
We are going to compare the tools in three different ways: **features**, **tech and performance**, and **community**.
|
||||
|
||||
## Features
|
||||
|
||||
@ -117,13 +117,22 @@ Nx doesn’t replace any of your tools, and it’s not “all in”. You can sta
|
||||
|
||||
Read [this guide](https://nx.dev/l/r/getting-started/nx-core) to learn more about how to only use Nx Core.
|
||||
|
||||
## Tech
|
||||
## Tech and Performance
|
||||
|
||||
Turborepo is mostly written in Golang. Nx is mostly written in TypeScript, but most of the heavy computation in Nx is done by core Node.js capabilities and node modules written in C++, so performance isn’t affected by this.
|
||||
|
||||
The one advantage the Go implementation has, is that any time you run an Nx command you pay a ~150ms penalty to boot Node.js. If you test 1 project, you pay a 150ms penalty, if you test 1000 projects, it is still a 150ms penalty. We don’t think in practice it matters because most other CLIs (e.g,. yarn) have the same penalty. The real performance gains from both Nx and Turborepo are in how intelligently they reduce, cache, and in Nx's case, distribute tasks.
|
||||
Benchmarking is hard because a lot depends on what you are trying to run, in what environment, etc. This is one benchmark we use when measuring Nx perf: [Nx and Turbo benchmark](https://github.com/vsavkin/large-monorepo/). It is a repo with 5 Next.js apps. We are measuring how quickly Nx and Turbo can figure out what needs to be restored from cache, and how quickly they can do it.
|
||||
|
||||
Benchmarking things, in general, is tricky, so we aren’t making claims that Nx is categorically faster. Based on our measurements, distributed task execution and optimizations in restoring files make Nx significantly faster for real-world scenarios, but you should do your own measurements because a lot of it is project specific.
|
||||
This is the result:
|
||||

|
||||
|
||||
Nx is 5 times faster on the latest MBP. Nx is 7.5 times faster on a Windows laptop.
|
||||
|
||||
Why is it faster? Nx is in many ways akin to React in that it's doing tree diffing when restoring files from the cache. If the right files are in the right place, Nx won't touch them. Turbo blows everything away every time. Nx's version isn't just faster, it's also more useful (again similarly to tree diffing in React). Blowing everything away on every restoration means that if any tools watch the folders (which is common when you build large apps or build microfrontends), they are going to get confused or triggered for no reason. This is similar to how recreating the DOM from scratch isn't just slower, but results in worse UX. But even if you disable tree-diffing and make Nx do what Turbo does, it is still 1.5 times faster.
|
||||
|
||||
The cache restoration Turborepo provides might be fast enough for a lot of repos (3 seconds is still plenty fast). What matters for larger repos like this one is the ability to distribute any command across say 50 machines while preserving the dev ergonomics of running it on a single machine. Nx can do it. Bazel can do it (which Nx borrows some ideas from). Turbo can't.
|
||||
|
||||
The one advantage Turbo's Go implementation has, is that any time you run an Nx command you pay a ~150ms penalty to boot Node.js. If you test 1 project, you pay a 150ms penalty, if you test 1000 projects, it is still a 150ms penalty. We don’t think in practice it matters because most other CLIs (e.g,. yarn) have the same penalty. The real performance gains from both Nx and Turborepo are in how intelligently they reduce, cache, and in Nx's case, distribute tasks.
|
||||
|
||||
**Nx and Turborepo often have different philosophies of how workspaces should be built.** Turborepo tends to think in terms of "packages", whereas Nx is focused on many lightweight projects. Large Nx Workspaces tend to be composed of hundreds or even thousands of projects, which helps the average build performance in three ways:
|
||||
|
||||
|
||||
BIN
nx-dev/nx-dev/public/documentation/latest/shared/nx-turbo.gif
Normal file
BIN
nx-dev/nx-dev/public/documentation/latest/shared/nx-turbo.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.0 MiB |
@ -49,7 +49,7 @@ function isNotAsset(linkPath: string): boolean {
|
||||
}
|
||||
|
||||
function isNotImage(linkPath: string): boolean {
|
||||
return !linkPath.endsWith('.png');
|
||||
return !linkPath.endsWith('.png') && !linkPath.endsWith('.gif');
|
||||
}
|
||||
|
||||
function isNotNxCommunityLink(linkPath: string): boolean {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user