This is unrelated to the release on Linux (congrats to the project BTW) but I’ve been wondering about this lately.
I recently compiled Zed from source and was pretty surprised when cargo pulled in 637 dependencies.
I’m not a Rust developer and I don’t want to diminish the complexity of a cross-platform, performant text editor, but is this really what people expect? What about the risk that one of these packages gets a malicious update?
Also read yesterday that Zed installs Node.js and packages silently without notifying the user.
That also does not sit that well with me.
You’re talking about a project with ~137 first party crates* (I counted awhile ago, may have changed by now). Pulling in 637 dependencies (and I honestly thought it was slightly more than that) isn’t surprising at all. I’ve previously also looked through the list and exactly 0 of the dependencies struck me as particularly surprising. I helped a tiny bit on the linux port, enough to get the sense that the Zed people are erring on the side of rewriting more of the world than they probably ought to, not less.
*And that was just counting things in the repo, not counting dependencies on contributors code that lives outside of the repo.
What about the risk that one of these packages gets a malicious update?
A lock file means updates aren’t pulled in automatically. Basically all third party dependencies are from crates.io, and are generally widely used being reviewed at least incidentally by many developers. It hasn’t been an issue yet * (and I’m not just referring to Zed here but the eceosystem as a whole, and more broadly all the ecosystems that lean heavily on language specific package managers). I honestly think that it’s unlikely to be an issue in the future. People who are concerned are doing good work at various forms of further mitigation beyond lock files (e.g. https://github.com/mozilla/cargo-vethttps://github.com/crev-dev/cargo-crevhttps://blog.rust-lang.org/inside-rust/2024/05/07/this-development-cycle-in-cargo-1.79.html#sbom)
* Typo squatting, yes. Malicious updates, no.
Edit: Fixed number of first party crates 112 -> 137.
Smaller Rust projects have way fewer dependencies. Zed does a lot more than just edit text files. It contains a whole architecture for distributed collaboration. Whether this is desirable is an entirely different question.
Doesn’t it install node.js because of the lsp? Also the number of dependencies is generally high in modern packages but doesn’t necessarily indicate bloat. For example KDE made changes to break up the DE packages. You still need them for the DE so it ends up pulling in a bunch of dependent KDE packages as well. People freaked out about KDE applications being bloated because they saw a bunch of packages in the terminal, but it was the same amount of code, just spread out into smaller packages as opposed to one big package.
Rust has a small standard lib by design (easier to port to other platforms. Better for systems programming) but that means like basic stuff like random number generation end up being third party packages, so people typically rely on a larger amount of third party dependencies for large projects.
As for the security issue, I think that is still an open question that projects are trying to figure out. Some build the dependencies themselves and use specific trusted versions of a package on an internal repository network, but that is a lot of work
I’m fairly certain that in the Rust community, dependencies are seen more as a virtue than a vice. The idea is that a tightly integrated package manager reduces the friction to split out generic functionality into separate packages thus increasing code reuse and reducing redundant work. It may be the case that the total amount of code in Zed is roughly equivalent to a similarly featureful text editor written in, say, C++, just that a lot of the code is split out into separate packages.
It’s also worth noting that even for individual “projects” in Rust which might be considered one package in some ecosystems, it’s common to split them into several crates. Tokio is a good example of this. There’s a couple of reasons why sub-crates are preferable for this.
First, Rust crates can gate code behind “features”. You can use attributes to gate features, but usually it’s cleaner and easier to separate functionality into it’s own crate to do so, especially if the feature involves pulling in optional dependencies.
Secondly is the iteration time in development. Before incremental compilation, any changes within a crate meant recompiling the entire crate (which also has a knock-on effect on its dependencies); this has improved with incremental compilation, but the compiler still needs to check what codegen units are affected and need to be recompiled, which of course worsens with the size of the crate. Splitting into several crates not only helps keep crate size down, but the logical boundary means that the scope of code that needs to be recompiled due to a change is also minimized.
Plus, parallelizing the rustc frontend is a work in progress (if you watch your CPU monitor during compilation, you’ll notice that there’s a period after finishing building all your project’s dependencies and before LLVM starts chewing on the generated LLVM IR when CPU utilization drops to one core) and Rust’s most basic form of parallel compilation is doing a topological sort on the dependencies and then building crates in parallel whenever possible.
When I’m doing incremental rebuilds of my projects, and it takes 4 seconds, somewhere between 1 and 3 of those seconds (I can’t remember exactly) is rustc boost-clocking a single core to 5.2GHz and the remaining 3 to 1 seconds are mold taking advantage of my Noctua cooler to boost-clock all six cores to 4.9GHz.
After installation, Zed occupied 535 MB of disk space on my Linux system. By comparison, Emacs-GTK is 137 MB. So Zed is about 4x larger than Emacs. That seems bloated to some people, and noteworthy.
Has it been confirmed that strip doesn’t drop that? Among other things, it wasn’t too long ago that cargo didn’t know how to strip the precompiled “release build with debug symbols” standard library while statically linking it and I believe the default for the strip profile option is still none.
I used du to tell me the the total amount of file system space occupied by all of the files that were installed by the Zed installer. About half of that is a private copy of node stored in a Zed-specific subdirectory, since part of Zed is written in Javascript. I compared that to the total file system space required by an installation of the Debian emacs-gtk package, which is Emacs with a GUI. The Emacs number is slightly inflated because some non-Emacs packages were installed as dependencies, but that only accounted for 1.5 MB on my system (since I already had gtk installed). If Zed were to conform to Debian packaging rules, then the private copy of Node would be replaced by the standard Node package, which would make the Zed specific part of the installation smaller. This refactoring could also shrink memory usage, if I was running other Node software at the same time.
It has a lot more than a typical project would, and that gives some people pause. I appreciate the good explanations and justifications given in the other responses, though. It helps me to understand that “editor” these days really means “operating system”.
I’m not a Rust developer and I don’t want to diminish the complexity of a cross-platform, performant text editor, but is this really what people expect?
Yes, in Lapce we have 700~800 crates (depends if you are Linux/macOS/Windows). There is an extreme amount of logic that needs to be covered, on each platform and I’m not in a mood to write all that from scratch. Mind that a lot of crates do very specific thing, have multiple variants (e.g. crate + crate-sys, or multiple Windows targets, etc.), or other reasons.
What about the risk that one of these packages gets a malicious update?
Unless we update to it, nothing, since we keep the lockfile that contains all dependencies resolved to specific versions.
I might have OCD on limiting the number of outside dependencies.
Personal opinions aside, what is the general practice of ensuring the correctness of all of the dependencies in production? Do people only test their own product, and as long as it passes tests, you may infer the robustness of all the dependencies? Or do any of you make your own unit tests for important dependencies?
While I don’t really like it, it is what I expect of Rust project that use async or do web things, and I would guess the GUI side of things is the same. It’s so easy to add packages, and if your five dependencies each depend on five more dependencies, you only need to go four levels deep to get to 625 packages.
What about the risk that one of these packages gets a malicious update?
There’s a fair amount of trust in the big packages since it’s not uncommon for their maintainers to be Rust team members. You sort of trust that your dependencies have also done their due diligence. Still, there’s always a non-zero chance of a malicious update.
The proposed solutions are often to use something like cargo vet or cargo crev to audit your dependencies, but that becomes a lot easier if you don’t have many.
and I would guess the GUI side of things is the same
It’s worth pointing out that they made the unusual decision to write their GUI implementation from scratch (and have released their framework for use outside of zed: https://www.gpui.rs/) and are depending on relatively little third party code as a result.
Though they still end up picking up a number of dependencies for talking to the system, loading font data, and so on in order to write their GUI framework. Potentially in number of cargo dependencies terms more than if they just dependended on gtk or something (because recursive dependencies of a C library aren’t counted by cargo).
(Disclaimer: I have no personal experience of Zed.)
I recently compiled Zed from source and was pretty surprised when cargo pulled in 637 dependencies.
Well, it sounds like you fared better than some. :-)
I don’t personally have knowledge of how the distribution of package sizes in Rust compares to other ecosystems, but it is said that Rust tends to use smaller and more numerous packages than others, especially C++, though I guess not Node.js. Kornel said
It’s also worth noting that Rust projects tend to use tiny single-purpose dependencies, so this is not like 1111 C dependencies or 1111 distro packages. More like 1111 .c files.
I’m not sure the average dependency size is quite so small in my own experience of Rust, but (1) I would agree that the large number of dependencies doesn’t necessarily mean that the dependency graph is as large in bytes and lines of code as you might think and (2) Kornel has stats and I don’t. :-)
(Hm, @kornel, would it be easy for you to add Zed to the off-Crates.io crates that Lib.rs tracks, so that future comments surprised by the size of its dependency graph in number of crates can be complemented with data on the size of the dependency graph in bytes and LoC, as Lib.rs crate pages show?)
What about the risk that one of these packages gets a malicious update?
I do think this risk is present and I do suspect that the high numbers of dependencies commonly used in Rust exacerbate it. Like gpm and jamesw, I gesture towards cargo-crev and cargo-vet as improvements in this area, but these tools are, so far, not at all widely used, and I don’t have gpm’s apparent trust that popular crates’ wide use (by the majority of the ecosystem that does not formally audit their dependencies) translates into sufficient review of dependencies to catch malicious ones.
One actionable thing one can do as a potential user of a Rust project is to check whether it has a supply-chain/config.toml file, which indicates use of cargo-vet (although it’s possible that a project has neglected to run cargo vet check recently — see whether they’re running it in CI, if they have CI). I don’t know what the equivalent is for cargo-crev, aside from seeing whether a project’s README mentions it.
Personally I like the rest of the editor enough that I’m happy to ignore the AI features until this hype cycle cools off. I appreciate that AI exhaustion is real though.
I’ve been using Zed on Linux for several weeks, and I’m very happy with it. Its keybinding system is flexible enough to accommodate my very idiosyncratic muscle memory. And it’s SO FAST. It works very well with rust-analyzer, in addition to giving a pretty good experience on random other stuff (json, yaml, python) without having to do much of anything.
It doesn’t work on my Linux Mint machine. It asks me to type in my password (WTF!), so I hit the cancel button in the dialog, and then no window is displayed, although there are two background processes I have to kill. I realize this is alpha quality software, so maybe I’ll try again later this year.
I hope I’m be wrong but I guess the VCS integrations and other goodies could just be paid for in the future, with a discount if you subscribe for 12 months. 💰
We envision Zed as a free-to-use editor, supplemented by subscription-based, optional network features, such as:
Channels and calls
Chat
Channel notes
We plan to offer our collaboration features to open source teams, free of charge.
Also further up under “Zed” -> “Will Zed be free?”
Yes. Zed will be free to use as a standalone editor. We will instead charge a subscription for optional features targeting teams and collaboration.
Obviously these things can be changed in future, but my suspicion is everything non-network/realtime collaboration related will always be free based on what they’ve consistently said.
I use Darcs daily & Pijul occassionally. A few projects I use are happily still using Mercurial. None of these have staging. If you install something like git-branchless, record does not require staging either. Staging is a weird Git concept.
This is unrelated to the release on Linux (congrats to the project BTW) but I’ve been wondering about this lately.
I recently compiled Zed from source and was pretty surprised when cargo pulled in 637 dependencies. I’m not a Rust developer and I don’t want to diminish the complexity of a cross-platform, performant text editor, but is this really what people expect? What about the risk that one of these packages gets a malicious update?
Also read yesterday that Zed installs Node.js and packages silently without notifying the user. That also does not sit that well with me.
You’re talking about a project with ~137 first party crates* (I counted awhile ago, may have changed by now). Pulling in 637 dependencies (and I honestly thought it was slightly more than that) isn’t surprising at all. I’ve previously also looked through the list and exactly 0 of the dependencies struck me as particularly surprising. I helped a tiny bit on the linux port, enough to get the sense that the Zed people are erring on the side of rewriting more of the world than they probably ought to, not less.
*And that was just counting things in the repo, not counting dependencies on contributors code that lives outside of the repo.
A lock file means updates aren’t pulled in automatically. Basically all third party dependencies are from crates.io, and are generally widely used being reviewed at least incidentally by many developers. It hasn’t been an issue yet * (and I’m not just referring to Zed here but the eceosystem as a whole, and more broadly all the ecosystems that lean heavily on language specific package managers). I honestly think that it’s unlikely to be an issue in the future. People who are concerned are doing good work at various forms of further mitigation beyond lock files (e.g. https://github.com/mozilla/cargo-vet https://github.com/crev-dev/cargo-crev https://blog.rust-lang.org/inside-rust/2024/05/07/this-development-cycle-in-cargo-1.79.html#sbom)
* Typo squatting, yes. Malicious updates, no.
Edit: Fixed number of first party crates 112 -> 137.
Smaller Rust projects have way fewer dependencies. Zed does a lot more than just edit text files. It contains a whole architecture for distributed collaboration. Whether this is desirable is an entirely different question.
I highly recommend watching this interview where it is explained in depth: Building the Zed Text Editor (with Nathan Sobo).
Doesn’t it install node.js because of the lsp? Also the number of dependencies is generally high in modern packages but doesn’t necessarily indicate bloat. For example KDE made changes to break up the DE packages. You still need them for the DE so it ends up pulling in a bunch of dependent KDE packages as well. People freaked out about KDE applications being bloated because they saw a bunch of packages in the terminal, but it was the same amount of code, just spread out into smaller packages as opposed to one big package.
Rust has a small standard lib by design (easier to port to other platforms. Better for systems programming) but that means like basic stuff like random number generation end up being third party packages, so people typically rely on a larger amount of third party dependencies for large projects.
As for the security issue, I think that is still an open question that projects are trying to figure out. Some build the dependencies themselves and use specific trusted versions of a package on an internal repository network, but that is a lot of work
I’m fairly certain that in the Rust community, dependencies are seen more as a virtue than a vice. The idea is that a tightly integrated package manager reduces the friction to split out generic functionality into separate packages thus increasing code reuse and reducing redundant work. It may be the case that the total amount of code in Zed is roughly equivalent to a similarly featureful text editor written in, say, C++, just that a lot of the code is split out into separate packages.
It’s also worth noting that even for individual “projects” in Rust which might be considered one package in some ecosystems, it’s common to split them into several crates. Tokio is a good example of this. There’s a couple of reasons why sub-crates are preferable for this.
First, Rust crates can gate code behind “features”. You can use attributes to gate features, but usually it’s cleaner and easier to separate functionality into it’s own crate to do so, especially if the feature involves pulling in optional dependencies.
Secondly is the iteration time in development. Before incremental compilation, any changes within a crate meant recompiling the entire crate (which also has a knock-on effect on its dependencies); this has improved with incremental compilation, but the compiler still needs to check what codegen units are affected and need to be recompiled, which of course worsens with the size of the crate. Splitting into several crates not only helps keep crate size down, but the logical boundary means that the scope of code that needs to be recompiled due to a change is also minimized.
Plus, parallelizing the rustc frontend is a work in progress (if you watch your CPU monitor during compilation, you’ll notice that there’s a period after finishing building all your project’s dependencies and before LLVM starts chewing on the generated LLVM IR when CPU utilization drops to one core) and Rust’s most basic form of parallel compilation is doing a topological sort on the dependencies and then building crates in parallel whenever possible.
When I’m doing incremental rebuilds of my projects, and it takes 4 seconds, somewhere between 1 and 3 of those seconds (I can’t remember exactly) is rustc boost-clocking a single core to 5.2GHz and the remaining 3 to 1 seconds are mold taking advantage of my Noctua cooler to boost-clock all six cores to 4.9GHz.
Also unrelated to the release but why do people keep harping about the number of dependencies that Zed has?
After installation, Zed occupied 535 MB of disk space on my Linux system. By comparison, Emacs-GTK is 137 MB. So Zed is about 4x larger than Emacs. That seems bloated to some people, and noteworthy.
Especially given that Emacs was the previous gold standard for seemingly bloated software.
Wait, the release build of zed is 535 MB? This doesn’t seem right to me.
That number probably including the cache, downloaded extensions and language servers. The binary is 149MB.
Whereas the emacs-gtk binary is 40MB (38MiB), which is also roughly 1/4 the size of Zed.
Has it been confirmed that
stripdoesn’t drop that? Among other things, it wasn’t too long ago thatcargodidn’t know how to strip the precompiled “release build with debug symbols” standard library while statically linking it and I believe the default for thestripprofile option is stillnone.I used
duto tell me the the total amount of file system space occupied by all of the files that were installed by the Zed installer. About half of that is a private copy of node stored in a Zed-specific subdirectory, since part of Zed is written in Javascript. I compared that to the total file system space required by an installation of the Debian emacs-gtk package, which is Emacs with a GUI. The Emacs number is slightly inflated because some non-Emacs packages were installed as dependencies, but that only accounted for 1.5 MB on my system (since I already had gtk installed). If Zed were to conform to Debian packaging rules, then the private copy of Node would be replaced by the standard Node package, which would make the Zed specific part of the installation smaller. This refactoring could also shrink memory usage, if I was running other Node software at the same time.It has a lot more than a typical project would, and that gives some people pause. I appreciate the good explanations and justifications given in the other responses, though. It helps me to understand that “editor” these days really means “operating system”.
Poor Emacs that was blamed for including an operating system when it wasn’t cool to have one.
And an e-mail client.
Sorry I didn’t know it was a hot topic. I guess this just hit me more with this piece of software. At least enough to mention it.
And of course https://xkcd.com/2347/
Yes, in Lapce we have 700~800 crates (depends if you are Linux/macOS/Windows). There is an extreme amount of logic that needs to be covered, on each platform and I’m not in a mood to write all that from scratch. Mind that a lot of crates do very specific thing, have multiple variants (e.g. crate + crate-sys, or multiple Windows targets, etc.), or other reasons.
Unless we update to it, nothing, since we keep the lockfile that contains all dependencies resolved to specific versions.
I might have OCD on limiting the number of outside dependencies.
Personal opinions aside, what is the general practice of ensuring the correctness of all of the dependencies in production? Do people only test their own product, and as long as it passes tests, you may infer the robustness of all the dependencies? Or do any of you make your own unit tests for important dependencies?
Aggressively minimize scope. Make software which does less things, and is composable with other software.
But that works only in domains where you can carve-out a reasonable scope! Notably, building a feature-full editor isn’t such a domain.
While I don’t really like it, it is what I expect of Rust project that use async or do web things, and I would guess the GUI side of things is the same. It’s so easy to add packages, and if your five dependencies each depend on five more dependencies, you only need to go four levels deep to get to 625 packages.
There’s a fair amount of trust in the big packages since it’s not uncommon for their maintainers to be Rust team members. You sort of trust that your dependencies have also done their due diligence. Still, there’s always a non-zero chance of a malicious update.
The proposed solutions are often to use something like
cargo vetorcargo crevto audit your dependencies, but that becomes a lot easier if you don’t have many.It’s worth pointing out that they made the unusual decision to write their GUI implementation from scratch (and have released their framework for use outside of zed: https://www.gpui.rs/) and are depending on relatively little third party code as a result.
Though they still end up picking up a number of dependencies for talking to the system, loading font data, and so on in order to write their GUI framework. Potentially in number of cargo dependencies terms more than if they just dependended on gtk or something (because recursive dependencies of a C library aren’t counted by cargo).
(Disclaimer: I have no personal experience of Zed.)
Well, it sounds like you fared better than some. :-)
I don’t personally have knowledge of how the distribution of package sizes in Rust compares to other ecosystems, but it is said that Rust tends to use smaller and more numerous packages than others, especially C++, though I guess not Node.js. Kornel said
I’m not sure the average dependency size is quite so small in my own experience of Rust, but (1) I would agree that the large number of dependencies doesn’t necessarily mean that the dependency graph is as large in bytes and lines of code as you might think and (2) Kornel has stats and I don’t. :-)
(Hm, @kornel, would it be easy for you to add Zed to the off-Crates.io crates that Lib.rs tracks, so that future comments surprised by the size of its dependency graph in number of crates can be complemented with data on the size of the dependency graph in bytes and LoC, as Lib.rs crate pages show?)
I do think this risk is present and I do suspect that the high numbers of dependencies commonly used in Rust exacerbate it. Like gpm and jamesw, I gesture towards cargo-crev and cargo-vet as improvements in this area, but these tools are, so far, not at all widely used, and I don’t have gpm’s apparent trust that popular crates’ wide use (by the majority of the ecosystem that does not formally audit their dependencies) translates into sufficient review of dependencies to catch malicious ones.
One actionable thing one can do as a potential user of a Rust project is to check whether it has a
supply-chain/config.tomlfile, which indicates use of cargo-vet (although it’s possible that a project has neglected to runcargo vet checkrecently — see whether they’re running it in CI, if they have CI). I don’t know what the equivalent is for cargo-crev, aside from seeing whether a project’s README mentions it.I’m building
dioxus-cliand it’s now at building: “666/751”. So maybe Zed is even a modest project here.One of Zed’s main points on its roadmap is embrace AI, sigh.
Personally I like the rest of the editor enough that I’m happy to ignore the AI features until this hype cycle cools off. I appreciate that AI exhaustion is real though.
Hating on LLMs is this generation’s version of hating on IntelliSense.
I’ve been using Zed on Linux for several weeks, and I’m very happy with it. Its keybinding system is flexible enough to accommodate my very idiosyncratic muscle memory. And it’s SO FAST. It works very well with rust-analyzer, in addition to giving a pretty good experience on random other stuff (json, yaml, python) without having to do much of anything.
It doesn’t work on my Linux Mint machine. It asks me to type in my password (WTF!), so I hit the cancel button in the dialog, and then no window is displayed, although there are two background processes I have to kill. I realize this is alpha quality software, so maybe I’ll try again later this year.
One more site falls into the trap of “it proclaims some grand announcement but it doesn’t tell me what the fuck Zed even is”.
I know what Zed is, but c’mon. Less eye-candy, more content.
I works quite well, but there are a few things I dislike:
autosafecan have both a string and an object as value.I hope I’m be wrong but I guess the VCS integrations and other goodies could just be paid for in the future, with a discount if you subscribe for 12 months. 💰
There’s an answer to this in the FAQ: https://zed.dev/faq#how-will-you-make-money (Under “Company” -> “How will you make money?”)
Also further up under “Zed” -> “Will Zed be free?”
Obviously these things can be changed in future, but my suspicion is everything non-network/realtime collaboration related will always be free based on what they’ve consistently said.
Thanks, I had forgotten about this… :)
So there’s hope for an open source git/vcs integration.
That would be wild, considering it’s an open source project.
Probably I could hack together the most important stuff myself or just use VS Code.
Don’t most VCSs lack a staging area?
Git is more than 90% of VCS usage. If Git has one, most developers use one.
For now. If me keep having tooling that only supports Git, then yeah, the hegemony will probably continue.
Git has one. Are there any other VCSs, that are really used a lot?
I use Darcs daily & Pijul occassionally. A few projects I use are happily still using Mercurial. None of these have staging. If you install something like
git-branchless,recorddoes not require staging either. Staging is a weird Git concept.Hype!