From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from lists.gentoo.org (pigeon.gentoo.org [208.92.234.80]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by finch.gentoo.org (Postfix) with ESMTPS id 3A34C15817D for ; Fri, 21 Jun 2024 13:14:25 +0000 (UTC) Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id 6C697E2AAA; Fri, 21 Jun 2024 13:14:20 +0000 (UTC) Received: from smtp.gentoo.org (mail.gentoo.org [IPv6:2001:470:ea4a:1:5054:ff:fec7:86e4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by pigeon.gentoo.org (Postfix) with ESMTPS id 50D75E2AAD for ; Fri, 21 Jun 2024 13:14:20 +0000 (UTC) Received: from oystercatcher.gentoo.org (oystercatcher.gentoo.org [148.251.78.52]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by smtp.gentoo.org (Postfix) with ESMTPS id 43E8A33BF28 for ; Fri, 21 Jun 2024 13:14:19 +0000 (UTC) Received: from localhost.localdomain (localhost [IPv6:::1]) by oystercatcher.gentoo.org (Postfix) with ESMTP id B12821D5C for ; Fri, 21 Jun 2024 13:14:15 +0000 (UTC) From: "Sam James" To: gentoo-commits@lists.gentoo.org Content-Transfer-Encoding: 8bit Content-type: text/plain; charset=UTF-8 Reply-To: gentoo-dev@lists.gentoo.org, "Sam James" Message-ID: <1718324862.72b754bb11066b10ae14b8f017f93ad5c62e7467.sam@gentoo> Subject: [gentoo-commits] proj/gentoo-functions:master commit in: / X-VCS-Repository: proj/gentoo-functions X-VCS-Files: functions.sh X-VCS-Directories: / X-VCS-Committer: sam X-VCS-Committer-Name: Sam James X-VCS-Revision: 72b754bb11066b10ae14b8f017f93ad5c62e7467 X-VCS-Branch: master Date: Fri, 21 Jun 2024 13:14:15 +0000 (UTC) Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-commits@lists.gentoo.org X-Auto-Response-Suppress: DR, RN, NRN, OOF, AutoReply X-Archives-Salt: 4acb70c9-d7f2-4357-b94a-bbf5bb7951ee X-Archives-Hash: e2c89046b6eed835980403b7c24ae7b4 commit: 72b754bb11066b10ae14b8f017f93ad5c62e7467 Author: Kerin Millar plushkava net> AuthorDate: Sat Jun 8 15:44:32 2024 +0000 Commit: Sam James gentoo org> CommitDate: Fri Jun 14 00:27:42 2024 +0000 URL: https://gitweb.gentoo.org/proj/gentoo-functions.git/commit/?id=72b754bb Throttle the rate at which genfun_cols may be refreshed Limit the rate at which genfun_cols can be refreshed to intervals that are no shorter than 5 decisconds (half a second). Doing so renders repeated calls to the _eend() function at short intervals faster by an order of magnitude. On one of my fastest available machines, I performed the following benchmark with bash 5.2.26. $ time for ((i=0; i<50000; i++)); do ebegin "$i"; eend; done The results were as follows. BEFORE real 0m56.897s user 0m16.990s sys 0m28.540s AFTER real 0m6.663s user 0m6.435s sys 0m0.191s On one of my slowest available machines, I performed the following benchmark with bash 5.2.26. $ time for ((i=0; i<15000; i++)); do ebegin "$i"; eend; done The results were as follows. BEFORE real 0m52.557s user 0m34.484s sys 0m18.231s AFTER real 0m11.422s user 0m10.654s sys 0m0.535s On that same (slow) machine, I performed the following benchmark with dash 0.5.12. $ time dash -c ' . ./functions.sh while :; do ebegin $((i+=1)); eend; [ $i -eq 15000 ] && exit; done' The results were as follows. BEFORE real 0m43.762s user 0m22.202s sys 0m21.415s AFTER real 0m3.470s user 0m2.535s sys 0m0.736s Signed-off-by: Kerin Millar plushkava.net> functions.sh | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 78 insertions(+), 3 deletions(-) diff --git a/functions.sh b/functions.sh index fcba801..52224a5 100644 --- a/functions.sh +++ b/functions.sh @@ -19,6 +19,7 @@ # EINFO_LOG : whether printing functions should call esyslog() # EINFO_QUIET : whether info message printing functions should be silenced # EINFO_VERBOSE : whether v-prefixed functions should do anything +# EPOCHREALTIME : potentially used by _update_time() to get the time # IFS : multiple message operands are joined by its first character # INSIDE_EMACS : whether to work around an emacs-specific bug in _eend() # NO_COLOR : whether colored output should be suppressed @@ -919,16 +920,37 @@ _select_by_mtime() { | { IFS= read -r line && printf '%s\n' "${line#* }"; } } +# +# Considers the first parameter as a number of deciseconds and determines +# whether fewer have elapsed since the last occasion on which the function was +# called. +# +_should_throttle() +{ + _update_time || return + if [ "$(( genfun_time - genfun_last_time > $1 ))" -eq 1 ]; then + genfun_last_time=${genfun_time} + false + fi +} + # # Determines whether the terminal on STDIN is able to report its dimensions. # Upon success, the number of columns shall be stored in genfun_cols. # _update_columns() { - # Command substitutions are rather slow in bash. Using the COLUMNS - # variable helps but checkwinsize won't work properly in subshells. + # Two optimisations are applied. Firstly, the rate at which updates can + # be performed is throttled to intervals of 5 deciseconds. Secondly, if + # running on bash then the COLUMNS variable may be gauged, albeit only + # in situations where doing so can be expected to work reliably; not if + # in a subshell. Note that executing true(1) is faster than executing + # stty(1) within a comsub. # shellcheck disable=3028,3044 - if [ "$$" = "${BASHPID}" ] && shopt -q checkwinsize; then + if _should_throttle 5; then + test "${genfun_cols}" + return + elif [ "$$" = "${BASHPID}" ] && shopt -q checkwinsize; then "${genfun_bin_true}" set -- 0 "${COLUMNS}" else @@ -942,6 +964,59 @@ _update_columns() [ "$#" -eq 2 ] && is_int "$2" && [ "$2" -gt 0 ] && genfun_cols=$2 } +# +# Determines either the number of deciseconds elapsed since the unix epoch or +# the number of deciseconds that the operating system has been online, depending +# on the capabilities of the shell and/or platform. Upon success, the obtained +# value shall be assigned to genfun_time. Otherwise, the return value shall be +# greater than 0. +# +_update_time() +{ + genfun_last_time=0 + + # shellcheck disable=3028 + if [ "${BASH_VERSINFO:-0}" -ge 5 ]; then + # shellcheck disable=2034,3045 + _update_time() + { + local ds s timeval + + timeval=${EPOCHREALTIME} + s=${timeval%.*} + printf -v ds '%.1f' ".${timeval#*.}" + if [ "${ds}" = "1.0" ]; then + ds=10 + else + ds=${ds#0.} + fi + genfun_time=$(( s * 10 + ds )) + } + elif [ -f /proc/uptime ]; then + _update_time() + { + local ds s timeval + + IFS=' ' read -r timeval _ < /proc/uptime || return + s=${timeval%.*} + printf -v ds '%.1f' ".${timeval#*.}" + if [ "${ds}" = "1.0" ]; then + ds=10 + else + ds=${ds#0.} + fi + genfun_time=$(( s * 10 + ds )) + } + else + _update_time() + { + false + } + fi + + _update_time +} + # # Grades the capability of the terminal attached to STDIN, assigning the level # to genfun_tty. If no terminal is detected, the level shall be 0. If a dumb