From f659ba2ea23d46af4a3d770c08f3f3d0baf2151f Mon Sep 17 00:00:00 2001 From: neil Date: Thu, 15 Oct 2026 15:03:18 +0800 Subject: [PATCH] Skip conf writes that change nothing Since #7278 every conf write is a temp file plus a rename, and _setopt and _clear_conf rewrote the conf even when the content stayed the same: _savedeployconf clears a legacy key that is almost never there, and deploy hooks re-save the same values on every run. On storage where file creation and rename are expensive (ZFS on HDD) a multideploy run went from about 23 seconds to over 2 minutes. Return early when the new content equals the old one. A simulated 3-service docker multideploy drops from 96 conf writes to 32. Fixes #7335 --- acme.sh | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/acme.sh b/acme.sh index ccd34b18..e1a35075 100755 --- a/acme.sh +++ b/acme.sh @@ -2914,6 +2914,7 @@ _setopt() { _err "Cannot read $__conf." return 1 fi + __old_text="$__text" #build the new content first and write it once through _write_conf: #redirecting straight into the conf truncates it before anything is #written, so a failing sed (#2426) or a failing write (#7247) left a @@ -2930,6 +2931,13 @@ _setopt() { _debug3 APP __text="$__text${__text:+$__nl}$__opt$__sep$__val$__end" fi + if [ -z "$__sed_err" ] && [ "$__text" = "$__old_text" ]; then + #the value is already saved: callers re-save the same values on every + #run, and each write is a temp file plus a rename, which is slow on + #some storage (#7335) + _debug3 "Unchanged, skip writing $__conf" + return 0 + fi if [ "$__sed_err" ] || ! _write_conf "$__conf" "$__text"; then _err "Cannot save '$__opt' to $__conf." return 1 @@ -2959,11 +2967,19 @@ _clear_conf() { _c_c_f="$1" _sdkey="$2" if [ "$_c_c_f" ]; then - _conf_data="$(cat "$_c_c_f")" + _c_c_old="$(cat "$_c_c_f")" #printf, not echo: dash's builtin echo interprets backslash escapes and #would corrupt saved values that contain them on every rewrite - if ! _conf_data="$(printf -- "%s\n" "$_conf_data" | sed "/^$_sdkey *=.*$/d")" || - ! _write_conf "$_c_c_f" "$_conf_data"; then + if ! _conf_data="$(printf -- "%s\n" "$_c_c_old" | sed "/^$_sdkey *=.*$/d")"; then + _err "Cannot clear '$_sdkey' in $_c_c_f." + return 1 + fi + #the key is not there, the usual case for the legacy keys cleared on + #every _savedeployconf: nothing to write (#7335) + if [ "$_conf_data" = "$_c_c_old" ]; then + return 0 + fi + if ! _write_conf "$_c_c_f" "$_conf_data"; then _err "Cannot clear '$_sdkey' in $_c_c_f." return 1 fi