Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Documenting differences between rtx and asdf #1565

Closed
hyperupcall opened this issue May 29, 2023 · 15 comments
Closed

Documenting differences between rtx and asdf #1565

hyperupcall opened this issue May 29, 2023 · 15 comments

Comments

@hyperupcall
Copy link
Contributor

hyperupcall commented May 29, 2023

I thought it would be useful to document the differences between asdf and other meta version managers (that's what I'm it) like rtx and others that seem to be cropping up recently.

I know this repository is probably not the best place to put it, so I created version-manager/documents to put this information. For now, it includes tables for .tool-versions compatability and a general comparison across meta version managers. Later, I plan to include scripts to reproduciably measure performance (In the future, I will be making asdf faster so I want to chart improvements). It may also be cool to list languages that each tool supports.

So if anyone (especially maintainers) have any feedback or suggestions or what you would like to see, that would be greatly appreciated! I also opened a similar issue on the rtx repository (jdx/mise#588), for maybe making it easier to talk about stuff.

@jdx
Copy link

jdx commented May 30, 2023

I think this is great. A good opportunity to standardize tools and explain differences to users that won't be nearly as familiar as people like us are. It reminds me of https://github.com/shadowspawn/node-version-usage which is a similar useful overview. Another comparison it reminds me of is this one for chezmoi.

A couple of random notes/thoughts:

  1. rtx should probably be PATH/shim since it can work just as well with shims—the rtx docs don't currently communicate this as well as they should though. It's been a sticking point for folks. I plan to show shims+PATH as 2 methods with their own pros/cons rather than promoting one over the other as it is today.
  2. performance sounds incredibly useful, though it might be tough to get a real apples to apples comparison since the tools work differently in a lot of ways. What I would love to see is a chart comparing them over time built automatically in a github action. I'd be more than happy to help contribute to this effort.
  3. the !-<difference> syntax I am pretty sure I will modify relatively soon. This hasn't happened yet but I think it'll be more like sub-1:nodejs@18.0.0, sub-0.1:nodejs@18.0.0. What you have is correct today though—and it marks it as experimental so changing it later shouldn't be a big surprise to anyone.
  4. the way that rtx currently uses asdf plugins might make things a little tough to communicate, but my plan is to over time reduce the amount we use asdf plugins in favor of baking popular languages into the CLI directly.

@hyperupcall
Copy link
Contributor Author

rtx should probably be PATH/shim since it can work just as well with shims—the rtx docs don't currently communicate this as well as they should though. It's been a sticking point for folks. I plan to show shims+PATH as 2 methods with their own pros/cons rather than promoting one over the other as it is today.

Gotchia - I'll make those changes. Yeah I myself like both approaches so hopefully labeling them as two good options will help other people make more informed decisions. I'm thinking of listing all options in the documents repository - shims, PATH, and symlinks in general (not specific to rtx, asdf, etc.)

performance sounds incredibly useful, though it might be tough to get a real apples to apples comparison since the tools work differently in a lot of ways. What I would love to see is a chart comparing them over time built automatically in a github action. I'd be more than happy to help contribute to this effort.

Yeah I want to measure performance right. I'm probably going to start with code that is ran on cd hook (if applicable), time to reshim (with few/many many plugins) (if applicable), and see what to do from there. I'll definitely ping you once I get some numbers to be sure I'm not missing anything on the rtx side.

my plan is to over time reduce the amount we use asdf plugins in favor of baking popular languages into the CLI directly

I like that idea - execing into Bash for some standout output feels messy and was kind of surprised when I learned rtx did that. Once there is an rtx-specific/internal plugin system I'd be happy to contribute plugins.

@noraj
Copy link
Contributor

noraj commented Nov 24, 2023

Where can I read about differences between shim and hook?

I remember in the past when neither rtx or asdf-vm existed, rbenv was created because rvm was messing with the system and creating bugs. One of the biggest arguments of rbenv was we use shims and not hooks like rvm. Then asdf-vm and said "let's pack up rbenv, nodenv, etc. altogether". And now "hey we are rtx, it's asdf-vm but un rust" and one of the biggest highlighted feature is:

No shims - shims cause problems, they break which, and add overhead. By default, rtx does not use them—however you can if you want to.

I'm surprised jdx says that (below) while clearly taking position for hook in its README (above).

rtx should probably be PATH/shim since it can work just as well with shims—the rtx docs don't currently communicate this as well as they should though. It's been a sticking point for folks. I plan to show shims+PATH as 2 methods with their own pros/cons rather than promoting one over the other as it is today.

So as a user that is not nearly as familiar as people like you are, where can I read about the fundamental differences between SHIM and HOOk (and auxiliary about asdf-vm vs rtx)? As a user, I want to choose based on objective criteria and not because one tool is newer, more hyper or has more "stars" than the other.

@jdx
Copy link

jdx commented Nov 25, 2023

I don't think I've seen an authoritative, objective resource for this but I can offer some thoughts after having built rtx and dealing with problems with each. Perhaps I should write this up as a more formal blog post but you can at least have some extemporaneous thoughts.

To start, the main difference between hooks and shims is that shims execute the version manager every time the tool (e.g.: node) is called, but hooks execute each time cd is run or the prompt is displayed.

Where I've come down on this is that in general, I think the hook model works better in interactive setups, and shims work better in non-interactive setups. However this may be in part to the type of hook that rtx uses—some tools hook "cd" but rtx is hooked to prompt display (so effectively it can't work at all in a non-interactive setup since the prompt is never displayed).

I think hooking cd is a mistake though for one big reason: it won't run if a config file is edited. For example, if I do this in an interactive session it wouldn't work if only hooking cd:

echo "node 18" > .tool-versions
node -v

Related to that, I actually don't know how it would be possible to ever get that in a non-interactive setup to work with any hook. Shims are the only way I can think of to handle this kind of scenario. Another notable use-case is IDEs. With hooks, you'd have to write an extension for a version manager to use it in every IDE you want to support, but with shims you just need to add a directory to PATH.

So it seems shims have a lot of benefits, they are generally more "compatible" I would say, but I think the "feel" of working with hooks are better which is why I prefer it in an interactive environment. I think this is important enough to warrant having separate approaches for interactive and non-interactive sessions. If you prefer things to be consistent and don't care about the things I outline below you may prefer shims.

In an interactive environment, I like which to function. If all it does it spit out ~/.asdf/shims/node—that's not terribly helpful. I want to know the real path of the tool I'm using, not just a shim. Of course you can use asdf which but that requires knowing about that command and often results in which node and then noticing it uses a shim and remembering you need to use asdf which node. I like the more "native" feel of not needing that extra step.

I also hate that shims will be in use globally. For example, if I setup node to run in one project, then I will need to have ~/.asdf/shims/node be node no matter where I am—even in a project where I might want to use a different version manager. With hooks, we only add things to PATH where they're actually specified. So if a project doesn't use node, then node won't necessarily point to anything, it will naturally fall back to whatever is defined on the system if anything. In this way, hooks don't impact other projects where you might want to use a different setup. (note that with asdf you can use the system version but there are still problems with that like breaking which).

There is a performance consideration as well that generally is in favor of hooks over shims but not always. The version manager needs to execute whenever the hook is run or whenever the shim is called. Are you running cd or node more frequently? For most people this will be node (or whatever else you're running via asdf/rtx). For asdf this cost is significant but with rtx it's so negligible it's probably not worth your time to consider.

That said, the way rtx implements hooks does have some notable quirks that make some potential setups difficult if not impossible such as jdx/mise#863 where rtx is a bit aggressive with PATH modifications. You won't be able to override rtx if you're not using shims. Though that might also just be a place where I need to be more thoughtful about the design. In practice this doesn't seem to have been too big of an issue save for python where everything is pretty challenging.

Anyhow, it's all fairly complex and it's not easy to say which is better or worse, but I think in general for nearly all users you'll find the experience of hooks for interactive and shims for non-interactive to behave optimally.

@noraj
Copy link
Contributor

noraj commented Nov 25, 2023

Thanks for the detailed answer.

@laluka
Copy link

laluka commented Nov 27, 2023

Thanks so much @jdx for the very detailed answer!

I've been struggling a bit to integrate rtx in ansible, and the following part maid it really clear even if it's not what I was looking for here! 🌹

Related to that, I actually don't know how it would be possible to ever get that in a non-interactive setup to work with any hook. Shims are the only way I can think of to handle this kind of scenario. Another notable use-case is IDEs. With hooks, you'd have to write an extension for a version manager to use it in every IDE you want to support, but with shims you just need to add a directory to PATH.

Do you have a sample playbook that would let's say install python/pip and then run pip runs ? I have a few ideas to achieve this, but none are really convincing:

  • Having ansible to invoke bash to force the display hook to trigger and then run our commands
  • Force the sourcing of rtx before any command relying on it
  • Invoke unicorns to fix the playbook

What would be your approach for this?


More related to the comparaison project: It would be nice to add in the general comparaison grid two things: Documentation Quality, Ramp-Up Time, and Supported Features with some more detail, a few meta package managers only allow a few technologies to be installed/applied.
Maybe also Owner to know if it's a company, OS project, or one-man-army maintainer! :)

@jdx
Copy link

jdx commented Jan 8, 2024

sorry for the delay, I don't know too much about using it inside of ansible but I do know that @laluka is doing that in this project: https://github.com/laluka/lalubuntu. You might be able to find out from there.

@laluka
Copy link

laluka commented Jan 9, 2024

@jdx hard morning ? 🤣

You literraly suggested me to help myself by having a look at my project.. 😆

@jdx
Copy link

jdx commented Jan 9, 2024

Wow, lol! I didn't even look at who wrote that

@laluka
Copy link

laluka commented Jan 9, 2024

image

@Stratus3D
Copy link
Member

Excellent explanation in #1565 (comment) @jdx ! I'd love that to be a blog post of yours, or something we could cite in a more official manner.

@jdx
Copy link

jdx commented Feb 1, 2024

I've actually been coming back to this to reference myself in other discussions! I think I should!

@yatharth
Copy link

yatharth commented Apr 9, 2024

Echoing that #1565 (comment) finally helped me grasp implications of shims vs hooks for mise.

@jdx Would have loved to see it included in the jtx/mise repo README or the docs website somewhere!

@laluka
Copy link

laluka commented Apr 12, 2024

Came back to this one, once again, every time I re-read it it tastes different yet still amazed by the various approaches & hook types!
Is the blogpost in your pipe yet @jdx ? ;)

@jdx
Copy link

jdx commented Apr 12, 2024

@laluka https://jdx.dev/posts/2024-04-13-shims-how-they-work-in-mise-en-place/

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

No branches or pull requests

6 participants