Ah! I finally have a progress bar that doesn't stall the build!

- pipe size in Linux is only 8*512=4096 bytes
 - pipe size is not setable
 - when the feeding process spits out data faster than the eating
   process can read it, then the feeding process stalls after 4KiB
   of data sent to the pipe
 - for us, the progress bar would spawn a sub-shell every line,
   and the sub-shell would in turn spawn a 'date' command.
   Which was sloooww as hell, and would cause some kind of a
   starvation: the pipe was full most of the time, and the
   feeding process was stalled all this time.

Now, we use internal variables and a little hack based onan offset
to determine the elapsed time. Much faster this way, but still
CPU-intensive.
This commit is contained in:
Yann E. MORIN" 2007-05-20 13:48:26 +00:00
parent 5d2b862edc
commit 4fb8055bf7
3 changed files with 29 additions and 22 deletions

View File

@ -255,13 +255,15 @@ config LOG_PROGRESS_BAR
default n
depends on ! LOG_ALL
help
This option will print a "rotating bar" (/-\|) below the last log line
to show work is not stalled.
If you say 'y' here, you'll be able to see the elapsed time.
Available when not in DEBUG log level.
WARNING! Very CPU intensive! If you have spare CPU, then you can use it,
otherwise, refrain from using it.
As a bonus, you'll also get a rotating bar (/-\|) showing you
that the build is not stalled (the bar rotates 1/4 every 10 lines
of components build log).
Note that the elapsed time can stall for a little while if a
component has long commands, as the elapsed time is only updated
each line.
config LOG_TO_FILE
bool

View File

@ -27,8 +27,12 @@ fi
CT_STAR_DATE=`CT_DoDate +%s%N`
CT_STAR_DATE_HUMAN=`CT_DoDate +%Y%m%d.%H%M%S`
# Log to a temporary file until we have built our environment
CT_ACTUAL_LOG_FILE="${CT_TOP_DIR}/$$.log"
# Log policy:
# - what goes to the log file goes to fd #1 (stdout)
# - what goes to the screen goes to fd #6
tmp_log_file="${CT_TOP_DIR}/$$.log"
exec 6>&1
exec >>"${tmp_log_file}"
# Are we configured? We'll need that later...
CT_TestOrAbort "Configuration file not found. Please create one." -f "${CT_TOP_DIR}/.config"
@ -182,22 +186,22 @@ mkdir -p "${CT_CC_CORE_PREFIX_DIR}"
# It's quite understandable that the log file will be installed in the install
# directory, so we must first ensure it exists and is writeable (above) before
# we can log there
exec >/dev/null
case "${CT_LOG_TO_FILE},${CT_LOG_FILE}" in
,*) rm -f "${CT_ACTUAL_LOG_FILE}"
CT_ACTUAL_LOG_FILE=/dev/null
,*) rm -f "${tmp_log_file}"
;;
y,/*) mkdir -p "`dirname \"${CT_LOG_FILE}\"`"
mv "${CT_ACTUAL_LOG_FILE}" "${CT_LOG_FILE}"
CT_ACTUAL_LOG_FILE="${CT_LOG_FILE}"
mv "${tmp_log_file}" "${CT_LOG_FILE}"
exec >>"${CT_LOG_FILE}"
;;
y,*) mkdir -p "`pwd`/`dirname \"${CT_LOG_FILE}\"`"
mv "${CT_ACTUAL_LOG_FILE}" "`pwd`/${CT_LOG_FILE}"
CT_ACTUAL_LOG_FILE="`pwd`/${CT_LOG_FILE}"
mv "${tmp_log_file}" "`pwd`/${CT_LOG_FILE}"
exec >>"${CT_LOG_FILE}"
;;
esac
# Determine build system if not set by the user
CT_Test "You did not specify the build system. Guessing." -z "${CT_BUILD}"
CT_Test "You did not specify the build system. That's OK, I can guess..." -z "${CT_BUILD}"
CT_BUILD="`${CT_TOP_DIR}/tools/config.sub \"${CT_BUILD:-\`${CT_TOP_DIR}/tools/config.guess\`}\"`"
# Arrange paths depending on wether we use sys-root or not.

View File

@ -12,7 +12,7 @@ CT_OnError() {
for((depth=2; ${BASH_LINENO[$((${depth}-1))]}>0; depth++)); do
CT_DoLog ERROR " called from \"${BASH_SOURCE[${depth}]}\" at line # ${BASH_LINENO[${depth}-1]} in function \"${FUNCNAME[${depth}]}\""
done
CT_DoLog ERROR "Look at \"${CT_ACTUAL_LOG_FILE}\" for more info on this error."
[ "${CT_LOG_TO_FILE}" = "y" ] && CT_DoLog ERROR "Look at \"${CT_LOG_FILE}\" for more info on this error."
CT_STEP_COUNT=1
CT_DoEnd ERROR
exit $ret
@ -54,30 +54,31 @@ CT_DoLog() {
cat -
else
echo "${1}"
fi |( IFS="\n" # We want the full lines, even leading spaces
fi |( offset=$((`CT_DoDate +%s`+(CT_STAR_DATE/(1000*1000*1000))))
IFS="\n" # We want the full lines, even leading spaces
CT_PROG_BAR_CPT=0
indent=$((2*CT_STEP_COUNT))
while read line; do
case "${CT_LOG_SEE_TOOLS_WARN},${line}" in
y,*"warning:"*) cur_L=WARN; cur_l=${CT_LOG_LEVEL_WARN};;
y,*"WARNING:"*) cur_L=WARN; cur_l=${CT_LOG_LEVEL_WARN};;
*"error:"*) cur_L=ERROR; cur_l=${CT_LOG_LEVEL_ERROR};;
*"make["?*"]:"*"Stop.") cur_L=ERROR; cur_l=${CT_LOG_LEVEL_ERROR};;
*) cur_L="${LEVEL}"; cur_l="${level}";;
esac
l="`printf \"[%-5s]%*s%s%s\" \"${cur_L}\" \"${indent}\" \" \" \"${line}\"`"
# There will always be a log file, be it /dev/null
echo -e "${l}" >>"${CT_ACTUAL_LOG_FILE}"
echo -e "${l}"
if [ ${cur_l} -le ${max_level} ]; then
echo -e "\r${l}"
echo -e "\r${l}" >&6
fi
if [ "${CT_LOG_PROGRESS_BAR}" = "y" ]; then
str=`CT_DoDate +%s`
elapsed=$((str-(CT_STAR_DATE/(1000*1000*1000))))
elapsed=$((SECONDS+OFFSET))
[ ${CT_PROG_BAR_CPT} -eq 0 ] && bar="/"
[ ${CT_PROG_BAR_CPT} -eq 10 ] && bar="-"
[ ${CT_PROG_BAR_CPT} -eq 20 ] && bar="\\"
[ ${CT_PROG_BAR_CPT} -eq 30 ] && bar="|"
printf "\r[%02d:%02d] %s " $((elapsed/60)) $((elapsed%60)) "${bar}"
printf "\r[%02d:%02d] %s " $((elapsed/60)) $((elapsed%60)) "${bar}" >&6
CT_PROG_BAR_CPT=$(((CT_PROG_BAR_CPT+1)%40))
fi
done