Live data from Hacker News

Case Study: Npm uses Rust for its CPU-bound bottlenecks [pdf]

rust-lang.org

261–270 of 307 posts

Re: Case Study: Npm uses Rust for its CPU-bound bottlenecks [pdf]

#261

Earlier quoted context omitted.

This type of thinking is exactly why I stay away from the developer communities of Rust and Julia. Both communities seem to have this weird perception that their respective language categorically supersedes other tools in all use cases. Don’t get me wrong. Rust and Julia are very cool languages with a lot of use cases where they are great choices. But the communities come off as disproportionately full of zealots, wh…

Did you mean to reply to another comment? Because you're not addressing parent's point about the sordid history of non-memory safe codebases. Replying to everybody who replied to your comment is pointless if you don't take the time to read and process the replies.

I did not mean to reply to a different comment. I did address the parent's point by explaining that the premise of the point (the claim that no piece of C/C++ code is ever safe) should be categorically rejected and not engaged with.

> "Replying to everybody who replied to your comment is pointless if you don't take the time to read and process the replies."

This feels like you are being needlessly antagonistic and assuming incorrectly that I failed to read other comments or replies. If you did not understand the manner in which my comment was responding to the parent, that's fine, but it was and I don't appreciate your tone.

Re: Case Study: Npm uses Rust for its CPU-bound bottlenecks [pdf]

#262
post #234

Earlier quoted context omitted.

I mean, we still write the overwhelming majority of our code in JavaScript. We port to Rust when CPU-heavy task becomes a bottleneck to the rest of the system. It's not as if this paper is saying (nor is it the case) that we've ported the whole registry to Rust. JS has lots of advantages we appreciate.

I'm curious why this authorization service is CPU intensive. The article says it's basically deciding if you're authorized to publish a package. It sounds like the sort of thing that would talk to a database, or a cache like redis, and therefore mostly be IO bound itself. Is this maybe parsing data structures itself?

It's been a few years since I was directly involved in engineering, but my fairly educated understanding is that it's more around reading of possibly-private packages than publishing.

Publishing is a relatively rare event compared with reading, but in a world of private packages, orgs, and teams, the "can {user} read {object}" gets more complicated. It probably wouldn't be CPU bound if not for the sheer scale we're dealing with, but once all the IO bottlenecks are resolved, you still have to check to make sure that a login token is valid, then get the user associated with it, then check the teams/orgs/users with access to a thing (which might be public, in which case, the problem is a lot simpler, but you still have to get that info and check it), and then whether the user is in any of those groups. So there's a straightforward but relevant bit of CPU work to be done, and that's where Rust shines.

Re: Case Study: Npm uses Rust for its CPU-bound bottlenecks [pdf]

#263
post #250

Earlier quoted context omitted.

The current version of npm does this and this is "correct behaviour". I got bitten by this a few weeks ago. For the passers-by, the only way to make npm behave expectedly in this specific case is to use "npm ci" instead of "npm install" . If you do not do this, npm will assume you want to update the packages to the latest version at all times, at all costs, even if you have a lock file in place, and even if you have…

> and even if you have your package file and lock file locked to exact versions. (i.e. 2.0.0 exact, not ^2.0.0) Wait what? Are you sure about that part? That's a violation of npm's semver constraints https://semver.npmjs.com (I agree with you that "npm ci" should be the default behavior, and "npm install" should be called something different, like update-and-install)

Yes - to be more specific, you can lock your own package's dependencies to an exact version, but you cannot lock dependencies of your package's dependencies. You can't do anything about them. They will get updated because their package lock specifies the lock in the form of ^2.0.0. The fact that a package lock can resolve to multiple versions is counterintuitive. One would think the whole point of a package lock is to lock packages.

As a result, when you do a npm install in your oblivious and happy life, npm naturally assumes you want to summon Cthulhu. If you didn't want to summon Cthulhu, why did you call the command that summons Cthulhu? Yes, the default command summons Cthulhu because we believe in agile Cthulhu. If you don't want to summon Cthulhu, try this undocumented command with a misleading name we've added silently a few weeks ago for weird people like you who don't want to summon Cthulhu when they want to do a npm install. But seriously, why do you not want to summon Cthulhu?

Unfortunately, this was the impression I've gotten of the position of npm folks when I read a few threads about this. I've moved to npm ci for now and moved on. Npm's package lock is many things, however, none of the things it is, is a package lock.

Re: Case Study: Npm uses Rust for its CPU-bound bottlenecks [pdf]

#264

Earlier quoted context omitted.

That is incorrect. Both `npm install` and `npm ci` respect the lock file, and if a lock file is present, will make the `node_modules` tree match the lock file exactly. `npm ci` is optimized for a cold start, like on a CI server, where it's expected that `node_modules` will not be present. So, it doesn't bother looking in `node_modules` to see what's already installed. So, _in that cold start case_, it's faster, but i…

> Both `npm install` and `npm ci` respect the lock file This is not correct. `npm install` will update your dependencies, not install them, disregarding the package versions defined in the lock file. It feels like you are not getting the point of having a lock file in the first place. It should be obvious that you can't do an install (which npm calls ci) if you don't have a lock file. The lock file represents your ac…

If you run `npm install` with no arguments, and you have a lockfile, it will make the node_modules folder match the lockfile. Try it.

    $ json dependencies.esm =3.2.5
    
    $ npm ls esm
    tap@12.5.3 /Users/isaacs/dev/js/tap
    └── esm@3.2.5
    # currently have 3.2.5 installed
    
    $ npm view esm version
    3.2.10
    # latest version on the registry is 3.2.10
    
    $ npm install
    audited 590 packages in 1.515s
    found 0 vulnerabilities
    # npm install runs the audit, but updates nothing
    # already matches package-lock.json
    
    $ npm ls esm
    tap@12.5.3 /Users/isaacs/dev/js/tap
    └── esm@3.2.5
    
    # esm is still 3.2.5
    
    $ rm -rf node_modules/esm/
    # remove it from node_modules
    
    $ npm i
    added 1 package from 1 contributor and audited 590 packages in 1.647s
    found 0 vulnerabilities
    # it updated one package this time
    
    $ npm ls esm
    tap@12.5.3 /Users/isaacs/dev/js/tap
    └── esm@3.2.5
    # oh look, matches package-lock.json!  what do you know.
Now, if you do `npm install esm` or some other _explicit choice to pull in a package by name_, then yes, it'll update it, and update the package-lock.json as well. But that's not what we're talking about.

I often don't know what I'm talking about in general, but I do usually know what I'm talking about re npm.

Re: Case Study: Npm uses Rust for its CPU-bound bottlenecks [pdf]

#265
post #171

Earlier quoted context omitted.

That is incorrect. Both `npm install` and `npm ci` respect the lock file, and if a lock file is present, will make the `node_modules` tree match the lock file exactly. `npm ci` is optimized for a cold start, like on a CI server, where it's expected that `node_modules` will not be present. So, it doesn't bother looking in `node_modules` to see what's already installed. So, _in that cold start case_, it's faster, but i…

Thanks for the reply Isaac! This doesn’t match my first-hand experience unfortunately. Are there any circumstances under which npm install with a lockfile present deviates from the lockfile where npm ci does not? For example, why did this person experience the changing lockfile? https://github.com/npm/npm/issues/17101 Or why do these docs say? > Whenever you run npm install, npm generates or updates your package lock…

If you run `npm install` with an argument, then you're saying "get me this thing, and update the lock file", so it'll do that. `npm install` with no argument will only add new things if they're required by package.json, and not already satisfied, or if they don't match the package-lock.json.

In the bug linked, they wanted to install a specific package (not matching what was in the lockfile), without updating the lockfile. That's what `--no-save` will do.

The SO link is from almost 2 years ago, and a whole major version back. So I honestly don't know. Maybe a bug that was fixed? If this is still a problem for you on the latest release, maybe take it up on https://npm.community or a GitHub issue?

Re: Case Study: Npm uses Rust for its CPU-bound bottlenecks [pdf]

#266

Earlier quoted context omitted.

…so would Cargo? If you install a new package, why wouldn’t you expect it to show up in your lock file?

No, you guys don't understand.. npm updates the package lock even when not adding a new package, i.e. the initial `npm install`. It's insane I'm think to go back to yarn again..

You can use ‘npm ci’ for actually sensible install behaviour.

Re: Case Study: Npm uses Rust for its CPU-bound bottlenecks [pdf]

#267
post #50

This entire article is a pretty damning report on JavaScript in general, but this sentence takes the cake (emphasis mine): > The process of deploying the new Rust service was straight-forward, and soon they were able to forget about the Rust service because it caused so few operational issues. At npm, the usual experience of deploying a JavaScript service to production was that the service would need extensive monito…

Rust's package managment (cargo) is the best thing I have ever seen of it's kind. The very basic thing you can do is: cargo new funkyproject Which creates a new barebones rust project called "funkyproject". Every dependency specified in it's Cargo.toml will be automatically downloaded at build (if there is a new version). When a build is sucessful the versions of said dependency will be saved into a Cargo.lock file.…

Python does have something like this, which is conda [0].

It allows specifying dependencies with much of the same freedom you mentioned, in an environment.yaml file and other config files, you can provide arbitrary build instructions via shell scripts, use a community led repository of feeds for stable and repeatable cross-platform builds of all libraries [1], generate the boilerplate automatically for many types of packages (not just Python) [2], compiled version specifics with build variants / "features", and you can use pip as the package installer inside a pip section in the conda yaml config file.

[0]: https://github.com/conda/conda [1]: http://conda-forge.org/#about [2]: https://conda.io/projects/conda-build/en/latest/source/resou...

Re: Case Study: Npm uses Rust for its CPU-bound bottlenecks [pdf]

#268
post #60
post #23

Earlier quoted context omitted.

They also state that writing the service in Node took them an hour, two days for Go, and a week for Rust. Even taking into account their unfamiliarity with the language, it's probably fair to say that when switching to Rust, you'll usually spend more time writing and less time debugging. Whether that trade-off is worth it depends on the project.

It depends, I am over a year in Rust and it doesn't take me that much longer to write something in it than say in Python. The confidence I have that the thing I wrote is way higher in Rust and it is usually much faster. And: it is incredible easy to build and deploy. I think whether Rust is useful or not depends entirely on the application. If you need high confidence in what the thing is doing, it should run paralle…

> I tried too much to use OOP, which doesn't make any sense and leads to convoluted code.

Oh, well, you don't need Rust for that! :P

Re: Case Study: Npm uses Rust for its CPU-bound bottlenecks [pdf]

#269

Earlier quoted context omitted.

…so would Cargo? If you install a new package, why wouldn’t you expect it to show up in your lock file?

No, you guys don't understand.. npm updates the package lock even when not adding a new package, i.e. the initial `npm install`. It's insane I'm think to go back to yarn again..

I'm with you, the default behavior is so counter intuitive.

Re: Case Study: Npm uses Rust for its CPU-bound bottlenecks [pdf]

#270

Earlier quoted context omitted.

Obviously authorisation will be a huge overhead compared to sendfile + nginx right? Am I misunderstanding what npm does?

I mean, to use sendfile you need to open the file, and that does a permission check too...

No I'm talking about private NPM right. The perms on the file system are not equal to (or as costly as) the auth I need to have to access my private NPM repo.
Post reply on HN