loading...
Cover image for My terminal is procrastinating πŸ™„

My terminal is procrastinating πŸ™„

omrilotan profile image omrilotan ・2 min read

Reduce terminal instance boot time

I am a performance and observability enthusiast. I am also extremely impatient. This combination of traits drives me to find ways to accelerate any process that takes even a tiny bit longer than absolute necessary.

I made my terminal boot procrastinate for efficiency!

I want my terminal to perform operations only when they are required. I already measure everything that my bashrc runs. So I picked the scripts from my bashrc who take the longest to run, and turned them into on-demand commands.

thefuck

This one was easy.

thefuck is brilliant in correcting your previous console command, but the setup takes me nearly 700ms on average. Unthinkable!

Instead of setting it up up front when terminal instance boots up - I prefer to set it up when I need it. So I set up this idempotent function:

function fuck {
    eval "$(thefuck --alias)"
    eval "fuck $@"
}

First time I call fuck in an instance it performs the following operations:

  1. Setup thefuck with fuck alias (overrides this function).
  2. Trigger fuck with all the passed in arguments.

So initial setup time is reduced to 20ms and usage gets the hit of 700ms later, on demand. Second call will not take that hit.

nvm

Now, nvm I use more often - but it cost me over a whopping 1.5 seconds. It also is a bit trickier - because it loads up an environment, not just a command.

I chose to add this idem potency to the four major commands I use: node, npm, npx, nvm - but you can easily add more.

Each one of the commands is set up to:

  1. Unset all commands in the list (plus the nvm_load command)
  2. Load up nvm
  3. Call the original command with all arguments
if [ -f ".nvmrc" ]; then
    # Load NVM if needed
    source "$HOME/.nvm/nvm.sh"
else
    # Set up NVM loaders
    nodecommands=(nvm npm npx node)
    function nvm_load {
        # Unset all node command decorators
        for nodecommand in "${nodecommands[@]}"; do
            eval "unset -f ${nodecommand}"
        done
        unset -f nvm_load
        if [[ -s "$HOME/.nvm/nvm.sh" ]]; then
            echo "Loading NVM"
            source "$HOME/.nvm/nvm.sh"
        else
            echo "Can't find nvm script"
        fi
    }
    # All node commands should load NVM first
    for nodecommand in "${nodecommands[@]}"; do
        eval "function ${nodecommand} { nvm_load; ${nodecommand} \$@; }"
    done
fi

The draw back is that globally installed NPM packages won't work until you explicitly call one of these method names. On the other hand - you can add anything to the list if there's a command you use often and want to join the party (yarn etc).

There you go, NVM reduced to 80ms and will only take up your time when needed.

Now that NVM is not included by default, we also need to set it up when entering a directory that contains a .nvmrc file.

cd() {
    dir=$@
    : ${dir:=~}

    builtin cd $dir
    if [ -f ".nvmrc" ]; then
        nvm use
    fi
}


What do you think? Anything slowing you down loading up a terminal instance?

Posted on by:

omrilotan profile

omrilotan

@omrilotan

β˜• I woke up like this

Discussion

pic
Editor guide
 

Regarding nvm, you might consider taking a look at fnm. They seem to improve speed significantly.
github.com/Schniz/fnm