#!/usr/bin/env bash # Compact Strings measured with JOL: String layout, a million strings, when a string stays compact, flag status. # Regenerates every file in output/ except 07-jmh.txt (see jmh/). # JDK25=/path JDK27=/path ./run.sh # JDK 27 is Amazon Corretto 27+35 (https://corretto.aws/downloads/latest/amazon-corretto-27-x64-linux-jdk.tar.gz); JDK 25 is Temurin 25.0.4.1+1. set -uo pipefail unset JAVA_TOOL_OPTIONS HERE="$(cd "$(dirname "$0")" && pwd)"; cd "$HERE" JDK25="${JDK25:-/opt/jdks/jdk-25.0.4.1+1}"; JDK27="${JDK27:-/opt/jdks/jdk27}" OUT="$HERE/output"; mkdir -p "$OUT" .lib JOL=.lib/jol-core-0.17.jar if [ ! -s "$JOL" ]; then for try in 1 2 3 4 5; do curl -sfL -o "$JOL" https://repo1.maven.org/maven2/org/openjdk/jol/jol-core/0.17/jol-core-0.17.jar && break; sleep 5; done fi echo "4c98e9e61b3f189241057cb21b4331d1093e5b85 $JOL" | sha1sum -c - >/dev/null || { echo "JOL sha1 mismatch"; exit 1; } # Maven Central's own .sha1 B="$(mktemp -d)"; trap 'rm -rf "$B"' EXIT "$JDK25/bin/javac" --release 25 -cp "$JOL" -d "$B" src/*.java || exit 1 # JOL attaches to itself for Instrumentation and uses sun.misc.Unsafe (warned about on 24+); String's fields need --add-opens. COMMON=(-Djdk.attach.allowAttachSelf=true -XX:+EnableDynamicAgentLoading --sun-misc-unsafe-memory-access=allow --add-opens java.base/java.lang=ALL-UNNAMED -cp "$B:$JOL") run() { local jdk="$1" cls="$2"; shift 2; "$jdk/bin/java" "${COMMON[@]}" "$@" "$cls" 2>&1 | grep -v 'Picked up'; } # 01 - the layout of one String and a table by length, under six flag sets i=0 for cfg in "25|default|jdk25-default" "25|-XX:-CompactStrings|jdk25-no-compact-strings" "25|-XX:+UseCompactObjectHeaders|jdk25-compact-headers" "25|-XX:+UseCompactObjectHeaders -XX:-CompactStrings|jdk25-compact-headers-no-compact-strings" "27|default|jdk27-default" "27|-XX:-UseCompactObjectHeaders|jdk27-headers-off"; do v="${cfg%%|*}"; rest="${cfg#*|}"; flags="${rest%%|*}"; tag="${rest#*|}"; jdk="$JDK25"; [ "$v" = 27 ] && jdk="$JDK27" [ "$flags" = default ] && fl=() || read -ra fl <<< "$flags" i=$((i+1)); f="$OUT/$(printf %02d $i)-layout-$tag.txt" { echo "\$ java ${fl[*]:-} StringLayout (JDK $v)"; run "$jdk" StringLayout "${fl[@]}"; } > "$f" done # 02 - a million strings, same six flag sets i=10 for cfg in "25|default|jdk25-default" "25|-XX:-CompactStrings|jdk25-no-compact-strings" "25|-XX:+UseCompactObjectHeaders|jdk25-compact-headers" "25|-XX:+UseCompactObjectHeaders -XX:-CompactStrings|jdk25-compact-headers-no-compact-strings" "27|default|jdk27-default" "27|-XX:-UseCompactObjectHeaders|jdk27-headers-off"; do v="${cfg%%|*}"; rest="${cfg#*|}"; flags="${rest%%|*}"; tag="${rest#*|}"; jdk="$JDK25"; [ "$v" = 27 ] && jdk="$JDK27" [ "$flags" = default ] && fl=() || read -ra fl <<< "$flags" i=$((i+1)); f="$OUT/$(printf %02d $i)-million-$tag.txt" { echo "\$ java -Xmx3g ${fl[*]:-} MillionStrings (JDK $v)"; run "$jdk" MillionStrings -Xmx3g "${fl[@]}"; } > "$f" done # 03 - when does a string stay compact (JDK 25, default; and the same program with -XX:-CompactStrings) { echo "\$ java Upgrade (JDK 25)"; run "$JDK25" Upgrade; echo; echo "\$ java -XX:-CompactStrings Upgrade (JDK 25)"; run "$JDK25" Upgrade -XX:-CompactStrings; } > "$OUT/20-upgrade.txt" # 04 - is the flag diagnostic? (it is not: a product flag) { for v in 25 27; do jdk="$JDK25"; [ "$v" = 27 ] && jdk="$JDK27" echo "\$ java -XX:+PrintFlagsFinal -version | grep -E 'CompactStrings|CompactObjectHeaders' (JDK $v)" "$jdk/bin/java" -XX:+PrintFlagsFinal -version 2>&1 | grep -E 'CompactStrings|CompactObjectHeaders'; echo echo "\$ java -XX:-CompactStrings -version (JDK $v)"; "$jdk/bin/java" -XX:-CompactStrings -version 2>&1 | grep -v 'Picked up'; echo; done; } > "$OUT/21-flags.txt" echo done