From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pl1-f201.google.com (mail-pl1-f201.google.com [209.85.214.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3176938735D for ; Thu, 16 Jul 2026 04:33:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784176400; cv=none; b=cQrkwbRZVGZJXH9SAwb51iPqh7nYXJXITZ+36OX9Ij8QzlEBFv1X8HxA+Wndqya6gvuJn1KOTp/edHMhhs9sfnnycx/6K7tCebs8vDRlOy87au1mqEbnTetCpSjLzGix7xjxgjl50sIWM1AgkWSOZm5OgqiFg8vMch0QBJRmRpM= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784176400; c=relaxed/simple; bh=nTYCyrNr3Dopwvrdc9lhpjMUkBgrCvKzCBft9TlBxgs=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=sZoHhfQLll7j9aLGZ280CHL7LQUe08hS2/YyPGPPM4TxSX9l+zQqt5WJ0YYcKkqw4JfFxjdSDOj2UE2LrZnYxOMw0v9uRgdaeAVPI0myBgnYKLtWLTn8qIqpZ4rUvhNPilMWqxwiE2oBQYNw7RkXNJhG3B/wYVr+n/EEyMjwEpw= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=SZ0ULsGL; arc=none smtp.client-ip=209.85.214.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="SZ0ULsGL" Received: by mail-pl1-f201.google.com with SMTP id d9443c01a7336-2ce8a76df2dso109051655ad.2 for ; Wed, 15 Jul 2026 21:33:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1784176397; x=1784781197; darn=vger.kernel.org; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:from:to:cc:subject:date:message-id:reply-to :content-type; bh=fhU3XiQPN4YP2a3S4XXH/u+7fM9ZJ52r4mxVp56qzW8=; b=SZ0ULsGLy83Bw4fU85pzIr/FlE5nYfKKLBro3FqDi/SsEJVdFiaA7Dfb6v+4TYjAYB 2J4X6kq9P1ZiuJBE27wvNFexImW+XBllkGFcLQoERg37Hb+qckJRw5TiO6Nz4akA74vx YwHfXJAabLwfbbcwtk8gRvKzrzdX4Mz0DA1iEmtbMxZTme+8r2o9kOApPgL5utIzuQYr oAzuPB6FVI+mGbTwRnKhlhqMLtEgcUtuFrzgHRe2ELfur24lfRrbvAXyxzdElByujD4w 1ZBajlXWlB/MDQlSuU+miSumx4Vj9BhZAf/KaA/rHN26GOqkmZxfFSzg7rWE+jksLVne bR1Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1784176397; x=1784781197; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=fhU3XiQPN4YP2a3S4XXH/u+7fM9ZJ52r4mxVp56qzW8=; b=r7t/g+EDAFRVeNzDAPV+myLRJex6VF6w6JHiPlpIHkTFtAaSrvBung7R/UWcCwxISO sIraaBylMN8H50Ig7AxjNS0jK1ZSLATZSZ4m4AheUd3uGd8gcvWUtLbL4ablfTecxtJz 2Gn0jdA+CsxHxoXTxj00+28MLGLlJynIKA8txzlc0xBe02rtMFAkuvggzzmSQ6zr1Rul dxAL8wpwwT3dauUiAcZUas1S2rT4mCthijNk2eCxPMgD/PcvuukYZodaYVVo8cxKLSuL Rp97Aff4zDjTU9iiskJmXPL2Rx6aKiP9l6KJ/2HHl3+Z0rODC2JGk6CmAaRUn2BQuc/O URLQ== X-Forwarded-Encrypted: i=1; AHgh+RrY6YdFst4HljtyWFW9xfynakzPAeVDNavUFHbp6LOse7aRxodTHojqS6DVDz1m8Ws2lSQs6nmTTsb3y6U=@vger.kernel.org X-Gm-Message-State: AOJu0Yzy/r46CY+ShResPGgTX55i5eDjdqnUjZnZsFVmrA/etnlNS48N DHeIfYUEt4iCCeUIuHa4w23QzU645gshkMAeb0oIzHsaofDico4ceUL5orGASHmMvWQxDVGHjZF ql5dCmOM2QQ== X-Received: from dleb2-n1.prod.google.com ([2002:a05:701b:4242:10b0:13c:d45f:48f9]) (user=irogers job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a21:9210:b0:3b4:8f18:33a with SMTP id adf61e73a8af0-3c35731da43mr11363765637.1.1784176397266; Wed, 15 Jul 2026 21:33:17 -0700 (PDT) Date: Wed, 15 Jul 2026 21:32:20 -0700 In-Reply-To: <20260716043223.388233-1-irogers@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260525231900.3527228-1-irogers@google.com> <20260716043223.388233-1-irogers@google.com> X-Mailer: git-send-email 2.55.0.141.g00534a21ce-goog Message-ID: <20260716043223.388233-12-irogers@google.com> Subject: [PATCH v3 11/14] perf stat: Extend JSON output linter to test core aggregation checks From: Ian Rogers To: irogers@google.com, acme@kernel.org, namhyung@kernel.org, ctshao@google.com Cc: adrian.hunter@intel.com, james.clark@linaro.org, jolsa@kernel.org, linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, mingo@redhat.com, peterz@infradead.org Content-Type: text/plain; charset="UTF-8" This patch extends tools/perf/tests/shell/stat+json_output.sh to run all basic and standard CPU/thread aggregation checks under the --new JSON print flag: - check_no_args - check_system_wide - check_interval - check_event - check_per_thread - check_per_node - check_system_wide_no_aggr - check_per_core - check_per_socket - check_per_die This guarantees that JSON outputs produced by the decoupled, zero-allocation, and streaming print callbacks are formally validated across standard and interval modes. Signed-off-by: Ian Rogers Assisted-by: Antigravity:gemini-3.5-flash Acked-by: Chun-Tse Shao --- tools/perf/tests/shell/stat+json_output.sh | 71 ++++++++++++++-------- 1 file changed, 45 insertions(+), 26 deletions(-) diff --git a/tools/perf/tests/shell/stat+json_output.sh b/tools/perf/tests/shell/stat+json_output.sh index 85d1ad7186c6..8168b861ade7 100755 --- a/tools/perf/tests/shell/stat+json_output.sh +++ b/tools/perf/tests/shell/stat+json_output.sh @@ -13,6 +13,7 @@ shelldir=$(dirname "$0") . "${shelldir}"/lib/setup_python.sh pythonchecker=$(dirname $0)/lib/perf_json_output_lint.py +perf_new_opt="" stat_output=$(mktemp /tmp/__perf_test.stat_output.json.XXXXX) cleanup() { @@ -35,42 +36,42 @@ function ParanoidAndNotRoot() check_no_args() { - echo -n "Checking json output: no args " - perf stat -j -o "${stat_output}" true + echo -n "Checking $api_label: no args " + perf stat -j $perf_new_opt -o "${stat_output}" true $PYTHON $pythonchecker --no-args --file "${stat_output}" echo "[Success]" } check_system_wide() { - echo -n "Checking json output: system wide " + echo -n "Checking $api_label: system wide " if ParanoidAndNotRoot 0 then echo "[Skip] paranoia and not root" return fi - perf stat -j -a -o "${stat_output}" true + perf stat -j $perf_new_opt -a -o "${stat_output}" true $PYTHON $pythonchecker --system-wide --file "${stat_output}" echo "[Success]" } check_system_wide_no_aggr() { - echo -n "Checking json output: system wide no aggregation " + echo -n "Checking $api_label: system wide no aggregation " if ParanoidAndNotRoot 0 then echo "[Skip] paranoia and not root" return fi - perf stat -j -A -a --no-merge -o "${stat_output}" true + perf stat -j $perf_new_opt -A -a --no-merge -o "${stat_output}" true $PYTHON $pythonchecker --system-wide-no-aggr --file "${stat_output}" echo "[Success]" } check_interval() { - echo -n "Checking json output: interval " - perf stat -j -I 1000 -o "${stat_output}" true + echo -n "Checking $api_label: interval " + perf stat -j $perf_new_opt -I 1000 -o "${stat_output}" true $PYTHON $pythonchecker --interval --file "${stat_output}" echo "[Success]" } @@ -78,110 +79,110 @@ check_interval() check_event() { - echo -n "Checking json output: event " - perf stat -j -e cpu-clock -o "${stat_output}" true + echo -n "Checking $api_label: event " + perf stat -j $perf_new_opt -e cpu-clock -o "${stat_output}" true $PYTHON $pythonchecker --event --file "${stat_output}" echo "[Success]" } check_per_core() { - echo -n "Checking json output: per core " + echo -n "Checking $api_label: per core " if ParanoidAndNotRoot 0 then echo "[Skip] paranoia and not root" return fi - perf stat -j --per-core -a -o "${stat_output}" true + perf stat -j $perf_new_opt --per-core -a -o "${stat_output}" true $PYTHON $pythonchecker --per-core --file "${stat_output}" echo "[Success]" } check_per_thread() { - echo -n "Checking json output: per thread " + echo -n "Checking $api_label: per thread " if ParanoidAndNotRoot 0 then echo "[Skip] paranoia and not root" return fi - perf stat -j --per-thread -p $$ -o "${stat_output}" true + perf stat -j $perf_new_opt --per-thread -p $$ -o "${stat_output}" true $PYTHON $pythonchecker --per-thread --file "${stat_output}" echo "[Success]" } check_per_cache_instance() { - echo -n "Checking json output: per cache_instance " + echo -n "Checking $api_label: per cache_instance " if ParanoidAndNotRoot 0 then echo "[Skip] paranoia and not root" return fi - perf stat -j --per-cache -a true 2>&1 | $PYTHON $pythonchecker --per-cache + perf stat -j $perf_new_opt --per-cache -a true 2>&1 | $PYTHON $pythonchecker --per-cache echo "[Success]" } check_per_cluster() { - echo -n "Checking json output: per cluster " + echo -n "Checking $api_label: per cluster " if ParanoidAndNotRoot 0 then echo "[Skip] paranoia and not root" return fi - perf stat -j --per-cluster -a true 2>&1 | $PYTHON $pythonchecker --per-cluster + perf stat -j $perf_new_opt --per-cluster -a true 2>&1 | $PYTHON $pythonchecker --per-cluster echo "[Success]" } check_per_die() { - echo -n "Checking json output: per die " + echo -n "Checking $api_label: per die " if ParanoidAndNotRoot 0 then echo "[Skip] paranoia and not root" return fi - perf stat -j --per-die -a -o "${stat_output}" true + perf stat -j $perf_new_opt --per-die -a -o "${stat_output}" true $PYTHON $pythonchecker --per-die --file "${stat_output}" echo "[Success]" } check_per_node() { - echo -n "Checking json output: per node " + echo -n "Checking $api_label: per node " if ParanoidAndNotRoot 0 then echo "[Skip] paranoia and not root" return fi - perf stat -j --per-node -a -o "${stat_output}" true + perf stat -j $perf_new_opt --per-node -a -o "${stat_output}" true $PYTHON $pythonchecker --per-node --file "${stat_output}" echo "[Success]" } check_per_socket() { - echo -n "Checking json output: per socket " + echo -n "Checking $api_label: per socket " if ParanoidAndNotRoot 0 then echo "[Skip] paranoia and not root" return fi - perf stat -j --per-socket -a -o "${stat_output}" true + perf stat -j $perf_new_opt --per-socket -a -o "${stat_output}" true $PYTHON $pythonchecker --per-socket --file "${stat_output}" echo "[Success]" } check_metric_only() { - echo -n "Checking json output: metric only " + echo -n "Checking $api_label: metric only " if [ "$(uname -m)" = "s390x" ] && ! grep '^facilities' /proc/cpuinfo | grep -qw 67 then echo "[Skip] CPU-measurement counter facility not installed" return fi - perf stat -j --metric-only -M page_faults_per_second -o "${stat_output}" true + perf stat -j $perf_new_opt --metric-only -M page_faults_per_second -o "${stat_output}" true $PYTHON $pythonchecker --metric-only --file "${stat_output}" echo "[Success]" } @@ -214,6 +215,7 @@ check_for_topology() } check_for_topology +api_label="json output" check_no_args check_system_wide check_interval @@ -232,5 +234,22 @@ then else echo "[Skip] Skipping tests for system_wide_no_aggr, per_core, per_die and per_socket since socket id exposed via topology is invalid" fi +# Run New API JSON basic and standard aggregation checks +perf_new_opt="--new" +api_label="json (New API)" +check_no_args +check_system_wide +check_interval +check_event +check_per_thread +check_per_node +if [ $skip_test -ne 1 ] +then + check_system_wide_no_aggr + check_per_core + check_per_die + check_per_socket +fi + cleanup exit 0 -- 2.55.0.141.g00534a21ce-goog