Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 56 additions & 53 deletions contrib/development/perf_interpreters.sh
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
# https://bwipp.terryburton.co.uk
#
# Copyright (c) 2004-2026 Terry Burton

#
# Compare interpreter performance on representative barcode generation
# workloads: encode-only (dontdraw) and full rendering, for small and
Expand All @@ -29,7 +28,10 @@ DISTILLER_HOST=${DISTILLER_HOST:-}
REPS=${REPS:-3}

MONOLITHIC="$ROOT/build/monolithic/barcode.ps"
[ -f "$MONOLITHIC" ] || { echo "missing $MONOLITHIC (run make first)"; exit 1; }
[ -f "$MONOLITHIC" ] || {
echo "missing $MONOLITHIC (run make first)"
exit 1
}

WORK=$(mktemp -d)
trap 'rm -rf "$WORK"' EXIT
Expand All @@ -49,69 +51,70 @@ CASESEOF
)

body() { # encoder data options render monolithic-path
if [ "$4" = "encode" ]; then
printf 'currentglobal true setglobal\n'
printf '/uk.co.terryburton.bwipp.global_ctx << /enabledontdraw true >> def\n'
printf 'setglobal\n'
fi
printf '(%s) run\n' "$5"
printf '10 10 moveto (%s) (%s) /%s /uk.co.terryburton.bwipp findresource exec\n' \
"$2" "$([ "$4" = encode ] && printf 'dontdraw %s' "$3" || printf '%s' "$3")" "$1"
[ "$4" = "encode" ] && printf 'pop\n' || printf 'showpage\n'
printf '(CASE-DONE\\n) print flush\n'
if [ "$4" = "encode" ]; then
printf 'currentglobal true setglobal\n'
printf '/uk.co.terryburton.bwipp.global_ctx << /enabledontdraw true >> def\n'
printf 'setglobal\n'
fi
printf '(%s) run\n' "$5"
printf '10 10 moveto (%s) (%s) /%s /uk.co.terryburton.bwipp findresource exec\n' \
"$2" "$([ "$4" = encode ] && printf 'dontdraw %s' "$3" || printf '%s' "$3")" "$1"
[ "$4" = "encode" ] && printf 'pop\n' || printf 'showpage\n'
printf '(CASE-DONE\\n) print flush\n'
}

best() { # fastest of REPS runs of "$@"
local t best=""
for _ in $(seq "$REPS"); do
t=$( { /usr/bin/time -f %e "$@" >/dev/null; } 2>&1 | tail -1)
if [ -z "$best" ] || \
[ "$(printf '%s\n%s\n' "$t" "$best" | sort -g | head -1)" = "$t" ]; then
best=$t
fi
done
printf '%s' "$best"
local t best=""
for _ in $(seq "$REPS"); do
t=$( { /usr/bin/time -f %e "$@" >/dev/null; } 2>&1 | tail -1)
if [ -z "$best" ] || \
[ "$(printf '%s\n%s\n' "$t" "$best" | sort -g | head -1)" = "$t" ]; then
best=$t
fi
done
printf '%s' "$best"
}

if [ -n "$DISTILLER_HOST" ]; then
echo "provisioning Distiller cases on $DISTILLER_HOST"
ssh "$DISTILLER_HOST" 'New-Item -ItemType Directory -Force -Path C:\bwipp-test\perf | Out-Null'
scp -q "$MONOLITHIC" "$DISTILLER_HOST:C:/bwipp-test/perf/barcode.ps"
scp -q "$ROOT/tests/distiller_tests/fontalias.ps" "$DISTILLER_HOST:C:/bwipp-test/perf/"
cat > "$WORK/time-one.ps1" <<-'PS1EOF'
param([string]$File)
$sw = [Diagnostics.Stopwatch]::StartNew()
$p = Start-Process -FilePath C:\bwipp-test\Distiller\acrodist.exe -ArgumentList "/N","/Q",$File -PassThru -WorkingDirectory C:\bwipp-test\Distiller -WindowStyle Hidden
$null = $p.WaitForExit(300000)
$sw.Stop()
"{0:0.00}" -f $sw.Elapsed.TotalSeconds
PS1EOF
scp -q "$WORK/time-one.ps1" "$DISTILLER_HOST:C:/bwipp-test/perf/"
echo "provisioning Distiller cases on $DISTILLER_HOST"
ssh "$DISTILLER_HOST" 'New-Item -ItemType Directory -Force -Path C:\bwipp-test\perf | Out-Null'
scp -q "$MONOLITHIC" "$DISTILLER_HOST:C:/bwipp-test/perf/barcode.ps"
scp -q "$ROOT/tests/distiller_tests/fontalias.ps" "$DISTILLER_HOST:C:/bwipp-test/perf/"
cat >"$WORK/time-one.ps1" <<'PS1EOF'
param([string]$File)
$sw = [Diagnostics.Stopwatch]::StartNew()
$p = Start-Process -FilePath C:\bwipp-test\Distiller\acrodist.exe -ArgumentList "/N","/Q",$File -PassThru -WorkingDirectory C:\bwipp-test\Distiller -WindowStyle Hidden
$null = $p.WaitForExit(300000)
$sw.Stop()
"{0:0.00}" -f $sw.Elapsed.TotalSeconds
PS1EOF
scp -q "$WORK/time-one.ps1" "$DISTILLER_HOST:C:/bwipp-test/perf/"
fi

printf '%-12s %8s' case gs
[ -n "$XPOST" ] && printf ' %8s' xpost
[ -n "$DISTILLER_HOST" ] && printf ' %10s' distiller
printf '\n'


echo "$CASES" | while IFS='|' read -r name enc data opts render; do
body "$enc" "$data" "$opts" "$render" "$MONOLITHIC" > "$WORK/$name.ps"
g=$(best "$GS" -q -dNOSAFER -dNOPAUSE -dBATCH -sDEVICE=nullpage "$WORK/$name.ps" < /dev/null)
printf '%-12s %8s' "$name" "$g"
if [ -n "$XPOST" ]; then
{ printf '(%s) run\n' "$ROOT/tests/xpost_tests/shim.ps"
cat "$WORK/$name.ps"; printf 'quit\n'; } > "$WORK/$name.xp.ps"
x=$(best "$XPOST" -q -d null "$WORK/$name.xp.ps" < /dev/null)
printf ' %8s' "$x"
fi
if [ -n "$DISTILLER_HOST" ]; then
{ printf '%%!PS-Adobe-3.0\n(C:/bwipp-test/perf/fontalias.ps) run\n'
sed "s|($MONOLITHIC) run|(C:/bwipp-test/perf/barcode.ps) run|" "$WORK/$name.ps"
} > "$WORK/$name.dist.ps"
scp -q "$WORK/$name.dist.ps" </dev/null "$DISTILLER_HOST:C:/bwipp-test/perf/$name.ps"
d=$(ssh -n "$DISTILLER_HOST" "powershell -ExecutionPolicy Bypass -File C:\\bwipp-test\\perf\\time-one.ps1 C:\\bwipp-test\\perf\\$name.ps" | tr -d '\r')
printf ' %10s' "$d"
fi
printf '\n'
body "$enc" "$data" "$opts" "$render" "$MONOLITHIC" >"$WORK/$name.ps"
g=$(best "$GS" -q -dNOSAFER -dNOPAUSE -dBATCH -sDEVICE=nullpage "$WORK/$name.ps" < /dev/null)
printf '%-12s %8s' "$name" "$g"
if [ -n "$XPOST" ]; then
{ printf '(%s) run\n' "$ROOT/tests/xpost_tests/shim.ps"
cat "$WORK/$name.ps"
printf 'quit\n'
} >"$WORK/$name.xp.ps"
x=$(best "$XPOST" -q -d null "$WORK/$name.xp.ps" < /dev/null)
printf ' %8s' "$x"
fi
if [ -n "$DISTILLER_HOST" ]; then
{ printf '%%!PS-Adobe-3.0\n(C:/bwipp-test/perf/fontalias.ps) run\n'
sed "s|($MONOLITHIC) run|(C:/bwipp-test/perf/barcode.ps) run|" "$WORK/$name.ps"
} >"$WORK/$name.dist.ps"
scp -q "$WORK/$name.dist.ps" </dev/null "$DISTILLER_HOST:C:/bwipp-test/perf/$name.ps"
d=$(ssh -n "$DISTILLER_HOST" "powershell -ExecutionPolicy Bypass -File C:\\bwipp-test\\perf\\time-one.ps1 C:\\bwipp-test\\perf\\$name.ps" | tr -d '\r')
printf ' %10s' "$d"
fi
printf '\n'
done
12 changes: 6 additions & 6 deletions tests/distiller_tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,12 @@ pwsh tests/distiller_tests/run.ps1 `
```

| `run.ps1` parameter | Default | Purpose |
|---------------------|------------------|----------------------------------|
| `-Distiller` | `$env:ACRODIST` | path to `acrodist.exe` |
| `-Monolithic` | repo build path | built `barcode.ps` |
| `-Timeout` | `900` | per-file timeout in seconds |
| `-Skip` | *(empty)* | test names to skip |
| `-Filter` | `*` | restrict to matching test names |
| ------------------- | ---------------- | -------------------------------- |
| `-Distiller` | `$env:ACRODIST` | path to `acrodist.exe` |
| `-Monolithic` | repo build path | built `barcode.ps` |
| `-Timeout` | `900` | per-file timeout in seconds |
| `-Skip` | *(empty)* | test names to skip |
| `-Filter` | `*` | restrict to matching test names |

Prints `PASS`/`FAIL`/`SKIP` per file with a summary, and exits non-zero on
failure.
61 changes: 43 additions & 18 deletions tests/distiller_tests/assemble-distiller.sh
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,30 @@ OUT=${2:?usage: assemble-distiller.sh <Adobe Acrobat 5.0.1.7z> <output-dir>}
EXPECT_SHA256=${EXPECT_SHA256:-446c06ae42c4d71d0298188ad2587178708b58a0e04545efb4035078ec1b2477}

sevenzip=$(command -v 7z || command -v 7za || true)
[ -n "$sevenzip" ] || { echo "error: 7z/7za not found (apt install p7zip-full)" >&2; exit 1; }
command -v unshield >/dev/null 2>&1 || { echo "error: unshield not found (apt install unshield)" >&2; exit 1; }
command -v sha256sum >/dev/null 2>&1 || { echo "error: sha256sum not found" >&2; exit 1; }
[ -f "$ARCHIVE" ] || { echo "error: no such archive: $ARCHIVE" >&2; exit 1; }
[ -n "$sevenzip" ] || {
echo "error: 7z/7za not found (apt install p7zip-full)" >&2
exit 1
}
command -v unshield >/dev/null 2>&1 || {
echo "error: unshield not found (apt install unshield)" >&2
exit 1
}
command -v sha256sum >/dev/null 2>&1 || {
echo "error: sha256sum not found" >&2
exit 1
}
[ -f "$ARCHIVE" ] || {
echo "error: no such archive: $ARCHIVE" >&2
exit 1
}

echo "Verifying $ARCHIVE ..."
got=$(sha256sum "$ARCHIVE" | cut -d' ' -f1)
if [ "$got" != "$EXPECT_SHA256" ]; then
echo "error: checksum mismatch; refusing to proceed" >&2
echo " expected $EXPECT_SHA256" >&2
echo " got $got" >&2
exit 1
echo "error: checksum mismatch; refusing to proceed" >&2
echo " expected $EXPECT_SHA256" >&2
echo " got $got" >&2
exit 1
fi

TMP=$(mktemp -d)
Expand All @@ -51,13 +63,17 @@ echo "Extracting installer cabinet ..."
"$sevenzip" x -y -o"$TMP" "$ARCHIVE" -r data1.cab data1.hdr >/dev/null
CAB=$(find "$TMP" -name data1.cab | head -1)
[ -n "$CAB" ] && [ -f "$(dirname "$CAB")/data1.hdr" ] || {
echo "error: data1.cab / data1.hdr not found in archive" >&2; exit 1; }
echo "error: data1.cab / data1.hdr not found in archive" >&2
exit 1
}

echo "Assembling Distiller tree ..."
for g in "Distiller Program Files" "Distiller Win NT System files" \
"Distiller Settings English" "Fonts" "PSDisk"; do
unshield -g "$g" -d "$TMP/$g" x "$CAB" >/dev/null || {
echo "error: could not extract group '$g' (unexpected cabinet contents)" >&2; exit 1; }
"Distiller Settings English" "Fonts" "PSDisk"; do
unshield -g "$g" -d "$TMP/$g" x "$CAB" >/dev/null || {
echo "error: could not extract group '$g' (unexpected cabinet contents)" >&2
exit 1
}
done

D="$OUT/Distiller"
Expand All @@ -67,28 +83,37 @@ mkdir -p "$D/Font" "$D/Data"
# acrodist.exe + DLLs + Data/ (distinit.ps, DISTSADB.DOS, ...); locate by the
# binary so we are robust to how unshield names the destination directory.
pf=$(find "$TMP/Distiller Program Files" -name acrodist.exe -printf '%h\n' | head -1)
[ -n "$pf" ] || { echo "error: acrodist.exe not present in cabinet" >&2; exit 1; }
[ -n "$pf" ] || {
echo "error: acrodist.exe not present in cabinet" >&2
exit 1
}
cp -a "$pf/." "$D/"

find "$TMP/Distiller Win NT System files" -name 'PdfPorts.dll' -exec cp {} "$D/" \;
find "$TMP/Distiller Settings English" -type d -name Settings -exec cp -a {} "$D/" \;
find "$TMP/Distiller Settings English" -type d -name Startup -exec cp -a {} "$D/" \;
find "$TMP/Distiller Settings English" -type d -name Startup -exec cp -a {} "$D/" \;
find "$TMP/Fonts" -type f -iname '*.pfb' -exec cp {} "$D/Font/" \;

# psdisk resource tree -> Data/psdisk so distinit's relative GenericResourceDir
# (data/psdisk/Resource/) resolves; Windows resolves Data/ case-insensitively.
psd=$(find "$TMP/PSDisk" -type d -name psdisk | head -1)
[ -n "$psd" ] || { echo "error: psdisk resource tree not present in cabinet" >&2; exit 1; }
[ -n "$psd" ] || {
echo "error: psdisk resource tree not present in cabinet" >&2
exit 1
}
cp -a "$psd" "$D/Data/"

# Drop the external CMYK profile the job options reference, so Distiller needs
# no colour profile installed on the host (which would require elevation).
for jo in "$D"/Settings/*.joboptions; do
sed -i -e 's#/CalCMYKProfile (.*)#/CalCMYKProfile ()#' \
-e 's#/ColorConversionStrategy /[A-Za-z]*#/ColorConversionStrategy /LeaveColorUnchanged#' "$jo"
sed -i -e 's#/CalCMYKProfile (.*)#/CalCMYKProfile ()#' \
-e 's#/ColorConversionStrategy /[A-Za-z]*#/ColorConversionStrategy /LeaveColorUnchanged#' "$jo"
done

[ -f "$D/acrodist.exe" ] || { echo "error: assembly incomplete (no acrodist.exe)" >&2; exit 1; }
[ -f "$D/acrodist.exe" ] || {
echo "error: assembly incomplete (no acrodist.exe)" >&2
exit 1
}

echo "Assembled portable Distiller at: $D"
echo " dlls=$(ls "$D"/*.dll 2>/dev/null | wc -l) fonts=$(ls "$D/Font" 2>/dev/null | wc -l) psdisk=$([ -d "$D/Data/psdisk/Resource" ] && echo yes || echo no)"
Expand Down
24 changes: 15 additions & 9 deletions tests/distiller_tests/remote.sh
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,15 @@ ROOT=$(cd "$HERE/../.." && pwd)
MONO="$ROOT/build/monolithic/barcode.ps"
PSDIR="$ROOT/tests/ps_tests"

[ -f "$MONO" ] || { echo "error: missing $MONO (run: make monolithic)" >&2; exit 1; }
[ -f "$MONO" ] || {
echo "error: missing $MONO (run: make monolithic)" >&2
exit 1
}

# Reachability: skip cleanly rather than fail the caller if the host is down.
if ! ssh -o BatchMode=yes -o ConnectTimeout=10 "$HOST" "exit" >/dev/null 2>&1; then
echo "SKIPPED $HOST not reachable over SSH"
exit 0
echo "SKIPPED $HOST not reachable over SSH"
exit 0
fi

psh() { ssh -o BatchMode=yes "$HOST" "powershell -NoProfile -ExecutionPolicy Bypass -Command $1"; }
Expand All @@ -50,12 +53,15 @@ psh "New-Item -ItemType Directory -Force -Path '$REMOTE_DIR/tests/distiller_test
# Provision a portable Distiller when a source is supplied and it is absent
# (or FORCE is set).
if [ -n "$DIST_SRC" ]; then
[ -f "$DIST_SRC/acrodist.exe" ] || { echo "error: $DIST_SRC has no acrodist.exe" >&2; exit 1; }
present=$(psh "Test-Path '$ACRODIST'" | tr -d '\r')
if [ "$present" != "True" ] || [ -n "$FORCE" ]; then
echo "Provisioning Distiller -> $REMOTE_DIR/Distiller"
scp -q -o BatchMode=yes -r "$DIST_SRC" "$HOST:$REMOTE_DIR/"
fi
[ -f "$DIST_SRC/acrodist.exe" ] || {
echo "error: $DIST_SRC has no acrodist.exe" >&2
exit 1
}
present=$(psh "Test-Path '$ACRODIST'" | tr -d '\r')
if [ "$present" != "True" ] || [ -n "$FORCE" ]; then
echo "Provisioning Distiller -> $REMOTE_DIR/Distiller"
scp -q -o BatchMode=yes -r "$DIST_SRC" "$HOST:$REMOTE_DIR/"
fi
fi

# Push harness, tests and the freshly built monolithic.
Expand Down
22 changes: 13 additions & 9 deletions tests/distiller_tests/run.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ $ErrorActionPreference = "Continue"
$test = $PSScriptRoot
$root = (Resolve-Path (Join-Path $test "..\..")).Path
if (-not $Monolithic) { $Monolithic = Join-Path $root "build\monolithic\barcode.ps" }
$testsdir = Join-Path $root "tests\ps_tests"
$testutils = Join-Path $testsdir "test_utils.ps"
$fontalias = Join-Path $test "fontalias.ps"
$testsdir = Join-Path $root "tests\ps_tests"
$testutils = Join-Path $testsdir "test_utils.ps"
$fontalias = Join-Path $test "fontalias.ps"

# Treat a missing or bogus path as "interpreter not available" and skip.
if (-not $Distiller -or -not (Test-Path $Distiller)) {
Expand All @@ -49,8 +49,8 @@ $skipset = @($Skip -split '\s+' | Where-Object { $_ })
$work = Join-Path $env:TEMP ("distiller_tests_" + [guid]::NewGuid().ToString("N"))
New-Item -ItemType Directory -Force -Path $work | Out-Null

$faF = $fontalias -replace '\\','/'
$tuF = $testutils -replace '\\','/'
$faF = $fontalias -replace '\\','/'
$tuF = $testutils -replace '\\','/'
$moF = $Monolithic -replace '\\','/'

$files = Get-ChildItem (Join-Path $testsdir "$Filter.ps.test") | Sort-Object Name
Expand All @@ -76,13 +76,15 @@ try {

$sw = [Diagnostics.Stopwatch]::StartNew()
$p = Start-Process -FilePath $Distiller -ArgumentList "/N","/Q",$drv `
-PassThru -WorkingDirectory $distdir -WindowStyle Hidden
-PassThru -WorkingDirectory $distdir -WindowStyle Hidden
$ok = $p.WaitForExit($Timeout * 1000)
$sw.Stop()
$secs = "{0:0.00}" -f $sw.Elapsed.TotalSeconds

if (-not $ok) {
try { $p.Kill() } catch {}
try { $p.Kill() } catch {
Write-Error "Failed to stop timed-out Distiller process for $name"
}
Write-Output "FAIL $name (${secs}s)"
Write-Output " timeout after ${Timeout}s"
$failed++
Expand All @@ -94,14 +96,16 @@ try {
$t -notmatch "testError|stackImbalance|dict leak|global VM leak|%%\[ Error") {
Write-Output "PASS $name (${secs}s)"
$pass++
} else {
}
else {
Write-Output "FAIL $name (${secs}s)"
($t -replace "`r","" -split "`n" | Select-Object -Last 40) |
ForEach-Object { Write-Output $_ }
$failed++
}
}
} finally {
}
finally {
Remove-Item $work -Recurse -Force -EA SilentlyContinue
}

Expand Down
Loading