Search code examples
performancegit-bashminttytput

tput is very slow on MinTTY (Git Bash)


Git Bash is pretty sluggish overall (compare 1.082s of average runtime under WSL/Ubuntu vs 4.460s in MinTTY). I've narrowed down a whopping 1.479s to the following chunk of code:

# Determine if this terminal supports colors
if test -t 1; then
    if [[ -n "$(tput colors)" ]] && [[ "$(tput colors)" -ge 8 ]]; then
        MY_APP_FMT_SUPPORTED=true

        MY_APP_FMT_BOLD="$(tput bold)"
        MY_APP_FMT_UNDERLINE="$(tput smul)"
        MY_APP_FMT_INVERSE="$(tput smso)"
        MY_APP_FMT_BLACK="$(tput setaf 0)"
        MY_APP_FMT_RED="$(tput setaf 1)"
        MY_APP_FMT_GREEN="$(tput setaf 2)"
        MY_APP_FMT_YELLOW="$(tput setaf 3)"
        MY_APP_FMT_BLUE="$(tput setaf 4)"
        MY_APP_FMT_MAGENTA="$(tput setaf 5)"
        MY_APP_FMT_CYAN="$(tput setaf 6)"
        MY_APP_FMT_WHITE="$(tput setaf 7)"

        MY_APP_FMT_CODE=$MY_APP_FMT_CYAN

        # placing it down below so that option -x doesn't cause bad highlighting
        # to persist
        MY_APP_FMT_CLEAR="$(tput sgr0)"
    fi
fi

Given my understanding of the performance of *nix tools on Windows, I suspect the slowdown is from all the subshells.

  • Should these subshells explain the entire slowdown? If not, I'll need to continue researching why Git Bash is still sluggish.
  • Is there a more performant way to do this while maintaining terminal compatibility?

Solution

  • You can group tput calls by using -S option:

    #!/usr/bin/env bash
    
    tkeys=(bold smul "setaf 0" "setaf 1") # You can add the rest
    
    tvalues_s=$(tput -S < <(printf "%s\n" "${tkeys[@]}"))
    
    declare -a tvalues=( ${tvalues_s//$'\e'/ $'\e'} )
    
    declare -p tvalues
    

    Now that you have values in tvalues, which you can assign to MY_APP_FMT_...