Skip to content

Makeself script slow for large archives in versions 2.4.2+ #344

@tonygoldman

Description

@tonygoldman

Use case

I created a makeself archive to flash an Nvidia Jetson.
The makeself size is about 6Gb and contains a Linux filesystem and a flashing script.

Version 2.4.0

Makeself build takes 10 seconds and utilizes all cores simultaniously for compression.

In version 2.4.0 tar is piped directly to the compression program allowing fast and simultanious compression.

exec 3<> "$tmpfile"
( cd "$archdir" && ( tar $TAR_EXTRA -$TAR_ARGS - . | eval "$GZIP_CMD" >&3 ) ) || \
    { echo Aborting: archive directory not found or temporary file: "$tmpfile" could not be created.; exec 3>&-; rm -f "$tmpfile"; exit 1; }
exec 3>&- # try to close the archive

Version 2.4.2 - 2.5.0

Makeself build takes 140 seconds, and only a single core is utilized, except for 10 seconds near the end of the build.

In version 2.4.2+ an empty archive is updated in a loop for each file, unefficient for large archives.
Furthermore, compression only occurs later in the script, removing the advantage of simultanious archiving and compression.

tmparch="${TMPDIR:-/tmp}/mkself$$.tar"
(
    if test "$APPEND" = "y"; then
        tail -n "+$OLDSKIP" "$archname" | eval "$GUNZIP_CMD" > "$tmparch"
    fi
    cd "$archdir"
    # "Determining if a directory is empty"
    # https://www.etalabs.net/sh_tricks.html
    find . \
        \( \
        ! -type d \
        -o \
        \( -links 2 -exec sh -c '
            is_empty () (
                cd "$1"
                set -- .[!.]* ; test -f "$1" && return 1
                set -- ..?* ; test -f "$1" && return 1
                set -- * ; test -f "$1" && return 1
                return 0
            )
            is_empty "$0"' {} \; \
        \) \
        \) -print \
        | LC_ALL=C sort \
        | sed 's/./\\&/g' \
        | xargs $TAR $TAR_EXTRA --format $TAR_FORMAT -$TAR_ARGS "$tmparch"
) || {
    echo "ERROR: failed to create temporary archive: $tmparch"
    rm -f "$tmparch" "$tmpfile"
    exit 1
}

USIZE=`du $DU_ARGS "$tmparch" | awk '{print $1}'`

eval "$GZIP_CMD" <"$tmparch" >"$tmpfile" || {
    echo "ERROR: failed to create temporary file: $tmpfile"
    rm -f "$tmparch" "$tmpfile"
    exit 1
}
rm -f "$tmparch"

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions