From nobody Fri Nov 29 18:47:08 2024 Received: from NAM11-DM6-obe.outbound.protection.outlook.com (mail-dm6nam11on2043.outbound.protection.outlook.com [40.107.223.43]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1990B18B47B; Fri, 22 Nov 2024 08:46:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.223.43 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732265166; cv=fail; b=bG2sFJzy4G5RwDLNCy6Ad1fV/7f6X3Lxh6h6ko4MjZhDfYmpQHMWyN1uaWckl5WtLi55UkFxdFLqg+W54y5S8rq7GXXoCLoV216gnDXFB9SKcKSPz3aeLUY0E2deqidUwgyh0KI3HT/yxa9V3oIjBy9EKghdaXvbCBKecaNXOto= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732265166; c=relaxed/simple; bh=P1nWv8z/IOls01vQg/NC6fLMvX7VZStc7AFmDwKJHEo=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=u058wQPzfUCbhLpqseAhz6/YdbywfPzHTbXT1Nmmc4OtcPW2fJcYoz95Iu/gdta2Dq18zmCVEvLN0016p9w/sHsBy9+gLUduGJxnJl26DP3JlzYSQKm1ZWNDFlL7GGHI/UmP+Zf9p724vA0BQvnP59AtLKdrOAEPdDCK0admF4I= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amd.com; spf=fail smtp.mailfrom=amd.com; dkim=pass (1024-bit key) header.d=amd.com header.i=@amd.com header.b=bgZIEpDF; arc=fail smtp.client-ip=40.107.223.43 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amd.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=amd.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=amd.com header.i=@amd.com header.b="bgZIEpDF" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=PiScKEo4Y0SDitcnjZdVcNgmMcfC87m6U7XeOGGlyGDGxzUPRxevaGyvuOYPAMW7kKqy57QHomm5qPth9gN8bUQGjuSzz+d7NefjSg7gBdZlygwjWXi0NbnlLw1iZKBzRxDQRnD3Xt+LNqMfl5P/zkInMMt1N3pFEUmQ6c/4a+nMV2qWm+G7c3LeMNdyFx3LSB5QaEcaXXOf11L86RH3WZuRgzQJjCEMzhA2IiXaQ7jy+JsQJwIACAYlTwJD4/E8yzzgdlKSa6+6eZOKHFTB2mVKcXgdZ0aSq9l5wRd8qgS3mi3JF6tnkHDJjSPpshgAGIV/4DNWJNONM3ogB3yOtA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=2/DI0PVVpXpBtH/awXTgRanKvguZmxyb83QDf7ygUuU=; b=pe1V682sw1sKBLS2LUL3Ffnxs+REyzDxv+bluXo6fgqbKHfCFHHr3grVay0b4MIL5nv5rnRwkBmwbIFaHhsciSXRwgNcLfp0JpurzjV3BrOsyx8/ZQ4eDkGIfKUK4lOuOpVcvHq1pw0eWSCAKKYPTzlRpOpwv9ZHSKyauu6PX55yhp0KTMdGvwijNJ/gTy0xXRk63jB7iYFMi4XDyMN6f5anllIJteeuZKgVyjtnYdXEtvPoZjX5NAJ9v+ebWkHpbTmHhwDMqO4OEzEa7jvSF0PhwMTOJCGOoWPlIQLsE8Xtq4ywXESWYZzmVk/5zuHYDm5aVu9gmjUhf3QMsBzLyg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.12) smtp.rcpttodomain=infradead.org smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=2/DI0PVVpXpBtH/awXTgRanKvguZmxyb83QDf7ygUuU=; b=bgZIEpDF6Gnpm+KoGvTYfhYNCwPP1s2i9RKOhZhrph/DErODYXwFfnP5SPMkNxvK4kTn9Al+8UHXdqFO8AR6WqjJMh6dRR042ZvkyoKAjnFg17mD03JU0HZYiUErsd6488BX7wqOdW7fNUsLwvPEvJJZ7Df92Gq/WEz+hxMTndI= Received: from BN9PR03CA0466.namprd03.prod.outlook.com (2603:10b6:408:139::21) by CH2PR12MB4166.namprd12.prod.outlook.com (2603:10b6:610:78::13) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.8182.18; Fri, 22 Nov 2024 08:45:56 +0000 Received: from BN3PEPF0000B06B.namprd21.prod.outlook.com (2603:10b6:408:139:cafe::4e) by BN9PR03CA0466.outlook.office365.com (2603:10b6:408:139::21) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.20.8158.23 via Frontend Transport; Fri, 22 Nov 2024 08:45:55 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.12) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.12 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.12; helo=SATLEXMB04.amd.com; pr=C Received: from SATLEXMB04.amd.com (165.204.84.12) by BN3PEPF0000B06B.mail.protection.outlook.com (10.167.243.70) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.8207.0 via Frontend Transport; Fri, 22 Nov 2024 08:45:55 +0000 Received: from tapi.amd.com (10.180.168.240) by SATLEXMB04.amd.com (10.181.40.145) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.39; Fri, 22 Nov 2024 02:45:47 -0600 From: Swapnil Sapkal To: , , , , , CC: , , , , , , , , , , , , , , , , , , , , , James Clark Subject: [PATCH v2 1/6] sched/stats: Print domain name in /proc/schedstat Date: Fri, 22 Nov 2024 08:44:47 +0000 Message-ID: <20241122084452.1064968-2-swapnil.sapkal@amd.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20241122084452.1064968-1-swapnil.sapkal@amd.com> References: <20241122084452.1064968-1-swapnil.sapkal@amd.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: SATLEXMB03.amd.com (10.181.40.144) To SATLEXMB04.amd.com (10.181.40.145) X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: BN3PEPF0000B06B:EE_|CH2PR12MB4166:EE_ X-MS-Office365-Filtering-Correlation-Id: 35b6efe8-4388-43c5-d09e-08dd0ad21453 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|1800799024|36860700013|7416014|376014|82310400026; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?aVd1jGJ9iGN4AIB0HNJW3wBaF8KCK9yHmJ5eHjKlg8iZwUXbj2ExtM+Vm4HD?= =?us-ascii?Q?Et/DG4j8lpPgYtb6V70M5DpBM2Pe8FURL6MttIbNdH5Tbn+4+eP7psWX/9vo?= =?us-ascii?Q?ZrWUM2xAXNtjKRM9w/NDkhQ50svw1Is+UajQ7zRos2ozDG/LFgK5OFa8AfQI?= =?us-ascii?Q?hlGlkh1TKSVWSI8mgGuCRkcTAlG2gTWShZcHGqlEvEPIctuQSEXBFjgpOlXi?= =?us-ascii?Q?7Y1OfShsQs1iijIOaKrwtwp4xT3gwtjPtvH9MdiiQXC20ok83cE06WZpSC1X?= =?us-ascii?Q?Vlndtnc3K87l6ujnKtJ/OocU6j8Gf4kM9qJdTtyvjK3uqfXIjQhEXo0JE076?= =?us-ascii?Q?xNsABEIge13Xk4kjUAVU+grPcQ98bRZ50Z6cauJXk5PjmCQdb/g99xUJ4TAB?= =?us-ascii?Q?k+3C7SG8llppkfDZO4CBILJOKWVj3r6O828E6LV5jhB0m2IcVFGOHG+8C+PJ?= =?us-ascii?Q?6cekDuqgj3FL+I0UZ21WnKhdxtSq2S7yEKxn4/YvRKwahRmovEbY2rP+ISkm?= =?us-ascii?Q?ziNc+N2S5cHcYEgDB9h5dPJHtHHyww8DUVYCqahGrj5ODdNFVLQtnRvrDyK2?= =?us-ascii?Q?asImIwKUph7LjhRgBYV9V40ar4tmCg+Gy+maRfVMPzCK9QyDOmPdk8II7ldz?= =?us-ascii?Q?G0QZV/sVgYRgQHUyMh8XRRPv5JabMU49PuKYqMqJ1gcr4sfFIfVCSQnQGfkW?= =?us-ascii?Q?pJILLM7pahIyRahueI/GM/8dbog+BkAv0ARz/rp5bWbPSgTTvPSizr42fnoU?= =?us-ascii?Q?w4FYW1hUHGeXs0SD1928tOESfJj9d+g2y05SOkQkRZ0FpR4yLa1TilbFZqYI?= =?us-ascii?Q?B+a4G20nWOmZfH0htThSz0SS3vFj216+WriYhyWNiTnqdesn0CqQqvlCNpmo?= =?us-ascii?Q?mOixlEA/pIDserdV6zDucR1BEYkhYQvmyYv9a/+X/OQ33SZzXOX2aVipF6WR?= =?us-ascii?Q?xquEroJCtXz5gtFVQU3A33/fFsEjx7wb3qY4UEscU6D6DvynoqDO2E3UjXPx?= =?us-ascii?Q?nC/kCiUB1yQ/i3MoOJa31TL+bOOcZxspYn+gup/7ZI+rwSg3LO+XVx4mDjSi?= =?us-ascii?Q?JqLMnziur3d0Q1iS2Tc9h+loSkN6oSz5RPZQhKwdSwCbUHH8PL7O3ja/xkNR?= =?us-ascii?Q?4olxUQJ73nIc8mm0jgJ32h7zrXCRPXGvdL2iIJ1dQcNzdj5BlhvNylz+FbFN?= =?us-ascii?Q?zcdDaAIEPET03t7fl4yGkOAHb97X4gXhS0IU3ZkPheDp0csSP18yi9yeFiLa?= =?us-ascii?Q?a0fH3XEvajG4uahbj/CJs2THUk1roPArxQPxuigPPE7fEnfW7nXNgZySFACD?= =?us-ascii?Q?l32wqFX6LPAIyQA9JRDp9+Xltzfe9H7rQgps9HDq4vHtYzfzRXIUYxGRFX5J?= =?us-ascii?Q?cfbn+awnwu9WsxZyWCov7IC68SGLBQCttNoGjr91RigQ/UlCpQ=3D=3D?= X-Forefront-Antispam-Report: CIP:165.204.84.12;CTRY:US;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:SATLEXMB04.amd.com;PTR:atlvpn-bp.amd.com;CAT:NONE;SFS:(13230040)(1800799024)(36860700013)(7416014)(376014)(82310400026);DIR:OUT;SFP:1101; X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 22 Nov 2024 08:45:55.6144 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 35b6efe8-4388-43c5-d09e-08dd0ad21453 X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d;Ip=[165.204.84.12];Helo=[SATLEXMB04.amd.com] X-MS-Exchange-CrossTenant-AuthSource: BN3PEPF0000B06B.namprd21.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: CH2PR12MB4166 Content-Type: text/plain; charset="utf-8" From: K Prateek Nayak Currently, there does not exist a straightforward way to extract the names of the sched domains and match them to the per-cpu domain entry in /proc/schedstat other than looking at the debugfs files which are only visible after enabling "verbose" debug after commit 34320745dfc9 ("sched/debug: Put sched/domains files under the verbose flag") Since tools like `perf sched schedstat` require displaying per-domain information in user friendly manner, display the names of sched domain, alongside their level in /proc/schedstat if CONFIG_SCHED_DEBUG is enabled. Domain names also makes the /proc/schedstat data unambiguous when some of the cpus are offline. For example, on a 128 cpus AMD Zen3 machine where CPU0 and CPU64 are SMT siblings and CPU64 is offline: Before: cpu0 ... domain0 ... domain1 ... cpu1 ... domain0 ... domain1 ... domain2 ... After: cpu0 ... domain0:MC ... domain1:PKG ... cpu1 ... domain0:SMT ... domain1:MC ... domain2:PKG ... schedstat version has not been updated since this change merely adds additional information to the domain name field and does not add a new field altogether. Signed-off-by: K Prateek Nayak Signed-off-by: Ravi Bangoria Tested-by: James Clark --- Documentation/scheduler/sched-stats.rst | 8 ++++++-- kernel/sched/stats.c | 6 +++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Documentation/scheduler/sched-stats.rst b/Documentation/schedu= ler/sched-stats.rst index 7c2b16c4729d..b60a3e7bc108 100644 --- a/Documentation/scheduler/sched-stats.rst +++ b/Documentation/scheduler/sched-stats.rst @@ -6,6 +6,8 @@ Version 16 of schedstats changed the order of definitions w= ithin 'enum cpu_idle_type', which changed the order of [CPU_MAX_IDLE_TYPES] columns in show_schedstat(). In particular the position of CPU_IDLE and __CPU_NOT_IDLE changed places. The size of the array is unchanged. +With CONFIG_SCHED_DEBUG enabled, the domain field can also print the +name of the corresponding sched domain. =20 Version 15 of schedstats dropped counters for some sched_yield: yld_exp_empty, yld_act_empty and yld_both_empty. Otherwise, it is @@ -71,9 +73,11 @@ Domain statistics ----------------- One of these is produced per domain for each cpu described. (Note that if CONFIG_SMP is not defined, *no* domains are utilized and these lines -will not appear in the output.) +will not appear in the output. [:] is an optional extension to the d= omain +field that prints the name of the corresponding sched domain. It can appea= r in +schedstat version 16 and above, and requires CONFIG_SCHED_DEBUG.) =20 -domain 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 = 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 +domain[:] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 = 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 =20 The first field is a bit mask indicating what cpus this domain operates ov= er. =20 diff --git a/kernel/sched/stats.c b/kernel/sched/stats.c index eb0cdcd4d921..bd4ed737e894 100644 --- a/kernel/sched/stats.c +++ b/kernel/sched/stats.c @@ -138,7 +138,11 @@ static int show_schedstat(struct seq_file *seq, void *= v) for_each_domain(cpu, sd) { enum cpu_idle_type itype; =20 - seq_printf(seq, "domain%d %*pb", dcount++, + seq_printf(seq, "domain%d", dcount++); +#ifdef CONFIG_SCHED_DEBUG + seq_printf(seq, ":%s", sd->name); +#endif + seq_printf(seq, " %*pb", cpumask_pr_args(sched_domain_span(sd))); for (itype =3D 0; itype < CPU_MAX_IDLE_TYPES; itype++) { seq_printf(seq, " %u %u %u %u %u %u %u %u", --=20 2.43.0 From nobody Fri Nov 29 18:47:08 2024 Received: from NAM12-BN8-obe.outbound.protection.outlook.com (mail-bn8nam12on2040.outbound.protection.outlook.com [40.107.237.40]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0A06A4206E; Fri, 22 Nov 2024 08:46:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.237.40 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732265198; cv=fail; b=OYQ5Xq6ihrQwa+glkX0JXmOO+/ktBZKRm3YYV6krVpT96j8uxNfWhGvvvMpwxRfkighaFic0nERoq8YzZv1218Nupyapt/l369Y2ov8YLtAZwGy41oER/fu6H+fdjqQRU2qjj4fu9aPfoh7f2kRACFMfBnNr0l8jz4BPY5JW3Kw= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732265198; c=relaxed/simple; bh=k3Km63ZXZ4y5KJvn+Fx4IToUcXF9H8Nt/XdDwJREv4Q=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=qf4N91KdSVo9koqF2k8CERv+kbWG1Btv3LexRzQwmNckRrLAJ76NOFOYPBdbUyF6J+XDZCr/np0b6f8iayGMZhjq9Ys4v2itK6Ibwfz1fli5aWDkGWTHEgL/QTPVLSTWW8T3lMKDEma1ThNI+HjlaXz6xi1ZKADT3l5FJJ4LB9U= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amd.com; spf=fail smtp.mailfrom=amd.com; dkim=pass (1024-bit key) header.d=amd.com header.i=@amd.com header.b=Dr5B7sEp; arc=fail smtp.client-ip=40.107.237.40 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amd.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=amd.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=amd.com header.i=@amd.com header.b="Dr5B7sEp" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=nFNMrk8C1RaonzJGpKnwy5XVkJPn7gqmxcvssr2LqsVsxZua9LbKaz+9ZnF5emL5X8GCfXxJC9cJQLEeWil80/0TjEtlAjSXaAZt4T8rhwp7Sc30Itu8Okge3ndXKO+UI+tPb2jxg6wWxfom0c+2YcAAr11qel5oBV4/hCGbKmYhP8g8kV9fBpoBVqJ+TM2NOL7yhs6H/BAFNRkFQjcUHmWrw3jx6eevypKlP0WEpbNkoD6K5eF8fFCa+2OLwN/+OF27vNnUbHrHh2Gbm5P7cPdR7nTip47gAnTaKyXIe8YtQYooeYHWMzL9mtpWUHogE7Nps9VUNGiEZP7Cw/UsvQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=g3rguBylLklod6O4BskoEO+/VMrCquf3NdJarAFv8Eo=; b=mbjbrN4H61ycAVrwIhICee1GjOk0msTADvtnETeH1KQ/fYdHPM5va7PIMuXveUnw2pFQXeYsCQPdy4CT6PHwhKdtQCxCS0pmA8IPqCMUOyvkhfF7+qP92ayHcKBJxM/873TrsRK2o0pEQKrAD02ml2HUqJib7+Ip/R5pYrflwtYUPhWE7npVjXi/P/CxYATtgAx0sz4T+gvx2KZQDi26fvNmwY7xsRqoH8A5piqHC3JXDPpS+5K8LIba5+JTOPU+dQH0QkjcXkAsamAyXq6cROHjQGrA8HAvWPs1Sgz/AQtQFmtFO0f+XAZspmjl3ETg3XEWYNMI3vQIAfBlfTOmhg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.12) smtp.rcpttodomain=infradead.org smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=g3rguBylLklod6O4BskoEO+/VMrCquf3NdJarAFv8Eo=; b=Dr5B7sEpyBalIjNx3cd+ebB6i9DElIMprAsm8eSorWpoCUG1I8RiBE6Jtxs6NaIhDRDJem4+kk4hSBf+DV72rxF6QxfCBVrkPwaOvo6rbeBRphChjPTX1mQjbvhsoRsUNaHW71xB/RippA4eUaHcYxIMjfMvSk4KikSt6RTusXE= Received: from MN0P223CA0006.NAMP223.PROD.OUTLOOK.COM (2603:10b6:208:52b::6) by SN7PR12MB7273.namprd12.prod.outlook.com (2603:10b6:806:2ac::21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.8158.23; Fri, 22 Nov 2024 08:46:30 +0000 Received: from BN1PEPF00004689.namprd05.prod.outlook.com (2603:10b6:208:52b:cafe::f) by MN0P223CA0006.outlook.office365.com (2603:10b6:208:52b::6) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.8182.15 via Frontend Transport; Fri, 22 Nov 2024 08:46:29 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.12) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.12 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.12; helo=SATLEXMB04.amd.com; pr=C Received: from SATLEXMB04.amd.com (165.204.84.12) by BN1PEPF00004689.mail.protection.outlook.com (10.167.243.134) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.8182.16 via Frontend Transport; Fri, 22 Nov 2024 08:46:29 +0000 Received: from tapi.amd.com (10.180.168.240) by SATLEXMB04.amd.com (10.181.40.145) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.39; Fri, 22 Nov 2024 02:46:21 -0600 From: Swapnil Sapkal To: , , , , , CC: , , , , , , , , , , , , , , , , , , , , , Swapnil Sapkal , James Clark Subject: [PATCH v2 2/6] perf sched stats: Add record and rawdump support Date: Fri, 22 Nov 2024 08:44:48 +0000 Message-ID: <20241122084452.1064968-3-swapnil.sapkal@amd.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20241122084452.1064968-1-swapnil.sapkal@amd.com> References: <20241122084452.1064968-1-swapnil.sapkal@amd.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: SATLEXMB03.amd.com (10.181.40.144) To SATLEXMB04.amd.com (10.181.40.145) X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: BN1PEPF00004689:EE_|SN7PR12MB7273:EE_ X-MS-Office365-Filtering-Correlation-Id: e3a3c04b-b003-49c9-ffa5-08dd0ad2288d X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|36860700013|7416014|82310400026|376014|1800799024; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?V4EdPGhgmUO7qH543vLYraV+ajDfFxKDbtPs/bXg0TiF8UW8BVtqaGeCmgl8?= =?us-ascii?Q?5tqyTb8BvrEeIG7GVVHzjX4DoCe/tTAZy+Q+1JpefQdLIf4IJtj6VtLxfb4V?= =?us-ascii?Q?N4xq1PVdjmkxz/sadokX4SkexVQg3rkG2l4+oqngddYR32IGLC+cvAtn+SZP?= =?us-ascii?Q?USmWqPht0ihAvRq41Gdn3Kxp/AOQAg5dsOvDET2AitHdBtG2AhdAqLMHjipq?= =?us-ascii?Q?1ET3osxXVGCzd6tiZ9hYzSXxMOThO593pvmGwZ2cfotq/OVFK8ksnkuAS0se?= =?us-ascii?Q?FDI6jEXpd3nBW1fkzZ0X2gZcw9cmY9pVfvpG5NTNaUuajhyBto/vtImOTePP?= =?us-ascii?Q?tYXWTmkNYIzZSb3XHo+7CeCk9PrHlX0KsQaAuuMvCz3BTHw57rpIMM9sJVEY?= =?us-ascii?Q?LuKPq5kS0u92LtWPvMjoQylEnEPnfs/3XQVtjQ0aKq2O9y6mb7GZ/ilYNIsj?= =?us-ascii?Q?U0VwRDHzBPXxP2N0g6eA6P3SmpiRsdlnWwI9WjhoAnTaTxim5riaqTL1Jv5O?= =?us-ascii?Q?igDuBqHojG02ctHteunJzNW3j532wAeBRIwUmNE9VEEZnuEOc6iKSZnA4Wxv?= =?us-ascii?Q?sUovKJfwyInvz5ESKzPgeqUvVaYBlXIEmLEF6oE48ZAP00netHMBXYwf/lLg?= =?us-ascii?Q?zgIyNpBUikohur6tXrmBP8dwdEiA4rNvOWVw0EoC83Zbexbpfzqe1zBWIsGM?= =?us-ascii?Q?zDZp8+m8NCtIx7kNM6rOMaTmRjxDyEbFN+8rs8i0WGhFNLhxOFq0ELH0lOD1?= =?us-ascii?Q?f7LWPvUqneq2K/Zp+Z6bd4aZ0dm+S+3JQhvuOeDmP4GSLH9PlurSfxalGahe?= =?us-ascii?Q?Gr3OfxTY1/m44rIQhKHfSKzKxxLi+8yS296BMNBtk4qETtywc5ctEkfQXKP+?= =?us-ascii?Q?TacVmOixt19JnZgKejMJT5AMLKtQGkujQr/Jm9Jxsc3uKt1qoQ56OOK4ra2Q?= =?us-ascii?Q?PdN4k5gfre9icOtPg+z/+DegMr1tWpqv+mSv/l0P5dbrtWT94+vUuTFlnMoU?= =?us-ascii?Q?iyMxvrL5wx2razauOKS7/MYxx1r1qL0L0pmndxmMWEECrLY7Pu4Vk62uCXIe?= =?us-ascii?Q?dX1U5bKyfypco4fhvKJQYvUXehZNiEnarCdt01fs0OFxbh/OLKf1n1z4I33F?= =?us-ascii?Q?HE3PRtU5UCNQNV2PpkH8Je0wlgjAfMGlRLlCbVpkChsI5a9wniNm8ZGWJLbK?= =?us-ascii?Q?jhVJkD+Ri6iceClhDoRgysPKkachR2Z2aP8X4keV0ty6ODqyLlk5ttXSk9z2?= =?us-ascii?Q?aRgokGoMZlYLtuFVVDVhAMTvtWggQcoOtDZvWNmFk/EjdMU6Kv/ebdUIg+8d?= =?us-ascii?Q?3N6FE9Jkup8QdM4vVAgAwyzDJJ4JVXoBLlxd8WgPwz8kTgwWLi8Jaais1rLF?= =?us-ascii?Q?yPVj2eYXKv2WkeiyJ/s4ZvvTZa51S4xy8KDzts8QgkJXnYOyeg=3D=3D?= X-Forefront-Antispam-Report: CIP:165.204.84.12;CTRY:US;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:SATLEXMB04.amd.com;PTR:atlvpn-bp.amd.com;CAT:NONE;SFS:(13230040)(36860700013)(7416014)(82310400026)(376014)(1800799024);DIR:OUT;SFP:1101; X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 22 Nov 2024 08:46:29.5501 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: e3a3c04b-b003-49c9-ffa5-08dd0ad2288d X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d;Ip=[165.204.84.12];Helo=[SATLEXMB04.amd.com] X-MS-Exchange-CrossTenant-AuthSource: BN1PEPF00004689.namprd05.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: SN7PR12MB7273 Content-Type: text/plain; charset="utf-8" Define new, perf tool only, sample types and their layouts. Add logic to parse /proc/schedstat, convert it to perf sample format and save samples to perf.data file with `perf sched stats record` command. Also add logic to read perf.data file, interpret schedstat samples and print rawdump of samples with `perf script -D`. Note that, /proc/schedstat file output is standardized with version number. The patch supports v15 but older or newer version can be added easily. Co-developed-by: Ravi Bangoria Signed-off-by: Ravi Bangoria Tested-by: James Clark Signed-off-by: Swapnil Sapkal --- tools/lib/perf/Documentation/libperf.txt | 2 + tools/lib/perf/Makefile | 2 +- tools/lib/perf/include/perf/event.h | 42 ++++ tools/lib/perf/include/perf/schedstat-v15.h | 52 ++++ tools/perf/builtin-inject.c | 2 + tools/perf/builtin-sched.c | 226 +++++++++++++++++- tools/perf/util/event.c | 98 ++++++++ tools/perf/util/event.h | 2 + tools/perf/util/session.c | 20 ++ tools/perf/util/synthetic-events.c | 250 ++++++++++++++++++++ tools/perf/util/synthetic-events.h | 3 + tools/perf/util/tool.c | 20 ++ tools/perf/util/tool.h | 4 +- 13 files changed, 720 insertions(+), 3 deletions(-) create mode 100644 tools/lib/perf/include/perf/schedstat-v15.h diff --git a/tools/lib/perf/Documentation/libperf.txt b/tools/lib/perf/Docu= mentation/libperf.txt index fcfb9499ef9c..39c78682ad2e 100644 --- a/tools/lib/perf/Documentation/libperf.txt +++ b/tools/lib/perf/Documentation/libperf.txt @@ -211,6 +211,8 @@ SYNOPSIS struct perf_record_time_conv; struct perf_record_header_feature; struct perf_record_compressed; + struct perf_record_schedstat_cpu; + struct perf_record_schedstat_domain; -- =20 DESCRIPTION diff --git a/tools/lib/perf/Makefile b/tools/lib/perf/Makefile index 3a9b2140aa04..43a8642e4bab 100644 --- a/tools/lib/perf/Makefile +++ b/tools/lib/perf/Makefile @@ -187,7 +187,7 @@ install_lib: libs $(call do_install_mkdir,$(libdir_SQ)); \ cp -fpR $(LIBPERF_ALL) $(DESTDIR)$(libdir_SQ) =20 -HDRS :=3D bpf_perf.h core.h cpumap.h threadmap.h evlist.h evsel.h event.h = mmap.h +HDRS :=3D bpf_perf.h core.h cpumap.h threadmap.h evlist.h evsel.h event.h = mmap.h schedstat-v15.h INTERNAL_HDRS :=3D cpumap.h evlist.h evsel.h lib.h mmap.h rc_check.h threa= dmap.h xyarray.h =20 INSTALL_HDRS_PFX :=3D $(DESTDIR)$(prefix)/include/perf diff --git a/tools/lib/perf/include/perf/event.h b/tools/lib/perf/include/p= erf/event.h index 37bb7771d914..189106874063 100644 --- a/tools/lib/perf/include/perf/event.h +++ b/tools/lib/perf/include/perf/event.h @@ -457,6 +457,44 @@ struct perf_record_compressed { char data[]; }; =20 +struct perf_record_schedstat_cpu_v15 { +#define CPU_FIELD(_type, _name, _ver) _type _name +#include "schedstat-v15.h" +#undef CPU_FIELD +}; + +struct perf_record_schedstat_cpu { + struct perf_event_header header; + __u64 timestamp; + union { + struct perf_record_schedstat_cpu_v15 v15; + }; + __u32 cpu; + __u16 version; +}; + +struct perf_record_schedstat_domain_v15 { +#define DOMAIN_FIELD(_type, _name, _ver) _type _name +#include "schedstat-v15.h" +#undef DOMAIN_FIELD +}; + +#define DOMAIN_NAME_LEN 16 + +struct perf_record_schedstat_domain { + struct perf_event_header header; + __u16 version; + __u64 timestamp; + __u32 cpu; + __u16 domain; + char name[DOMAIN_NAME_LEN]; + union { + struct perf_record_schedstat_domain_v15 v15; + }; + __u16 nr_cpus; + __u8 cpu_mask[]; +}; + enum perf_user_event_type { /* above any possible kernel type */ PERF_RECORD_USER_TYPE_START =3D 64, PERF_RECORD_HEADER_ATTR =3D 64, @@ -478,6 +516,8 @@ enum perf_user_event_type { /* above any possible kerne= l type */ PERF_RECORD_HEADER_FEATURE =3D 80, PERF_RECORD_COMPRESSED =3D 81, PERF_RECORD_FINISHED_INIT =3D 82, + PERF_RECORD_SCHEDSTAT_CPU =3D 83, + PERF_RECORD_SCHEDSTAT_DOMAIN =3D 84, PERF_RECORD_HEADER_MAX }; =20 @@ -518,6 +558,8 @@ union perf_event { struct perf_record_time_conv time_conv; struct perf_record_header_feature feat; struct perf_record_compressed pack; + struct perf_record_schedstat_cpu schedstat_cpu; + struct perf_record_schedstat_domain schedstat_domain; }; =20 #endif /* __LIBPERF_EVENT_H */ diff --git a/tools/lib/perf/include/perf/schedstat-v15.h b/tools/lib/perf/i= nclude/perf/schedstat-v15.h new file mode 100644 index 000000000000..43f8060c5337 --- /dev/null +++ b/tools/lib/perf/include/perf/schedstat-v15.h @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifdef CPU_FIELD +CPU_FIELD(__u32, yld_count, v15); +CPU_FIELD(__u32, array_exp, v15); +CPU_FIELD(__u32, sched_count, v15); +CPU_FIELD(__u32, sched_goidle, v15); +CPU_FIELD(__u32, ttwu_count, v15); +CPU_FIELD(__u32, ttwu_local, v15); +CPU_FIELD(__u64, rq_cpu_time, v15); +CPU_FIELD(__u64, run_delay, v15); +CPU_FIELD(__u64, pcount, v15); +#endif + +#ifdef DOMAIN_FIELD +DOMAIN_FIELD(__u32, idle_lb_count, v15); +DOMAIN_FIELD(__u32, idle_lb_balanced, v15); +DOMAIN_FIELD(__u32, idle_lb_failed, v15); +DOMAIN_FIELD(__u32, idle_lb_imbalance, v15); +DOMAIN_FIELD(__u32, idle_lb_gained, v15); +DOMAIN_FIELD(__u32, idle_lb_hot_gained, v15); +DOMAIN_FIELD(__u32, idle_lb_nobusyq, v15); +DOMAIN_FIELD(__u32, idle_lb_nobusyg, v15); +DOMAIN_FIELD(__u32, busy_lb_count, v15); +DOMAIN_FIELD(__u32, busy_lb_balanced, v15); +DOMAIN_FIELD(__u32, busy_lb_failed, v15); +DOMAIN_FIELD(__u32, busy_lb_imbalance, v15); +DOMAIN_FIELD(__u32, busy_lb_gained, v15); +DOMAIN_FIELD(__u32, busy_lb_hot_gained, v15); +DOMAIN_FIELD(__u32, busy_lb_nobusyq, v15); +DOMAIN_FIELD(__u32, busy_lb_nobusyg, v15); +DOMAIN_FIELD(__u32, newidle_lb_count, v15); +DOMAIN_FIELD(__u32, newidle_lb_balanced, v15); +DOMAIN_FIELD(__u32, newidle_lb_failed, v15); +DOMAIN_FIELD(__u32, newidle_lb_imbalance, v15); +DOMAIN_FIELD(__u32, newidle_lb_gained, v15); +DOMAIN_FIELD(__u32, newidle_lb_hot_gained, v15); +DOMAIN_FIELD(__u32, newidle_lb_nobusyq, v15); +DOMAIN_FIELD(__u32, newidle_lb_nobusyg, v15); +DOMAIN_FIELD(__u32, alb_count, v15); +DOMAIN_FIELD(__u32, alb_failed, v15); +DOMAIN_FIELD(__u32, alb_pushed, v15); +DOMAIN_FIELD(__u32, sbe_count, v15); +DOMAIN_FIELD(__u32, sbe_balanced, v15); +DOMAIN_FIELD(__u32, sbe_pushed, v15); +DOMAIN_FIELD(__u32, sbf_count, v15); +DOMAIN_FIELD(__u32, sbf_balanced, v15); +DOMAIN_FIELD(__u32, sbf_pushed, v15); +DOMAIN_FIELD(__u32, ttwu_wake_remote, v15); +DOMAIN_FIELD(__u32, ttwu_move_affine, v15); +DOMAIN_FIELD(__u32, ttwu_move_balance, v15); +#endif diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index d6989195a061..b6eca6e92390 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c @@ -2530,6 +2530,8 @@ int cmd_inject(int argc, const char **argv) inject.tool.finished_init =3D perf_event__repipe_op2_synth; inject.tool.compressed =3D perf_event__repipe_op4_synth; inject.tool.auxtrace =3D perf_event__repipe_auxtrace; + inject.tool.schedstat_cpu =3D perf_event__repipe_op2_synth; + inject.tool.schedstat_domain =3D perf_event__repipe_op2_synth; inject.tool.dont_split_sample_group =3D true; inject.session =3D __perf_session__new(&data, &inject.tool, /*trace_event_repipe=3D*/inject.output.is_pipe); diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 5981cc51abc8..7dfce34748e4 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -27,6 +27,8 @@ #include "util/debug.h" #include "util/event.h" #include "util/util.h" +#include "util/synthetic-events.h" +#include "util/target.h" =20 #include #include @@ -54,6 +56,7 @@ #define MAX_PRIO 140 =20 static const char *cpu_list; +static struct perf_cpu_map *user_requested_cpus; static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); =20 struct sched_atom; @@ -237,6 +240,9 @@ struct perf_sched { volatile bool thread_funcs_exit; const char *prio_str; DECLARE_BITMAP(prio_bitmap, MAX_PRIO); + + struct perf_session *session; + struct perf_data *data; }; =20 /* per thread run time data */ @@ -3660,6 +3666,199 @@ static void setup_sorting(struct perf_sched *sched,= const struct option *options sort_dimension__add("pid", &sched->cmp_pid); } =20 +static int process_synthesized_schedstat_event(const struct perf_tool *too= l, + union perf_event *event, + struct perf_sample *sample __maybe_unused, + struct machine *machine __maybe_unused) +{ + struct perf_sched *sched =3D container_of(tool, struct perf_sched, tool); + + if (perf_data__write(sched->data, event, event->header.size) <=3D 0) { + pr_err("failed to write perf data, error: %m\n"); + return -1; + } + + sched->session->header.data_size +=3D event->header.size; + return 0; +} + +static void sighandler(int sig __maybe_unused) +{ +} + +static int enable_sched_schedstats(int *reset) +{ + char path[PATH_MAX]; + FILE *fp; + char ch; + + snprintf(path, PATH_MAX, "%s/sys/kernel/sched_schedstats", procfs__mountp= oint()); + fp =3D fopen(path, "w+"); + if (!fp) { + pr_err("Failed to open %s\n", path); + return -1; + } + + ch =3D getc(fp); + if (ch =3D=3D '0') { + *reset =3D 1; + rewind(fp); + putc('1', fp); + fclose(fp); + } + return 0; +} + +static int disable_sched_schedstat(void) +{ + char path[PATH_MAX]; + FILE *fp; + + snprintf(path, PATH_MAX, "%s/sys/kernel/sched_schedstats", procfs__mountp= oint()); + fp =3D fopen(path, "w"); + if (!fp) { + pr_err("Failed to open %s\n", path); + return -1; + } + + putc('0', fp); + fclose(fp); + return 0; +} + +/* perf.data or any other output file name used by stats subcommand (only)= . */ +const char *output_name; + +static int perf_sched__schedstat_record(struct perf_sched *sched, + int argc, const char **argv) +{ + struct perf_session *session; + struct evlist *evlist; + struct target *target; + int reset =3D 0; + int err =3D 0; + int fd; + struct perf_data data =3D { + .path =3D output_name, + .mode =3D PERF_DATA_MODE_WRITE, + }; + + signal(SIGINT, sighandler); + signal(SIGCHLD, sighandler); + signal(SIGTERM, sighandler); + + evlist =3D evlist__new(); + if (!evlist) + return -ENOMEM; + + session =3D perf_session__new(&data, &sched->tool); + if (IS_ERR(session)) { + pr_err("Perf session creation failed.\n"); + return PTR_ERR(session); + } + + session->evlist =3D evlist; + + sched->session =3D session; + sched->data =3D &data; + + fd =3D perf_data__fd(&data); + + /* + * Capture all important metadata about the system. Although they are + * not used by `perf sched stats` tool directly, they provide useful + * information about profiled environment. + */ + perf_header__set_feat(&session->header, HEADER_HOSTNAME); + perf_header__set_feat(&session->header, HEADER_OSRELEASE); + perf_header__set_feat(&session->header, HEADER_VERSION); + perf_header__set_feat(&session->header, HEADER_ARCH); + perf_header__set_feat(&session->header, HEADER_NRCPUS); + perf_header__set_feat(&session->header, HEADER_CPUDESC); + perf_header__set_feat(&session->header, HEADER_CPUID); + perf_header__set_feat(&session->header, HEADER_TOTAL_MEM); + perf_header__set_feat(&session->header, HEADER_CMDLINE); + perf_header__set_feat(&session->header, HEADER_CPU_TOPOLOGY); + perf_header__set_feat(&session->header, HEADER_NUMA_TOPOLOGY); + perf_header__set_feat(&session->header, HEADER_CACHE); + perf_header__set_feat(&session->header, HEADER_MEM_TOPOLOGY); + perf_header__set_feat(&session->header, HEADER_CPU_PMU_CAPS); + perf_header__set_feat(&session->header, HEADER_HYBRID_TOPOLOGY); + perf_header__set_feat(&session->header, HEADER_PMU_CAPS); + + err =3D perf_session__write_header(session, evlist, fd, false); + if (err < 0) + goto out; + + /* + * `perf sched stats` does not support workload profiling (-p pid) + * since /proc/schedstat file contains cpu specific data only. Hence, a + * profile target is either set of cpus or systemwide, never a process. + * Note that, although `-- ` is supported, profile data are + * still cpu/systemwide. + */ + target =3D zalloc(sizeof(struct target)); + if (cpu_list) + target->cpu_list =3D cpu_list; + else + target->system_wide =3D true; + + if (argc) { + err =3D evlist__prepare_workload(evlist, target, argv, false, NULL); + if (err) + goto out_target; + } + + if (cpu_list) { + user_requested_cpus =3D perf_cpu_map__new(cpu_list); + if (!user_requested_cpus) + goto out_target; + } + + err =3D perf_event__synthesize_schedstat(&(sched->tool), + process_synthesized_schedstat_event, + user_requested_cpus); + if (err < 0) + goto out_target; + + err =3D enable_sched_schedstats(&reset); + if (err < 0) + goto out_target; + + if (argc) + evlist__start_workload(evlist); + + /* wait for signal */ + pause(); + + if (reset) { + err =3D disable_sched_schedstat(); + if (err < 0) + goto out_target; + } + + err =3D perf_event__synthesize_schedstat(&(sched->tool), + process_synthesized_schedstat_event, + user_requested_cpus); + if (err < 0) + goto out_target; + + err =3D perf_session__write_header(session, evlist, fd, true); + +out_target: + free(target); +out: + if (!err) + fprintf(stderr, "[ perf sched stats: Wrote samples to %s ]\n", data.path= ); + else + fprintf(stderr, "[ perf sched stats: Failed !! ]\n"); + + close(fd); + perf_session__delete(session); + + return err; +} + static bool schedstat_events_exposed(void) { /* @@ -3835,6 +4034,12 @@ int cmd_sched(int argc, const char **argv) "analyze events only for given task priority(ies)"), OPT_PARENT(sched_options) }; + const struct option stats_options[] =3D { + OPT_STRING('o', "output", &output_name, "file", + "`stats record` with output filename"), + OPT_STRING('C', "cpu", &cpu_list, "cpu", "list of cpus to profile"), + OPT_END() + }; =20 const char * const latency_usage[] =3D { "perf sched latency []", @@ -3852,9 +4057,13 @@ int cmd_sched(int argc, const char **argv) "perf sched timehist []", NULL }; + const char *stats_usage[] =3D { + "perf sched stats {record} []", + NULL + }; const char *const sched_subcommands[] =3D { "record", "latency", "map", "replay", "script", - "timehist", NULL }; + "timehist", "stats", NULL }; const char *sched_usage[] =3D { NULL, NULL @@ -3950,6 +4159,21 @@ int cmd_sched(int argc, const char **argv) return ret; =20 return perf_sched__timehist(&sched); + } else if (!strcmp(argv[0], "stats")) { + const char *const stats_subcommands[] =3D {"record", NULL}; + + argc =3D parse_options_subcommand(argc, argv, stats_options, + stats_subcommands, + stats_usage, + PARSE_OPT_STOP_AT_NON_OPTION); + + if (argv[0] && !strcmp(argv[0], "record")) { + if (argc) + argc =3D parse_options(argc, argv, stats_options, + stats_usage, 0); + return perf_sched__schedstat_record(&sched, argc, argv); + } + usage_with_options(stats_usage, stats_options); } else { usage_with_options(sched_usage, sched_options); } diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index aac96d5d1917..0f863d38abe2 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -77,6 +77,8 @@ static const char *perf_event__names[] =3D { [PERF_RECORD_HEADER_FEATURE] =3D "FEATURE", [PERF_RECORD_COMPRESSED] =3D "COMPRESSED", [PERF_RECORD_FINISHED_INIT] =3D "FINISHED_INIT", + [PERF_RECORD_SCHEDSTAT_CPU] =3D "SCHEDSTAT_CPU", + [PERF_RECORD_SCHEDSTAT_DOMAIN] =3D "SCHEDSTAT_DOMAIN", }; =20 const char *perf_event__name(unsigned int id) @@ -550,6 +552,102 @@ size_t perf_event__fprintf_text_poke(union perf_event= *event, struct machine *ma return ret; } =20 +size_t perf_event__fprintf_schedstat_cpu(union perf_event *event, FILE *fp) +{ + struct perf_record_schedstat_cpu *cs =3D &event->schedstat_cpu; + __u16 version =3D cs->version; + size_t size =3D 0; + + size =3D fprintf(fp, "\ncpu%u ", cs->cpu); + +#define CPU_FIELD(_type, _name, _ver) \ + size +=3D fprintf(fp, "%" PRIu64 " ", (unsigned long)cs->_ver._name) + + if (version =3D=3D 15) { +#include + return size; + } +#undef CPU_FIELD + + return fprintf(fp, "Unsupported /proc/schedstat version %d.\n", + event->schedstat_cpu.version); +} + +size_t perf_event__fprintf_schedstat_domain(union perf_event *event, FILE = *fp) +{ + struct perf_record_schedstat_domain *ds =3D &event->schedstat_domain; + __u16 version =3D ds->version; + size_t cpu_mask_len_2; + size_t cpu_mask_len; + size_t size =3D 0; + char *cpu_mask; + int idx; + int i, j; + bool low; + + if (ds->name[0]) + size =3D fprintf(fp, "\ndomain%u:%s ", ds->domain, ds->name); + else + size =3D fprintf(fp, "\ndomain%u ", ds->domain); + + cpu_mask_len =3D ((ds->nr_cpus + 3) >> 2); + cpu_mask_len_2 =3D cpu_mask_len + ((cpu_mask_len - 1) / 8); + + cpu_mask =3D zalloc(cpu_mask_len_2 + 1); + if (!cpu_mask) + return fprintf(fp, "Cannot allocate memory for cpumask\n"); + + idx =3D ((ds->nr_cpus + 7) >> 3) - 1; + + i =3D cpu_mask_len_2 - 1; + + low =3D true; + j =3D 1; + while (i >=3D 0) { + __u8 m; + + if (low) + m =3D ds->cpu_mask[idx] & 0xf; + else + m =3D (ds->cpu_mask[idx] & 0xf0) >> 4; + + if (m >=3D 0 && m <=3D 9) + m +=3D '0'; + else if (m >=3D 0xa && m <=3D 0xf) + m =3D m + 'a' - 10; + else if (m >=3D 0xA && m <=3D 0xF) + m =3D m + 'A' - 10; + + cpu_mask[i] =3D m; + + if (j =3D=3D 8 && i !=3D 0) { + cpu_mask[i - 1] =3D ','; + j =3D 0; + i--; + } + + if (!low) + idx--; + low =3D !low; + i--; + j++; + } + size +=3D fprintf(fp, "%s ", cpu_mask); + free(cpu_mask); + +#define DOMAIN_FIELD(_type, _name, _ver) \ + size +=3D fprintf(fp, "%" PRIu64 " ", (unsigned long)ds->_ver._name) + + if (version =3D=3D 15) { +#include + return size; + } +#undef DOMAIN_FIELD + + return fprintf(fp, "Unsupported /proc/schedstat version %d.\n", + event->schedstat_domain.version); +} + size_t perf_event__fprintf(union perf_event *event, struct machine *machin= e, FILE *fp) { size_t ret =3D fprintf(fp, "PERF_RECORD_%s", diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index f8742e6230a5..96e7cd1d282d 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h @@ -360,6 +360,8 @@ size_t perf_event__fprintf_cgroup(union perf_event *eve= nt, FILE *fp); size_t perf_event__fprintf_ksymbol(union perf_event *event, FILE *fp); size_t perf_event__fprintf_bpf(union perf_event *event, FILE *fp); size_t perf_event__fprintf_text_poke(union perf_event *event, struct machi= ne *machine,FILE *fp); +size_t perf_event__fprintf_schedstat_cpu(union perf_event *event, FILE *fp= ); +size_t perf_event__fprintf_schedstat_domain(union perf_event *event, FILE = *fp); size_t perf_event__fprintf(union perf_event *event, struct machine *machin= e, FILE *fp); =20 int kallsyms__get_function_start(const char *kallsyms_filename, diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index dbaf07bf6c5f..a929a63e1827 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -691,6 +691,20 @@ static void perf_event__time_conv_swap(union perf_even= t *event, } } =20 +static void +perf_event__schedstat_cpu_swap(union perf_event *event __maybe_unused, + bool sample_id_all __maybe_unused) +{ + /* FIXME */ +} + +static void +perf_event__schedstat_domain_swap(union perf_event *event __maybe_unused, + bool sample_id_all __maybe_unused) +{ + /* FIXME */ +} + typedef void (*perf_event__swap_op)(union perf_event *event, bool sample_id_all); =20 @@ -729,6 +743,8 @@ static perf_event__swap_op perf_event__swap_ops[] =3D { [PERF_RECORD_STAT_ROUND] =3D perf_event__stat_round_swap, [PERF_RECORD_EVENT_UPDATE] =3D perf_event__event_update_swap, [PERF_RECORD_TIME_CONV] =3D perf_event__time_conv_swap, + [PERF_RECORD_SCHEDSTAT_CPU] =3D perf_event__schedstat_cpu_swap, + [PERF_RECORD_SCHEDSTAT_DOMAIN] =3D perf_event__schedstat_domain_swap, [PERF_RECORD_HEADER_MAX] =3D NULL, }; =20 @@ -1444,6 +1460,10 @@ static s64 perf_session__process_user_event(struct p= erf_session *session, return err; case PERF_RECORD_FINISHED_INIT: return tool->finished_init(session, event); + case PERF_RECORD_SCHEDSTAT_CPU: + return tool->schedstat_cpu(session, event); + case PERF_RECORD_SCHEDSTAT_DOMAIN: + return tool->schedstat_domain(session, event); default: return -EINVAL; } diff --git a/tools/perf/util/synthetic-events.c b/tools/perf/util/synthetic= -events.c index a58444c4aed1..b2f9ddba8a54 100644 --- a/tools/perf/util/synthetic-events.c +++ b/tools/perf/util/synthetic-events.c @@ -2507,3 +2507,253 @@ int parse_synth_opt(char *synth) =20 return ret; } + +static union perf_event *__synthesize_schedstat_cpu(struct io *io, __u16 v= ersion, + __u64 *cpu, __u64 timestamp) +{ + struct perf_record_schedstat_cpu *cs; + union perf_event *event; + size_t size; + char ch; + + size =3D sizeof(struct perf_record_schedstat_cpu); + size =3D PERF_ALIGN(size, sizeof(u64)); + event =3D zalloc(size); + + if (!event) + return NULL; + + cs =3D &event->schedstat_cpu; + cs->header.type =3D PERF_RECORD_SCHEDSTAT_CPU; + cs->header.size =3D size; + cs->timestamp =3D timestamp; + + if (io__get_char(io) !=3D 'p' || io__get_char(io) !=3D 'u') + goto out_cpu; + + if (io__get_dec(io, (__u64 *)cpu) !=3D ' ') + goto out_cpu; + +#define CPU_FIELD(_type, _name, _ver) \ + do { \ + __u64 _tmp; \ + ch =3D io__get_dec(io, &_tmp); \ + if (ch !=3D ' ' && ch !=3D '\n') \ + goto out_cpu; \ + cs->_ver._name =3D _tmp; \ + } while (0) + + if (version =3D=3D 15) { +#include + } +#undef CPU_FIELD + + cs->cpu =3D *cpu; + cs->version =3D version; + + return event; +out_cpu: + free(event); + return NULL; +} + +static size_t schedstat_sanitize_cpumask(char *cpu_mask, size_t cpu_mask_l= en) +{ + char *dst =3D cpu_mask; + char *src =3D cpu_mask; + int i =3D 0; + + for ( ; src < cpu_mask + cpu_mask_len; dst++, src++) { + while (*src =3D=3D ',') + src++; + + *dst =3D *src; + } + + for ( ; dst < src; dst++, i++) + *dst =3D '\0'; + + return cpu_mask_len - i; +} + +static union perf_event *__synthesize_schedstat_domain(struct io *io, __u1= 6 version, + __u64 cpu, __u64 timestamp) +{ + struct perf_env env =3D { .total_mem =3D 0, }; + int nr_cpus_avail =3D perf_env__nr_cpus_avail(&env); + struct perf_record_schedstat_domain *ds; + union perf_event *event; + size_t d_name_len =3D 0; + char *d_name =3D NULL; + size_t cpu_mask_len =3D 0; + char *cpu_mask =3D NULL; + __u64 d_num; + size_t size; + int i =3D 0; + bool low; + char ch; + int idx; + + if (io__get_char(io) !=3D 'o' || io__get_char(io) !=3D 'm' || io__get_cha= r(io) !=3D 'a' || + io__get_char(io) !=3D 'i' || io__get_char(io) !=3D 'n') + return NULL; + + ch =3D io__get_dec(io, &d_num); + if (ch =3D=3D ':') { + if (io__getdelim(io, &d_name, &d_name_len, ' ') < 0 || !d_name_len) + return NULL; + d_name[d_name_len - 1] =3D '\0'; + d_name_len--; + } else if (ch !=3D ' ') { + return NULL; + } + + if (io__getdelim(io, &cpu_mask, &cpu_mask_len, ' ') < 0 || !cpu_mask_len) + goto out; + + cpu_mask[cpu_mask_len - 1] =3D '\0'; + cpu_mask_len--; + cpu_mask_len =3D schedstat_sanitize_cpumask(cpu_mask, cpu_mask_len); + + size =3D sizeof(struct perf_record_schedstat_domain) + ((nr_cpus_avail + = 7) >> 3); + size =3D PERF_ALIGN(size, sizeof(u64)); + event =3D zalloc(size); + + if (!event) + goto out_cpu_mask; + + ds =3D &event->schedstat_domain; + ds->header.type =3D PERF_RECORD_SCHEDSTAT_DOMAIN; + ds->header.size =3D size; + ds->version =3D version; + ds->timestamp =3D timestamp; + if (d_name) + strncpy(ds->name, d_name, DOMAIN_NAME_LEN - 1); + ds->domain =3D d_num; + ds->nr_cpus =3D nr_cpus_avail; + + idx =3D ((nr_cpus_avail + 7) >> 3) - 1; + low =3D true; + for (i =3D cpu_mask_len - 1; i >=3D 0 && idx >=3D 0; i--) { + char mask =3D cpu_mask[i]; + + if (mask >=3D '0' && mask <=3D '9') + mask -=3D '0'; + else if (mask >=3D 'a' && mask <=3D 'f') + mask =3D mask - 'a' + 10; + else if (mask >=3D 'A' && mask <=3D 'F') + mask =3D mask - 'A' + 10; + + if (low) { + ds->cpu_mask[idx] =3D mask; + } else { + ds->cpu_mask[idx] |=3D (mask << 4); + idx--; + } + low =3D !low; + } + + free(d_name); + free(cpu_mask); + +#define DOMAIN_FIELD(_type, _name, _ver) \ + do { \ + __u64 _tmp; \ + ch =3D io__get_dec(io, &_tmp); \ + if (ch !=3D ' ' && ch !=3D '\n') \ + goto out_domain; \ + ds->_ver._name =3D _tmp; \ + } while (0) + + if (version =3D=3D 15) { +#include + } +#undef DOMAIN_FIELD + + ds->cpu =3D cpu; + return event; + +out_domain: + free(event); +out_cpu_mask: + free(cpu_mask); +out: + free(d_name); + return NULL; +} + +int perf_event__synthesize_schedstat(const struct perf_tool *tool, + perf_event__handler_t process, + struct perf_cpu_map *user_requested_cpus) +{ + char *line =3D NULL, path[PATH_MAX]; + union perf_event *event =3D NULL; + size_t line_len =3D 0; + char bf[BUFSIZ]; + __u64 timestamp; + __u64 cpu =3D -1; + __u16 version; + struct io io; + int ret =3D -1; + char ch; + + snprintf(path, PATH_MAX, "%s/schedstat", procfs__mountpoint()); + io.fd =3D open(path, O_RDONLY, 0); + if (io.fd < 0) { + pr_err("Failed to open %s. Possibly CONFIG_SCHEDSTAT is disabled.\n", pa= th); + return -1; + } + io__init(&io, io.fd, bf, sizeof(bf)); + + if (io__getline(&io, &line, &line_len) < 0 || !line_len) + goto out; + + if (!strcmp(line, "version 15\n")) { + version =3D 15; + } else { + pr_err("Unsupported %s version: %s", path, line + 8); + goto out_free_line; + } + + if (io__getline(&io, &line, &line_len) < 0 || !line_len) + goto out_free_line; + timestamp =3D atol(line + 10); + + /* + * FIXME: Can be optimized a bit by not synthesizing domain samples + * for filtered out cpus. + */ + for (ch =3D io__get_char(&io); !io.eof; ch =3D io__get_char(&io)) { + struct perf_cpu this_cpu; + + if (ch =3D=3D 'c') { + event =3D __synthesize_schedstat_cpu(&io, version, + &cpu, timestamp); + } else if (ch =3D=3D 'd') { + event =3D __synthesize_schedstat_domain(&io, version, + cpu, timestamp); + } + if (!event) + goto out_free_line; + + this_cpu.cpu =3D cpu; + + if (user_requested_cpus && !perf_cpu_map__has(user_requested_cpus, this_= cpu)) + continue; + + if (process(tool, event, NULL, NULL) < 0) { + free(event); + goto out_free_line; + } + + free(event); + } + + ret =3D 0; + +out_free_line: + free(line); +out: + close(io.fd); + return ret; +} diff --git a/tools/perf/util/synthetic-events.h b/tools/perf/util/synthetic= -events.h index b9c936b5cfeb..eab914c238df 100644 --- a/tools/perf/util/synthetic-events.h +++ b/tools/perf/util/synthetic-events.h @@ -141,4 +141,7 @@ int perf_event__synthesize_for_pipe(const struct perf_t= ool *tool, struct perf_data *data, perf_event__handler_t process); =20 +int perf_event__synthesize_schedstat(const struct perf_tool *tool, + perf_event__handler_t process, + struct perf_cpu_map *user_requested_cpu); #endif // __PERF_SYNTHETIC_EVENTS_H diff --git a/tools/perf/util/tool.c b/tools/perf/util/tool.c index 3b7f390f26eb..9f81d720735f 100644 --- a/tools/perf/util/tool.c +++ b/tools/perf/util/tool.c @@ -230,6 +230,24 @@ static int perf_session__process_compressed_event_stub= (struct perf_session *sess return 0; } =20 +static int process_schedstat_cpu_stub(struct perf_session *perf_session __= maybe_unused, + union perf_event *event) +{ + if (dump_trace) + perf_event__fprintf_schedstat_cpu(event, stdout); + dump_printf(": unhandled!\n"); + return 0; +} + +static int process_schedstat_domain_stub(struct perf_session *perf_session= __maybe_unused, + union perf_event *event) +{ + if (dump_trace) + perf_event__fprintf_schedstat_domain(event, stdout); + dump_printf(": unhandled!\n"); + return 0; +} + void perf_tool__init(struct perf_tool *tool, bool ordered_events) { tool->ordered_events =3D ordered_events; @@ -286,6 +304,8 @@ void perf_tool__init(struct perf_tool *tool, bool order= ed_events) tool->compressed =3D perf_session__process_compressed_event_stub; #endif tool->finished_init =3D process_event_op2_stub; + tool->schedstat_cpu =3D process_schedstat_cpu_stub; + tool->schedstat_domain =3D process_schedstat_domain_stub; } =20 bool perf_tool__compressed_is_stub(const struct perf_tool *tool) diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h index db1c7642b0d1..d289a5396b01 100644 --- a/tools/perf/util/tool.h +++ b/tools/perf/util/tool.h @@ -77,7 +77,9 @@ struct perf_tool { stat, stat_round, feature, - finished_init; + finished_init, + schedstat_cpu, + schedstat_domain; event_op4 compressed; event_op3 auxtrace; bool ordered_events; --=20 2.43.0 From nobody Fri Nov 29 18:47:08 2024 Received: from NAM12-DM6-obe.outbound.protection.outlook.com (mail-dm6nam12on2055.outbound.protection.outlook.com [40.107.243.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0140D18A6A0; Fri, 22 Nov 2024 08:47:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.243.55 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732265233; cv=fail; b=aO7C3kSJwqgFEOMYiTvoCYMpl9y7jASZcHskNX0OXN8qmEjZd05oQajN8f4DvKhqGc2ExZPG6Mkj6n9y7Vec6gg/I1v2cmpdzpkfpvGYFcfzcr60KdWZX5/EnV4UuZr0DEEviVBmNGQEfD0vM3Md+eDY5zk2ZCizMmuHfVF3VEY= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732265233; c=relaxed/simple; bh=L1uhnVYrkcJnTBeOoJX6ETJmd9Tqm8Fpldrh6NBAl/I=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=KA6vTsSfS6gsdr94vTkiNPQInNgkW0mbzu+mzLl4eqhX/lIqiMeS3lwZRWjWyC/c+087OR6AIy+3dVCMt8M+JrBO1qAkjYTTpmq6NOjJB7/ySrLKx7USpbnNW83pWSSucY0T2MO2SVhsEBLLNVIA8irUsZ6Fz8JxUIOGNlVzZJ0= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amd.com; spf=fail smtp.mailfrom=amd.com; dkim=pass (1024-bit key) header.d=amd.com header.i=@amd.com header.b=SM+bSd3v; arc=fail smtp.client-ip=40.107.243.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amd.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=amd.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=amd.com header.i=@amd.com header.b="SM+bSd3v" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=GJvlWKQZeTnXOeMV1pXp8iUQ4xH6dPE5oqELAVga+359IL3gyo9v2BHZ6sbFLJvk+GVhNAuiJBUwjm1QWM+BOep26GWVuGwLiwxMWUxK2RiGmTgKwnJ7SSZKCICYBmFYNWAW9VoJFR9aXYv3JgKRfuLTCKtWqh7QCZVmSnzFaFNSLZcT9bEZTEpOk9pCUu6vHe8FBIBWwXL5+EQyrCN6Qw4U/or35aXfsSz8B8aAvUqoO2DPVPDlY3txB95taLVLuTTMoyPsgP94JWvUaODCC4hR/ynQ1b0n1EswBs/0my9nzvMDudcakpHhMq+RSSZio0+TkSunfiN4Gp+eFVJLbQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=2YtOYfrtR6ex2FFTrsSBIvUsz5pDrdA6NJBvTleRGPg=; b=cc2Z83cxclCTn+9vigDnjkotdQexGh6tXk7PtACX10YarQ4ZuYu7syMR1L7atA4lYflahqcrOcEWFH7b/sMWaBwEZFMVdcfy+sBzURrrTOd3GaLgJMj5Q5OQL0wx4aZyqrNyazbBD5wUvLf3lPdp9VOthroRUjxMpz1lEDnq5C5tA5XnqBG7ts+j7H0kQpTlVA43BCBhqBoTCl5WUAAl+eJ/OBcQYrbOwGKwV8OvuD3NJ/wYs5mYwuP1SV0LVpnSj8RjBAfL56OxRc1Ou8eDlNUfyk+PsZevnxRMF8whrj+0WpW9/xueB7GD6A+vFgjL3VzbiNXCZJbh2GJu7z89/g== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.12) smtp.rcpttodomain=infradead.org smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=2YtOYfrtR6ex2FFTrsSBIvUsz5pDrdA6NJBvTleRGPg=; b=SM+bSd3vnYjXK6lzL19F0/4drgBf77RWvp1Z8qGqOc+8YbVPAh1qx2mONrO9+ie6YNWxr+4OVkUN0UNeG2CKtr2qMgdt7pHSVCT9YqDx+prfskmMK7QgSl31oBcxB7j3cUUECijkMKETp9oS2yMlFtmNTUMQ6w5zhfBVPH9ddnE= Received: from BLAP220CA0022.NAMP220.PROD.OUTLOOK.COM (2603:10b6:208:32c::27) by CYYPR12MB8921.namprd12.prod.outlook.com (2603:10b6:930:c7::14) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.8158.22; Fri, 22 Nov 2024 08:47:06 +0000 Received: from BN1PEPF0000468A.namprd05.prod.outlook.com (2603:10b6:208:32c:cafe::e9) by BLAP220CA0022.outlook.office365.com (2603:10b6:208:32c::27) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.8182.15 via Frontend Transport; Fri, 22 Nov 2024 08:47:05 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.12) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.12 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.12; helo=SATLEXMB04.amd.com; pr=C Received: from SATLEXMB04.amd.com (165.204.84.12) by BN1PEPF0000468A.mail.protection.outlook.com (10.167.243.135) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.8182.16 via Frontend Transport; Fri, 22 Nov 2024 08:47:05 +0000 Received: from tapi.amd.com (10.180.168.240) by SATLEXMB04.amd.com (10.181.40.145) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.39; Fri, 22 Nov 2024 02:46:54 -0600 From: Swapnil Sapkal To: , , , , , CC: , , , , , , , , , , , , , , , , , , , , , Swapnil Sapkal , James Clark Subject: [PATCH v2 3/6] perf sched stats: Add schedstat v16 support Date: Fri, 22 Nov 2024 08:44:49 +0000 Message-ID: <20241122084452.1064968-4-swapnil.sapkal@amd.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20241122084452.1064968-1-swapnil.sapkal@amd.com> References: <20241122084452.1064968-1-swapnil.sapkal@amd.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: SATLEXMB03.amd.com (10.181.40.144) To SATLEXMB04.amd.com (10.181.40.145) X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: BN1PEPF0000468A:EE_|CYYPR12MB8921:EE_ X-MS-Office365-Filtering-Correlation-Id: b8aa4393-f188-4968-9b19-08dd0ad23dfb X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|1800799024|36860700013|7416014|376014|82310400026; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?Fj0DPry7XTo7AN3aw2Jm+8lP6hAZanLgny7lwHTAa+7tIA2QmmcfHDbUBNIG?= =?us-ascii?Q?i3ppXYdOfqAx3RERr15SOzlLiCTO8TfDoXOuZkZgkcEd3jGqfnw8sxINv8Ue?= =?us-ascii?Q?Z7Sv+Ezl8QCUdqDWsWZgPwkvZYZW1EjK4B2NZTi1yR5AUHLCAQjwrUBntil6?= =?us-ascii?Q?p7q52LvHMzwGtYK1svXOMWRpwr+L1/E2bw1q9oQNh+o8+mKoxXBizkRisv6E?= =?us-ascii?Q?NARXJV2u/5fVnoLLzHGGvrW0G1g0H6u8i4Jct7BuToEM5DFQhjBf9YEAGHS5?= =?us-ascii?Q?dXeKN89Mm/Bqr9zglLlPmZzLy8yDfa6AFQVR2rfpAv92XUWnK/lDNCwOWxhL?= =?us-ascii?Q?WAF+J3qd+K8YkgO0oyIhUyjpw7q4KvZoSbunWvIoDcG81IyHDyAJBj3A8RUR?= =?us-ascii?Q?kLIGdBvDbXrtOrQ8GKFwXmHb1+Wb+FOUUjwUJZoINTRviVw419+2hd4dm+xi?= =?us-ascii?Q?/lnZUzk0l1pUTLhxxiz1SVt00tvji5pu+s9BAsVk2dLlEGqVkyqLJnnrduK0?= =?us-ascii?Q?kb4+G0sMr5owzPXWpayxkN+jrFLisI4ExGD44M7HTLeDZA2geMJmkIL3EDai?= =?us-ascii?Q?gX4Ku+qgBlmj5mV76/WON3zwpPnSwnKGl/5O+wUvMw3RZq3f46Z1+x0jhYjS?= =?us-ascii?Q?IfxUnvDyMbh3OuiJye+Qe4Wy53l7R3kRuh9LRrl3nVCQ6hfZIz6QPwepRvK+?= =?us-ascii?Q?59DtoBCN5WNktRWkxMGegTuzhgTOmpv0thtW9K9bVvWchhdbKSmB3rNN8Dv1?= =?us-ascii?Q?qzmz5jLfYlFSFqO3PZ5AEtLkYiN7w41FgZXoNlGy64T+C541aLBJjOKonovd?= =?us-ascii?Q?yKTvN86CCPHfGtAQJxnZsX06VBEwkUyVmF+BudaOSAPnsUYpHvoS002xzqv6?= =?us-ascii?Q?yPx4f/9g5Sqf2z2NagB65PlK9xfSvm0Li58gvFwK4fPV6ixsrtOenTuy9hG5?= =?us-ascii?Q?Dqee9+0l7FOGZ2S5vOqTNgRR76k3bvDLoYZU+kmEDiuRzfW69s0ptMwbeLiX?= =?us-ascii?Q?HUvbuTJ9JwqFCj+JOIiQAmlCNHnPf70EbdvNbodX5Z2qv7H5NJl4YGp7OMAz?= =?us-ascii?Q?O9OvMTNnxpCheJJuRoTGVIriGu4kkJyyKhWejnWoL42MM/nMDpuHoNN6IyUx?= =?us-ascii?Q?3w2psLChqSIip2wZ9UB5LlnlqT6qVUh+ok4C4+lZ1xfcOnw+qpaF+ylea0tz?= =?us-ascii?Q?nVHoM1uhN1iewOrLdC9AxRtxaMCyjx69LTAp3abzYOe34vUyBn5lhFZEJnZk?= =?us-ascii?Q?WY6PTqdCLIJavohURPTAIDkD8KaqGvKUNwu2miIRo5opbaI0XoEMfZbPg9/I?= =?us-ascii?Q?FhN2sin+tytIpiYTw5xotPWauBwS9SDEz02C8ihzLBZFHlvACdiBSa8XbbC/?= =?us-ascii?Q?S7bSKZIROuEyDynaHZDsgjn8AqrRyJG/VaY/WQXuHY+vNK8IAg=3D=3D?= X-Forefront-Antispam-Report: CIP:165.204.84.12;CTRY:US;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:SATLEXMB04.amd.com;PTR:atlvpn-bp.amd.com;CAT:NONE;SFS:(13230040)(1800799024)(36860700013)(7416014)(376014)(82310400026);DIR:OUT;SFP:1101; X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 22 Nov 2024 08:47:05.4850 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: b8aa4393-f188-4968-9b19-08dd0ad23dfb X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d;Ip=[165.204.84.12];Helo=[SATLEXMB04.amd.com] X-MS-Exchange-CrossTenant-AuthSource: BN1PEPF0000468A.namprd05.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: CYYPR12MB8921 Content-Type: text/plain; charset="utf-8" /proc/schedstat file output is standardized with version number. Add support to record and raw dump v16 version layout. Co-developed-by: Ravi Bangoria Signed-off-by: Ravi Bangoria Tested-by: James Clark Signed-off-by: Swapnil Sapkal --- tools/lib/perf/Makefile | 2 +- tools/lib/perf/include/perf/event.h | 14 ++++++ tools/lib/perf/include/perf/schedstat-v16.h | 52 +++++++++++++++++++++ tools/perf/util/event.c | 6 +++ tools/perf/util/synthetic-events.c | 6 +++ 5 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 tools/lib/perf/include/perf/schedstat-v16.h diff --git a/tools/lib/perf/Makefile b/tools/lib/perf/Makefile index 43a8642e4bab..066c1d85425a 100644 --- a/tools/lib/perf/Makefile +++ b/tools/lib/perf/Makefile @@ -187,7 +187,7 @@ install_lib: libs $(call do_install_mkdir,$(libdir_SQ)); \ cp -fpR $(LIBPERF_ALL) $(DESTDIR)$(libdir_SQ) =20 -HDRS :=3D bpf_perf.h core.h cpumap.h threadmap.h evlist.h evsel.h event.h = mmap.h schedstat-v15.h +HDRS :=3D bpf_perf.h core.h cpumap.h threadmap.h evlist.h evsel.h event.h = mmap.h schedstat-v15.h schedstat-v16.h INTERNAL_HDRS :=3D cpumap.h evlist.h evsel.h lib.h mmap.h rc_check.h threa= dmap.h xyarray.h =20 INSTALL_HDRS_PFX :=3D $(DESTDIR)$(prefix)/include/perf diff --git a/tools/lib/perf/include/perf/event.h b/tools/lib/perf/include/p= erf/event.h index 189106874063..8ef70799e070 100644 --- a/tools/lib/perf/include/perf/event.h +++ b/tools/lib/perf/include/perf/event.h @@ -463,11 +463,18 @@ struct perf_record_schedstat_cpu_v15 { #undef CPU_FIELD }; =20 +struct perf_record_schedstat_cpu_v16 { +#define CPU_FIELD(_type, _name, _ver) _type _name +#include "schedstat-v16.h" +#undef CPU_FIELD +}; + struct perf_record_schedstat_cpu { struct perf_event_header header; __u64 timestamp; union { struct perf_record_schedstat_cpu_v15 v15; + struct perf_record_schedstat_cpu_v16 v16; }; __u32 cpu; __u16 version; @@ -479,6 +486,12 @@ struct perf_record_schedstat_domain_v15 { #undef DOMAIN_FIELD }; =20 +struct perf_record_schedstat_domain_v16 { +#define DOMAIN_FIELD(_type, _name, _ver) _type _name +#include "schedstat-v16.h" +#undef DOMAIN_FIELD +}; + #define DOMAIN_NAME_LEN 16 =20 struct perf_record_schedstat_domain { @@ -490,6 +503,7 @@ struct perf_record_schedstat_domain { char name[DOMAIN_NAME_LEN]; union { struct perf_record_schedstat_domain_v15 v15; + struct perf_record_schedstat_domain_v16 v16; }; __u16 nr_cpus; __u8 cpu_mask[]; diff --git a/tools/lib/perf/include/perf/schedstat-v16.h b/tools/lib/perf/i= nclude/perf/schedstat-v16.h new file mode 100644 index 000000000000..d6a4691b2fd5 --- /dev/null +++ b/tools/lib/perf/include/perf/schedstat-v16.h @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifdef CPU_FIELD +CPU_FIELD(__u32, yld_count, v16); +CPU_FIELD(__u32, array_exp, v16); +CPU_FIELD(__u32, sched_count, v16); +CPU_FIELD(__u32, sched_goidle, v16); +CPU_FIELD(__u32, ttwu_count, v16); +CPU_FIELD(__u32, ttwu_local, v16); +CPU_FIELD(__u64, rq_cpu_time, v16); +CPU_FIELD(__u64, run_delay, v16); +CPU_FIELD(__u64, pcount, v16); +#endif + +#ifdef DOMAIN_FIELD +DOMAIN_FIELD(__u32, busy_lb_count, v16); +DOMAIN_FIELD(__u32, busy_lb_balanced, v16); +DOMAIN_FIELD(__u32, busy_lb_failed, v16); +DOMAIN_FIELD(__u32, busy_lb_imbalance, v16); +DOMAIN_FIELD(__u32, busy_lb_gained, v16); +DOMAIN_FIELD(__u32, busy_lb_hot_gained, v16); +DOMAIN_FIELD(__u32, busy_lb_nobusyq, v16); +DOMAIN_FIELD(__u32, busy_lb_nobusyg, v16); +DOMAIN_FIELD(__u32, idle_lb_count, v16); +DOMAIN_FIELD(__u32, idle_lb_balanced, v16); +DOMAIN_FIELD(__u32, idle_lb_failed, v16); +DOMAIN_FIELD(__u32, idle_lb_imbalance, v16); +DOMAIN_FIELD(__u32, idle_lb_gained, v16); +DOMAIN_FIELD(__u32, idle_lb_hot_gained, v16); +DOMAIN_FIELD(__u32, idle_lb_nobusyq, v16); +DOMAIN_FIELD(__u32, idle_lb_nobusyg, v16); +DOMAIN_FIELD(__u32, newidle_lb_count, v16); +DOMAIN_FIELD(__u32, newidle_lb_balanced, v16); +DOMAIN_FIELD(__u32, newidle_lb_failed, v16); +DOMAIN_FIELD(__u32, newidle_lb_imbalance, v16); +DOMAIN_FIELD(__u32, newidle_lb_gained, v16); +DOMAIN_FIELD(__u32, newidle_lb_hot_gained, v16); +DOMAIN_FIELD(__u32, newidle_lb_nobusyq, v16); +DOMAIN_FIELD(__u32, newidle_lb_nobusyg, v16); +DOMAIN_FIELD(__u32, alb_count, v16); +DOMAIN_FIELD(__u32, alb_failed, v16); +DOMAIN_FIELD(__u32, alb_pushed, v16); +DOMAIN_FIELD(__u32, sbe_count, v16); +DOMAIN_FIELD(__u32, sbe_balanced, v16); +DOMAIN_FIELD(__u32, sbe_pushed, v16); +DOMAIN_FIELD(__u32, sbf_count, v16); +DOMAIN_FIELD(__u32, sbf_balanced, v16); +DOMAIN_FIELD(__u32, sbf_pushed, v16); +DOMAIN_FIELD(__u32, ttwu_wake_remote, v16); +DOMAIN_FIELD(__u32, ttwu_move_affine, v16); +DOMAIN_FIELD(__u32, ttwu_move_balance, v16); +#endif diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 0f863d38abe2..64f81e7b7f70 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -566,6 +566,9 @@ size_t perf_event__fprintf_schedstat_cpu(union perf_eve= nt *event, FILE *fp) if (version =3D=3D 15) { #include return size; + } else if (version =3D=3D 16) { +#include + return size; } #undef CPU_FIELD =20 @@ -641,6 +644,9 @@ size_t perf_event__fprintf_schedstat_domain(union perf_= event *event, FILE *fp) if (version =3D=3D 15) { #include return size; + } else if (version =3D=3D 16) { +#include + return size; } #undef DOMAIN_FIELD =20 diff --git a/tools/perf/util/synthetic-events.c b/tools/perf/util/synthetic= -events.c index b2f9ddba8a54..f200f7ece3ef 100644 --- a/tools/perf/util/synthetic-events.c +++ b/tools/perf/util/synthetic-events.c @@ -2545,6 +2545,8 @@ static union perf_event *__synthesize_schedstat_cpu(s= truct io *io, __u16 version =20 if (version =3D=3D 15) { #include + } else if (version =3D=3D 16) { +#include } #undef CPU_FIELD =20 @@ -2667,6 +2669,8 @@ static union perf_event *__synthesize_schedstat_domai= n(struct io *io, __u16 vers =20 if (version =3D=3D 15) { #include + } else if (version =3D=3D 16) { +#include } #undef DOMAIN_FIELD =20 @@ -2710,6 +2714,8 @@ int perf_event__synthesize_schedstat(const struct per= f_tool *tool, =20 if (!strcmp(line, "version 15\n")) { version =3D 15; + } else if (!strcmp(line, "version 16\n")) { + version =3D 16; } else { pr_err("Unsupported %s version: %s", path, line + 8); goto out_free_line; --=20 2.43.0 From nobody Fri Nov 29 18:47:08 2024 Received: from NAM10-DM6-obe.outbound.protection.outlook.com (mail-dm6nam10on2078.outbound.protection.outlook.com [40.107.93.78]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0C6161BDA85; Fri, 22 Nov 2024 08:47:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.93.78 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732265260; cv=fail; b=TDlMOUclkjzWfUgponPASemYOGpNB6y9uQaRxMsNqxP7UqbRQL06Au+QALhPbw2qsOPf42vn5bQ+VQ5RBk6tHxuYd3brLeZgfPl2WklY0feolo+E1GHEpzJpBm5MuWSEYZHfcdAJzueDyhMxp5sHuGxra+0e1A2K7D1L4pSYh2g= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732265260; c=relaxed/simple; bh=VnIJYlawHlQVTwBnKI8nCNuxEnISR3yVMtq3MPErCnE=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=oDzQDzayleJB7QuubMhg1xWSxuWsNQN+9GWk/PS+TVgFoh3R+OwESsWEOO2T/9lIMowXxZn9K68UILPrapOjrlfzMMe7dYCnYRCvPTvF5q1CfKUtH64HanbNibWp2sdPaLtTHrIOdfbnuPwDO6QIgRFtyzNmT05MAUYFDnUIPgs= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amd.com; spf=fail smtp.mailfrom=amd.com; dkim=pass (1024-bit key) header.d=amd.com header.i=@amd.com header.b=fLb0+jx+; arc=fail smtp.client-ip=40.107.93.78 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amd.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=amd.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=amd.com header.i=@amd.com header.b="fLb0+jx+" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=rxqDSNLQhIOuauTtoTS1DOoEGq+VGBiH9bFJxuFULKWeZN7DKZfUrAhJLLbZ0EGkfTt2BobBf5BjQSnop7666vJstMR0jrNEgL0eQaVWuqDYYcZouXnqMLrmQtjuFmEBMoEEFi64F8U9QXE/FkoPmtrpl+NYT0s9aew0bInmdXRlsfVkB2a6k+sJ0+zjwYFPvAexTtkc66BsrLtjCPdyxev0iH9UmsN4nLLiuREm1XNlhCVGAD4PwEig4Z6MjIQLKu6SQy9WnFTGSsiMK0F+abcyGevERPEuRiWUFeouncYcRSeyYUJSkAHnYuXiFr+eZJ2EL7LVJfM7Qt2hqojZ0g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=DS2zJtIHSwuH8PO6wT1qomKERgCAegnDfXxpGPxDgrE=; b=nY48o/It9GoSB2EboNcQ0BZm47MsVzfdT7r5ke+pY8WbOUo/2eTnaNxcZL/7QxOWVTxy4jJQOPu3dyD/BNmfjl0/yZ6j4LD3ivWm05lnFAM8rPqCNhOA/DqHZG8IIyp1PvuY/4M3jcJ9YTzC5uACLPAvlt4RbygQs//TB4/Uw6D9GyS7AKsWVj7G+fApysD3Fv7ozKzA630j/77zGrWqga8YHQsKqYIPD7gpl8hl1HSVciLDDA3KuACVui8YRnF1D6lYO7J0RPjrBP329dWwynyVafNS2y4KXbbzQSTzLvztnw2o8L9WTX7wGmQWE/PMylMaKcx+fJbRMgslw8Vw7g== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.12) smtp.rcpttodomain=infradead.org smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=DS2zJtIHSwuH8PO6wT1qomKERgCAegnDfXxpGPxDgrE=; b=fLb0+jx+ctMCw/2izjp0o3FKEA0Lb2cOuw1cUBIEoSzjnbPQD/0ZOhbggfMNAFG+6Ggjd7RPg1fWHZhk+MGq54cQApq2mq6ZeHioel/jLzFVFJffe9jtgg4JP0vH5qAmu4AnwPqyQesc3fVy+AK1EqJHypNwY0diAKKpl+jmCtY= Received: from MN2PR05CA0022.namprd05.prod.outlook.com (2603:10b6:208:c0::35) by PH7PR12MB5831.namprd12.prod.outlook.com (2603:10b6:510:1d6::13) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.8158.22; Fri, 22 Nov 2024 08:47:27 +0000 Received: from BN1PEPF0000468E.namprd05.prod.outlook.com (2603:10b6:208:c0:cafe::28) by MN2PR05CA0022.outlook.office365.com (2603:10b6:208:c0::35) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.8182.16 via Frontend Transport; Fri, 22 Nov 2024 08:47:26 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.12) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.12 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.12; helo=SATLEXMB04.amd.com; pr=C Received: from SATLEXMB04.amd.com (165.204.84.12) by BN1PEPF0000468E.mail.protection.outlook.com (10.167.243.139) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.8182.16 via Frontend Transport; Fri, 22 Nov 2024 08:47:26 +0000 Received: from tapi.amd.com (10.180.168.240) by SATLEXMB04.amd.com (10.181.40.145) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.39; Fri, 22 Nov 2024 02:47:17 -0600 From: Swapnil Sapkal To: , , , , , CC: , , , , , , , , , , , , , , , , , , , , , Swapnil Sapkal , James Clark Subject: [PATCH v2 4/6] perf sched stats: Add support for report subcommand Date: Fri, 22 Nov 2024 08:44:50 +0000 Message-ID: <20241122084452.1064968-5-swapnil.sapkal@amd.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20241122084452.1064968-1-swapnil.sapkal@amd.com> References: <20241122084452.1064968-1-swapnil.sapkal@amd.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: SATLEXMB03.amd.com (10.181.40.144) To SATLEXMB04.amd.com (10.181.40.145) X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: BN1PEPF0000468E:EE_|PH7PR12MB5831:EE_ X-MS-Office365-Filtering-Correlation-Id: bd9f5104-985b-4fe3-ac2b-08dd0ad24a5b X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|7416014|376014|82310400026|1800799024|36860700013; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?R8c2se0A3/HsAkBRhN1Al7vX3tFjBlsF5T2Jh00Y9Ud8S0BDqDrhz3t6Y2bg?= =?us-ascii?Q?Mjtboitfmj2vzyn6vfK9cjnqnMm25QCRmmzlNi5YWkVUKl+VOdtzCJz0VrSP?= =?us-ascii?Q?543d9I9Pf1FkVEiaLGLLYUspSMXGNfBJBd8KKnkK0HqCYqquSUlPxBK6jEPt?= =?us-ascii?Q?r5cUNnCIOoTGbUa4tvoX6Q0YzhZ4SVeaCwZgU79nuea34CSKtEcOPfa4ZKY/?= =?us-ascii?Q?exUafv/3rwKIv6eicZNPb8GoOiZ6dyRJ/SmIkxk9nzmnBsyVBdtiarJ0WBip?= =?us-ascii?Q?2kOK+vhu8uYDbqD643DEjdkSRtcSjPSiJ8sAYQD/wzQoJWfRnhMhwySH4/93?= =?us-ascii?Q?QM8wpVNLU/OHcyOFrvgz6LYvRsrtOem2zwnnExDdYNL4iC2JqcLqreZJ4Lhz?= =?us-ascii?Q?ETDFJ/UzKB7PZ7bFVQ7zRYFpke0kdjK+5bU82NTvGIfEo8N740F9ttri/gmG?= =?us-ascii?Q?OaGmrDlEgBk1oyJNJFbdbD2CMDklRYjPZ39IQY7okcFDeETFhLGTorYoLV57?= =?us-ascii?Q?tEVicnRK0XDIEPYi0dA2oQPoQJCGKGz6RncXg8sk+KT+Smi5VUw/6YcytqjM?= =?us-ascii?Q?YzaawiDwVhkbkkaJCbTzQKWLDYKBszAg4Ti51JKjJ5WiQUtO9CfC+OVjxbJU?= =?us-ascii?Q?SKOYN90aofnWYTNtYue4HKuCzc/4ldx1ZdaLbsQXx7M6ezkuztxW7b93eMuQ?= =?us-ascii?Q?Gq3IaQezUxAuxJei58xGnjZsngkOasNVgjCUf/FiPLwuAIAu6Xm/Pmdk9kq7?= =?us-ascii?Q?4EN6QQatrV/kYdRu+15EeiATc2PjMaiayS0NcikuUfU7IsiJDa2vchzqlw9N?= =?us-ascii?Q?wfCXfTVIpBR/1HVxHPgnvbFFxYnBlDCCqhbb/7+eURxsh7wDowaE0id5NPLl?= =?us-ascii?Q?Ve61FnMEW55LSwgXn2e/aAXO/+fQu688GntUGrUsw/E7gsQQ98m6oZ3XxUSA?= =?us-ascii?Q?AQS71FjqdYIEVI3FP9NIDjUi5MKjXfj08/2N601nJIME+2MFKmf5/mMxUNw9?= =?us-ascii?Q?ISWjM8u7qOpYyNzprcuhjANlRdWzIs9NLejFX5JZaLWrXfX9poTeAeLEy5F7?= =?us-ascii?Q?YmNbyBw2nfxR9roG5kElSC1DSOFtuIr+PzZtUgG01LF1Y5Pn2DRZ28K8qylT?= =?us-ascii?Q?rPa2jPeQz1wJsuWYHZAratXzgqp1IVHTG8PYko8LFKyS5iw9HfYPET36JJNB?= =?us-ascii?Q?KFC0U+9D4UYwyhWAiE2DFQDfEL9YArwNlD1PdQY971FxUS0OGiuWkrZkaxtV?= =?us-ascii?Q?RP4uiUrjGIFoNXJNMrnj9oFhuLa8sB0ejby7nFb5Pen33m7etTMQjqVCTPuB?= =?us-ascii?Q?NNV0iUlBz8TuvZ45GcyND34DjktU5eKGGEaibc8PL8nBbOw44I0XwZKQR5PI?= =?us-ascii?Q?Ss653IF3/+rr0ssQ+zPpltPnwIlQ3SZWiTaV8VNLHsNQ1rGubQ=3D=3D?= X-Forefront-Antispam-Report: CIP:165.204.84.12;CTRY:US;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:SATLEXMB04.amd.com;PTR:atlvpn-bp.amd.com;CAT:NONE;SFS:(13230040)(7416014)(376014)(82310400026)(1800799024)(36860700013);DIR:OUT;SFP:1101; X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 22 Nov 2024 08:47:26.2316 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: bd9f5104-985b-4fe3-ac2b-08dd0ad24a5b X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d;Ip=[165.204.84.12];Helo=[SATLEXMB04.amd.com] X-MS-Exchange-CrossTenant-AuthSource: BN1PEPF0000468E.namprd05.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: PH7PR12MB5831 Content-Type: text/plain; charset="utf-8" `perf sched stats record` captures two sets of samples. For workload profile, first set right before workload starts and second set after workload finishes. For the systemwide profile, first set at the beginning of profile and second set on receiving SIGINT signal. Add `perf sched stats report` subcommand that will read both the set of samples, get the diff and render a final report. Final report prints scheduler stat at cpu granularity as well as sched domain granularity. Example usage: # perf sched stats record # perf sched stats report Co-developed-by: Ravi Bangoria Signed-off-by: Ravi Bangoria Tested-by: James Clark Signed-off-by: Swapnil Sapkal --- tools/lib/perf/include/perf/event.h | 8 +- tools/lib/perf/include/perf/schedstat-v15.h | 180 +++++-- tools/lib/perf/include/perf/schedstat-v16.h | 183 ++++++-- tools/perf/builtin-sched.c | 492 +++++++++++++++++++- tools/perf/util/event.c | 4 +- tools/perf/util/synthetic-events.c | 4 +- 6 files changed, 771 insertions(+), 100 deletions(-) diff --git a/tools/lib/perf/include/perf/event.h b/tools/lib/perf/include/p= erf/event.h index 8ef70799e070..f6e68eb27dd5 100644 --- a/tools/lib/perf/include/perf/event.h +++ b/tools/lib/perf/include/perf/event.h @@ -458,13 +458,13 @@ struct perf_record_compressed { }; =20 struct perf_record_schedstat_cpu_v15 { -#define CPU_FIELD(_type, _name, _ver) _type _name +#define CPU_FIELD(_type, _name, _desc, _format, _is_pct, _pct_of, _ver) _= type _name #include "schedstat-v15.h" #undef CPU_FIELD }; =20 struct perf_record_schedstat_cpu_v16 { -#define CPU_FIELD(_type, _name, _ver) _type _name +#define CPU_FIELD(_type, _name, _desc, _format, _is_pct, _pct_of, _ver) _= type _name #include "schedstat-v16.h" #undef CPU_FIELD }; @@ -481,13 +481,13 @@ struct perf_record_schedstat_cpu { }; =20 struct perf_record_schedstat_domain_v15 { -#define DOMAIN_FIELD(_type, _name, _ver) _type _name +#define DOMAIN_FIELD(_type, _name, _desc, _format, _is_jiffies, _ver) _ty= pe _name #include "schedstat-v15.h" #undef DOMAIN_FIELD }; =20 struct perf_record_schedstat_domain_v16 { -#define DOMAIN_FIELD(_type, _name, _ver) _type _name +#define DOMAIN_FIELD(_type, _name, _desc, _format, _is_jiffies, _ver) _ty= pe _name #include "schedstat-v16.h" #undef DOMAIN_FIELD }; diff --git a/tools/lib/perf/include/perf/schedstat-v15.h b/tools/lib/perf/i= nclude/perf/schedstat-v15.h index 43f8060c5337..011411ac0f7e 100644 --- a/tools/lib/perf/include/perf/schedstat-v15.h +++ b/tools/lib/perf/include/perf/schedstat-v15.h @@ -1,52 +1,142 @@ /* SPDX-License-Identifier: GPL-2.0 */ =20 #ifdef CPU_FIELD -CPU_FIELD(__u32, yld_count, v15); -CPU_FIELD(__u32, array_exp, v15); -CPU_FIELD(__u32, sched_count, v15); -CPU_FIELD(__u32, sched_goidle, v15); -CPU_FIELD(__u32, ttwu_count, v15); -CPU_FIELD(__u32, ttwu_local, v15); -CPU_FIELD(__u64, rq_cpu_time, v15); -CPU_FIELD(__u64, run_delay, v15); -CPU_FIELD(__u64, pcount, v15); +CPU_FIELD(__u32, yld_count, "sched_yield() count", + "%11u", false, yld_count, v15); +CPU_FIELD(__u32, array_exp, "Legacy counter can be ignored", + "%11u", false, array_exp, v15); +CPU_FIELD(__u32, sched_count, "schedule() called", + "%11u", false, sched_count, v15); +CPU_FIELD(__u32, sched_goidle, "schedule() left the processor idle", + "%11u", true, sched_count, v15); +CPU_FIELD(__u32, ttwu_count, "try_to_wake_up() was called", + "%11u", false, ttwu_count, v15); +CPU_FIELD(__u32, ttwu_local, "try_to_wake_up() was called to wake up the l= ocal cpu", + "%11u", true, ttwu_count, v15); +CPU_FIELD(__u64, rq_cpu_time, "total runtime by tasks on this processor (i= n jiffies)", + "%11llu", false, rq_cpu_time, v15); +CPU_FIELD(__u64, run_delay, "total waittime by tasks on this processor (in= jiffies)", + "%11llu", true, rq_cpu_time, v15); +CPU_FIELD(__u64, pcount, "total timeslices run on this cpu", + "%11llu", false, pcount, v15); #endif =20 #ifdef DOMAIN_FIELD -DOMAIN_FIELD(__u32, idle_lb_count, v15); -DOMAIN_FIELD(__u32, idle_lb_balanced, v15); -DOMAIN_FIELD(__u32, idle_lb_failed, v15); -DOMAIN_FIELD(__u32, idle_lb_imbalance, v15); -DOMAIN_FIELD(__u32, idle_lb_gained, v15); -DOMAIN_FIELD(__u32, idle_lb_hot_gained, v15); -DOMAIN_FIELD(__u32, idle_lb_nobusyq, v15); -DOMAIN_FIELD(__u32, idle_lb_nobusyg, v15); -DOMAIN_FIELD(__u32, busy_lb_count, v15); -DOMAIN_FIELD(__u32, busy_lb_balanced, v15); -DOMAIN_FIELD(__u32, busy_lb_failed, v15); -DOMAIN_FIELD(__u32, busy_lb_imbalance, v15); -DOMAIN_FIELD(__u32, busy_lb_gained, v15); -DOMAIN_FIELD(__u32, busy_lb_hot_gained, v15); -DOMAIN_FIELD(__u32, busy_lb_nobusyq, v15); -DOMAIN_FIELD(__u32, busy_lb_nobusyg, v15); -DOMAIN_FIELD(__u32, newidle_lb_count, v15); -DOMAIN_FIELD(__u32, newidle_lb_balanced, v15); -DOMAIN_FIELD(__u32, newidle_lb_failed, v15); -DOMAIN_FIELD(__u32, newidle_lb_imbalance, v15); -DOMAIN_FIELD(__u32, newidle_lb_gained, v15); -DOMAIN_FIELD(__u32, newidle_lb_hot_gained, v15); -DOMAIN_FIELD(__u32, newidle_lb_nobusyq, v15); -DOMAIN_FIELD(__u32, newidle_lb_nobusyg, v15); -DOMAIN_FIELD(__u32, alb_count, v15); -DOMAIN_FIELD(__u32, alb_failed, v15); -DOMAIN_FIELD(__u32, alb_pushed, v15); -DOMAIN_FIELD(__u32, sbe_count, v15); -DOMAIN_FIELD(__u32, sbe_balanced, v15); -DOMAIN_FIELD(__u32, sbe_pushed, v15); -DOMAIN_FIELD(__u32, sbf_count, v15); -DOMAIN_FIELD(__u32, sbf_balanced, v15); -DOMAIN_FIELD(__u32, sbf_pushed, v15); -DOMAIN_FIELD(__u32, ttwu_wake_remote, v15); -DOMAIN_FIELD(__u32, ttwu_move_affine, v15); -DOMAIN_FIELD(__u32, ttwu_move_balance, v15); +#ifdef DOMAIN_CATEGORY +DOMAIN_CATEGORY(" "); #endif +DOMAIN_FIELD(__u32, idle_lb_count, + "load_balance() count on cpu idle", "%11u", true, v15); +DOMAIN_FIELD(__u32, idle_lb_balanced, + "load_balance() found balanced on cpu idle", "%11u", true, v15); +DOMAIN_FIELD(__u32, idle_lb_failed, + "load_balance() move task failed on cpu idle", "%11u", true, v15); +DOMAIN_FIELD(__u32, idle_lb_imbalance, + "imbalance sum on cpu idle", "%11u", false, v15); +DOMAIN_FIELD(__u32, idle_lb_gained, + "pull_task() count on cpu idle", "%11u", false, v15); +DOMAIN_FIELD(__u32, idle_lb_hot_gained, + "pull_task() when target task was cache-hot on cpu idle", "%11u", fa= lse, v15); +DOMAIN_FIELD(__u32, idle_lb_nobusyq, + "load_balance() failed to find busier queue on cpu idle", "%11u", tr= ue, v15); +DOMAIN_FIELD(__u32, idle_lb_nobusyg, + "load_balance() failed to find busier group on cpu idle", "%11u", tr= ue, v15); +#ifdef DERIVED_CNT_FIELD +DERIVED_CNT_FIELD("load_balance() success count on cpu idle", "%11u", + idle_lb_count, idle_lb_balanced, idle_lb_failed, v15); +#endif +#ifdef DERIVED_AVG_FIELD +DERIVED_AVG_FIELD("avg task pulled per successful lb attempt (cpu idle)", = "%11.2Lf", + idle_lb_count, idle_lb_balanced, idle_lb_failed, idle_lb_gained, v15); +#endif +#ifdef DOMAIN_CATEGORY +DOMAIN_CATEGORY(" "); +#endif +DOMAIN_FIELD(__u32, busy_lb_count, + "load_balance() count on cpu busy", "%11u", true, v15); +DOMAIN_FIELD(__u32, busy_lb_balanced, + "load_balance() found balanced on cpu busy", "%11u", true, v15); +DOMAIN_FIELD(__u32, busy_lb_failed, + "load_balance() move task failed on cpu busy", "%11u", true, v15); +DOMAIN_FIELD(__u32, busy_lb_imbalance, + "imbalance sum on cpu busy", "%11u", false, v15); +DOMAIN_FIELD(__u32, busy_lb_gained, + "pull_task() count on cpu busy", "%11u", false, v15); +DOMAIN_FIELD(__u32, busy_lb_hot_gained, + "pull_task() when target task was cache-hot on cpu busy", "%11u", fa= lse, v15); +DOMAIN_FIELD(__u32, busy_lb_nobusyq, + "load_balance() failed to find busier queue on cpu busy", "%11u", tr= ue, v15); +DOMAIN_FIELD(__u32, busy_lb_nobusyg, + "load_balance() failed to find busier group on cpu busy", "%11u", tr= ue, v15); +#ifdef DERIVED_CNT_FIELD +DERIVED_CNT_FIELD("load_balance() success count on cpu busy", "%11u", + busy_lb_count, busy_lb_balanced, busy_lb_failed, v15); +#endif +#ifdef DERIVED_AVG_FIELD +DERIVED_AVG_FIELD("avg task pulled per successful lb attempt (cpu busy)", = "%11.2Lf", + busy_lb_count, busy_lb_balanced, busy_lb_failed, busy_lb_gained, v15); +#endif +#ifdef DOMAIN_CATEGORY +DOMAIN_CATEGORY(" "); +#endif +DOMAIN_FIELD(__u32, newidle_lb_count, + "load_balance() count on cpu newly idle", "%11u", true, v15); +DOMAIN_FIELD(__u32, newidle_lb_balanced, + "load_balance() found balanced on cpu newly idle", "%11u", true, v15= ); +DOMAIN_FIELD(__u32, newidle_lb_failed, + "load_balance() move task failed on cpu newly idle", "%11u", true, v= 15); +DOMAIN_FIELD(__u32, newidle_lb_imbalance, + "imbalance sum on cpu newly idle", "%11u", false, v15); +DOMAIN_FIELD(__u32, newidle_lb_gained, + "pull_task() count on cpu newly idle", "%11u", false, v15); +DOMAIN_FIELD(__u32, newidle_lb_hot_gained, + "pull_task() when target task was cache-hot on cpu newly idle", "%11= u", false, v15); +DOMAIN_FIELD(__u32, newidle_lb_nobusyq, + "load_balance() failed to find busier queue on cpu newly idle", "%11= u", true, v15); +DOMAIN_FIELD(__u32, newidle_lb_nobusyg, + "load_balance() failed to find busier group on cpu newly idle", "%11= u", true, v15); +#ifdef DERIVED_CNT_FIELD +DERIVED_CNT_FIELD("load_balance() success count on cpu newly idle", "%11u", + newidle_lb_count, newidle_lb_balanced, newidle_lb_failed, v15); +#endif +#ifdef DERIVED_AVG_FIELD +DERIVED_AVG_FIELD("avg task pulled per successful lb attempt (cpu newly id= le)", "%11.2Lf", + newidle_lb_count, newidle_lb_balanced, newidle_lb_failed, newidle_lb_g= ained, v15); +#endif +#ifdef DOMAIN_CATEGORY +DOMAIN_CATEGORY(" "); +#endif +DOMAIN_FIELD(__u32, alb_count, + "active_load_balance() count", "%11u", false, v15); +DOMAIN_FIELD(__u32, alb_failed, + "active_load_balance() move task failed", "%11u", false, v15); +DOMAIN_FIELD(__u32, alb_pushed, + "active_load_balance() successfully moved a task", "%11u", false, v1= 5); +#ifdef DOMAIN_CATEGORY +DOMAIN_CATEGORY(" "); +#endif +DOMAIN_FIELD(__u32, sbe_count, + "sbe_count is not used", "%11u", false, v15); +DOMAIN_FIELD(__u32, sbe_balanced, + "sbe_balanced is not used", "%11u", false, v15); +DOMAIN_FIELD(__u32, sbe_pushed, + "sbe_pushed is not used", "%11u", false, v15); +#ifdef DOMAIN_CATEGORY +DOMAIN_CATEGORY(" "); +#endif +DOMAIN_FIELD(__u32, sbf_count, + "sbf_count is not used", "%11u", false, v15); +DOMAIN_FIELD(__u32, sbf_balanced, + "sbf_balanced is not used", "%11u", false, v15); +DOMAIN_FIELD(__u32, sbf_pushed, + "sbf_pushed is not used", "%11u", false, v15); +#ifdef DOMAIN_CATEGORY +DOMAIN_CATEGORY(" "); +#endif +DOMAIN_FIELD(__u32, ttwu_wake_remote, + "try_to_wake_up() awoke a task that last ran on a diff cpu", "%11u",= false, v15); +DOMAIN_FIELD(__u32, ttwu_move_affine, + "try_to_wake_up() moved task because cache-cold on own cpu", "%11u",= false, v15); +DOMAIN_FIELD(__u32, ttwu_move_balance, + "try_to_wake_up() started passive balancing", "%11u", false, v15); +#endif /* DOMAIN_FIELD */ diff --git a/tools/lib/perf/include/perf/schedstat-v16.h b/tools/lib/perf/i= nclude/perf/schedstat-v16.h index d6a4691b2fd5..aebbed6a6151 100644 --- a/tools/lib/perf/include/perf/schedstat-v16.h +++ b/tools/lib/perf/include/perf/schedstat-v16.h @@ -1,52 +1,143 @@ /* SPDX-License-Identifier: GPL-2.0 */ =20 #ifdef CPU_FIELD -CPU_FIELD(__u32, yld_count, v16); -CPU_FIELD(__u32, array_exp, v16); -CPU_FIELD(__u32, sched_count, v16); -CPU_FIELD(__u32, sched_goidle, v16); -CPU_FIELD(__u32, ttwu_count, v16); -CPU_FIELD(__u32, ttwu_local, v16); -CPU_FIELD(__u64, rq_cpu_time, v16); -CPU_FIELD(__u64, run_delay, v16); -CPU_FIELD(__u64, pcount, v16); -#endif +CPU_FIELD(__u32, yld_count, "sched_yield() count", + "%11u", false, yld_count, v16); +CPU_FIELD(__u32, array_exp, "Legacy counter can be ignored", + "%11u", false, array_exp, v16); +CPU_FIELD(__u32, sched_count, "schedule() called", + "%11u", false, sched_count, v16); +CPU_FIELD(__u32, sched_goidle, "schedule() left the processor idle", + "%11u", true, sched_count, v16); +CPU_FIELD(__u32, ttwu_count, "try_to_wake_up() was called", + "%11u", false, ttwu_count, v16); +CPU_FIELD(__u32, ttwu_local, "try_to_wake_up() was called to wake up the l= ocal cpu", + "%11u", true, ttwu_count, v16); +CPU_FIELD(__u64, rq_cpu_time, "total runtime by tasks on this processor (i= n jiffies)", + "%11llu", false, rq_cpu_time, v16); +CPU_FIELD(__u64, run_delay, "total waittime by tasks on this processor (in= jiffies)", + "%11llu", true, rq_cpu_time, v16); +CPU_FIELD(__u64, pcount, "total timeslices run on this cpu", + "%11llu", false, pcount, v16); +#endif /* CPU_FIELD */ +/* SPDX-License-Identifier: GPL-2.0 */ =20 #ifdef DOMAIN_FIELD -DOMAIN_FIELD(__u32, busy_lb_count, v16); -DOMAIN_FIELD(__u32, busy_lb_balanced, v16); -DOMAIN_FIELD(__u32, busy_lb_failed, v16); -DOMAIN_FIELD(__u32, busy_lb_imbalance, v16); -DOMAIN_FIELD(__u32, busy_lb_gained, v16); -DOMAIN_FIELD(__u32, busy_lb_hot_gained, v16); -DOMAIN_FIELD(__u32, busy_lb_nobusyq, v16); -DOMAIN_FIELD(__u32, busy_lb_nobusyg, v16); -DOMAIN_FIELD(__u32, idle_lb_count, v16); -DOMAIN_FIELD(__u32, idle_lb_balanced, v16); -DOMAIN_FIELD(__u32, idle_lb_failed, v16); -DOMAIN_FIELD(__u32, idle_lb_imbalance, v16); -DOMAIN_FIELD(__u32, idle_lb_gained, v16); -DOMAIN_FIELD(__u32, idle_lb_hot_gained, v16); -DOMAIN_FIELD(__u32, idle_lb_nobusyq, v16); -DOMAIN_FIELD(__u32, idle_lb_nobusyg, v16); -DOMAIN_FIELD(__u32, newidle_lb_count, v16); -DOMAIN_FIELD(__u32, newidle_lb_balanced, v16); -DOMAIN_FIELD(__u32, newidle_lb_failed, v16); -DOMAIN_FIELD(__u32, newidle_lb_imbalance, v16); -DOMAIN_FIELD(__u32, newidle_lb_gained, v16); -DOMAIN_FIELD(__u32, newidle_lb_hot_gained, v16); -DOMAIN_FIELD(__u32, newidle_lb_nobusyq, v16); -DOMAIN_FIELD(__u32, newidle_lb_nobusyg, v16); -DOMAIN_FIELD(__u32, alb_count, v16); -DOMAIN_FIELD(__u32, alb_failed, v16); -DOMAIN_FIELD(__u32, alb_pushed, v16); -DOMAIN_FIELD(__u32, sbe_count, v16); -DOMAIN_FIELD(__u32, sbe_balanced, v16); -DOMAIN_FIELD(__u32, sbe_pushed, v16); -DOMAIN_FIELD(__u32, sbf_count, v16); -DOMAIN_FIELD(__u32, sbf_balanced, v16); -DOMAIN_FIELD(__u32, sbf_pushed, v16); -DOMAIN_FIELD(__u32, ttwu_wake_remote, v16); -DOMAIN_FIELD(__u32, ttwu_move_affine, v16); -DOMAIN_FIELD(__u32, ttwu_move_balance, v16); +#ifdef DOMAIN_CATEGORY +DOMAIN_CATEGORY(" "); +#endif +DOMAIN_FIELD(__u32, busy_lb_count, + "load_balance() count on cpu busy", "%11u", true, v16); +DOMAIN_FIELD(__u32, busy_lb_balanced, + "load_balance() found balanced on cpu busy", "%11u", true, v16); +DOMAIN_FIELD(__u32, busy_lb_failed, + "load_balance() move task failed on cpu busy", "%11u", true, v16); +DOMAIN_FIELD(__u32, busy_lb_imbalance, + "imbalance sum on cpu busy", "%11u", false, v16); +DOMAIN_FIELD(__u32, busy_lb_gained, + "pull_task() count on cpu busy", "%11u", false, v16); +DOMAIN_FIELD(__u32, busy_lb_hot_gained, + "pull_task() when target task was cache-hot on cpu busy", "%11u", fa= lse, v16); +DOMAIN_FIELD(__u32, busy_lb_nobusyq, + "load_balance() failed to find busier queue on cpu busy", "%11u", tr= ue, v16); +DOMAIN_FIELD(__u32, busy_lb_nobusyg, + "load_balance() failed to find busier group on cpu busy", "%11u", tr= ue, v16); +#ifdef DERIVED_CNT_FIELD +DERIVED_CNT_FIELD("load_balance() success count on cpu busy", "%11u", + busy_lb_count, busy_lb_balanced, busy_lb_failed, v16); +#endif +#ifdef DERIVED_AVG_FIELD +DERIVED_AVG_FIELD("avg task pulled per successful lb attempt (cpu busy)", = "%11.2Lf", + busy_lb_count, busy_lb_balanced, busy_lb_failed, busy_lb_gained, v16); +#endif +#ifdef DOMAIN_CATEGORY +DOMAIN_CATEGORY(" "); +#endif +DOMAIN_FIELD(__u32, idle_lb_count, + "load_balance() count on cpu idle", "%11u", true, v16); +DOMAIN_FIELD(__u32, idle_lb_balanced, + "load_balance() found balanced on cpu idle", "%11u", true, v16); +DOMAIN_FIELD(__u32, idle_lb_failed, + "load_balance() move task failed on cpu idle", "%11u", true, v16); +DOMAIN_FIELD(__u32, idle_lb_imbalance, + "imbalance sum on cpu idle", "%11u", false, v16); +DOMAIN_FIELD(__u32, idle_lb_gained, + "pull_task() count on cpu idle", "%11u", false, v16); +DOMAIN_FIELD(__u32, idle_lb_hot_gained, + "pull_task() when target task was cache-hot on cpu idle", "%11u", fa= lse, v16); +DOMAIN_FIELD(__u32, idle_lb_nobusyq, + "load_balance() failed to find busier queue on cpu idle", "%11u", tr= ue, v16); +DOMAIN_FIELD(__u32, idle_lb_nobusyg, + "load_balance() failed to find busier group on cpu idle", "%11u", tr= ue, v16); +#ifdef DERIVED_CNT_FIELD +DERIVED_CNT_FIELD("load_balance() success count on cpu idle", "%11u", + idle_lb_count, idle_lb_balanced, idle_lb_failed, v16); +#endif +#ifdef DERIVED_AVG_FIELD +DERIVED_AVG_FIELD("avg task pulled per successful lb attempt (cpu idle)", = "%11.2Lf", + idle_lb_count, idle_lb_balanced, idle_lb_failed, idle_lb_gained, v16); +#endif +#ifdef DOMAIN_CATEGORY +DOMAIN_CATEGORY(" "); +#endif +DOMAIN_FIELD(__u32, newidle_lb_count, + "load_balance() count on cpu newly idle", "%11u", true, v16); +DOMAIN_FIELD(__u32, newidle_lb_balanced, + "load_balance() found balanced on cpu newly idle", "%11u", true, v16= ); +DOMAIN_FIELD(__u32, newidle_lb_failed, + "load_balance() move task failed on cpu newly idle", "%11u", true, v= 16); +DOMAIN_FIELD(__u32, newidle_lb_imbalance, + "imbalance sum on cpu newly idle", "%11u", false, v16); +DOMAIN_FIELD(__u32, newidle_lb_gained, + "pull_task() count on cpu newly idle", "%11u", false, v16); +DOMAIN_FIELD(__u32, newidle_lb_hot_gained, + "pull_task() when target task was cache-hot on cpu newly idle", "%11= u", false, v16); +DOMAIN_FIELD(__u32, newidle_lb_nobusyq, + "load_balance() failed to find busier queue on cpu newly idle", "%11= u", true, v16); +DOMAIN_FIELD(__u32, newidle_lb_nobusyg, + "load_balance() failed to find busier group on cpu newly idle", "%11= u", true, v16); +#ifdef DERIVED_CNT_FIELD +DERIVED_CNT_FIELD("load_balance() success count on cpu newly idle", "%11u", + newidle_lb_count, newidle_lb_balanced, newidle_lb_failed, v16); +#endif +#ifdef DERIVED_AVG_FIELD +DERIVED_AVG_FIELD("avg task pulled per successful lb attempt (cpu newly id= le)", "%11.2Lf", + newidle_lb_count, newidle_lb_balanced, newidle_lb_failed, newidle_lb_g= ained, v16); +#endif +#ifdef DOMAIN_CATEGORY +DOMAIN_CATEGORY(" "); +#endif +DOMAIN_FIELD(__u32, alb_count, + "active_load_balance() count", "%11u", false, v16); +DOMAIN_FIELD(__u32, alb_failed, + "active_load_balance() move task failed", "%11u", false, v16); +DOMAIN_FIELD(__u32, alb_pushed, + "active_load_balance() successfully moved a task", "%11u", false, v1= 6); +#ifdef DOMAIN_CATEGORY +DOMAIN_CATEGORY(" "); +#endif +DOMAIN_FIELD(__u32, sbe_count, + "sbe_count is not used", "%11u", false, v16); +DOMAIN_FIELD(__u32, sbe_balanced, + "sbe_balanced is not used", "%11u", false, v16); +DOMAIN_FIELD(__u32, sbe_pushed, + "sbe_pushed is not used", "%11u", false, v16); +#ifdef DOMAIN_CATEGORY +DOMAIN_CATEGORY(" "); +#endif +DOMAIN_FIELD(__u32, sbf_count, + "sbf_count is not used", "%11u", false, v16); +DOMAIN_FIELD(__u32, sbf_balanced, + "sbf_balanced is not used", "%11u", false, v16); +DOMAIN_FIELD(__u32, sbf_pushed, + "sbf_pushed is not used", "%11u", false, v16); +#ifdef DOMAIN_CATEGORY +DOMAIN_CATEGORY(" "); #endif +DOMAIN_FIELD(__u32, ttwu_wake_remote, + "try_to_wake_up() awoke a task that last ran on a diff cpu", "%11u",= false, v16); +DOMAIN_FIELD(__u32, ttwu_move_affine, + "try_to_wake_up() moved task because cache-cold on own cpu", "%11u",= false, v16); +DOMAIN_FIELD(__u32, ttwu_move_balance, + "try_to_wake_up() started passive balancing", "%11u", false, v16); +#endif /* DOMAIN_FIELD */ diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 7dfce34748e4..58a4f6ce0448 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -3859,6 +3859,489 @@ static int perf_sched__schedstat_record(struct perf= _sched *sched, return err; } =20 +struct schedstat_domain { + struct perf_record_schedstat_domain *domain_data; + struct schedstat_domain *next; +}; + +struct schedstat_cpu { + struct perf_record_schedstat_cpu *cpu_data; + struct schedstat_domain *domain_head; + struct schedstat_cpu *next; +}; + +struct schedstat_cpu *cpu_head =3D NULL, *cpu_tail =3D NULL, *cpu_second_p= ass =3D NULL; +struct schedstat_domain *domain_tail =3D NULL, *domain_second_pass =3D NUL= L; +bool after_workload_flag; + +static void store_schedtstat_cpu_diff(struct schedstat_cpu *after_workload) +{ + struct perf_record_schedstat_cpu *before =3D cpu_second_pass->cpu_data; + struct perf_record_schedstat_cpu *after =3D after_workload->cpu_data; + __u16 version =3D after_workload->cpu_data->version; + +#define CPU_FIELD(_type, _name, _desc, _format, _is_pct, _pct_of, _ver) \ + (before->_ver._name =3D after->_ver._name - before->_ver._name) + + if (version =3D=3D 15) { +#include + } else if (version =3D=3D 16) { +#include + } + +#undef CPU_FIELD +} + +static void store_schedstat_domain_diff(struct schedstat_domain *after_wor= kload) +{ + struct perf_record_schedstat_domain *before =3D domain_second_pass->domai= n_data; + struct perf_record_schedstat_domain *after =3D after_workload->domain_dat= a; + __u16 version =3D after_workload->domain_data->version; + +#define DOMAIN_FIELD(_type, _name, _desc, _format, _is_jiffies, _ver) \ + (before->_ver._name =3D after->_ver._name - before->_ver._name) + + if (version =3D=3D 15) { +#include + } else if (version =3D=3D 16) { +#include + } +#undef DOMAIN_FIELD +} + +static void print_separator(size_t pre_dash_cnt, const char *s, size_t pos= t_dash_cnt) +{ + size_t i; + + for (i =3D 0; i < pre_dash_cnt; ++i) + printf("-"); + + printf("%s", s); + + for (i =3D 0; i < post_dash_cnt; ++i) + printf("-"); + + printf("\n"); +} + +static inline void print_cpu_stats(struct perf_record_schedstat_cpu *cs) +{ + printf("%-65s %12s %12s\n", "DESC", "COUNT", "PCT_CHANGE"); + print_separator(100, "", 0); + +#define CALC_PCT(_x, _y) ((_y) ? ((double)(_x) / (_y)) * 100 : 0.0) + +#define CPU_FIELD(_type, _name, _desc, _format, _is_pct, _pct_of, _ver) \ + do { \ + printf("%-65s: " _format, _desc, cs->_ver._name); \ + if (_is_pct) { \ + printf(" ( %8.2lf%% )", \ + CALC_PCT(cs->_ver._name, cs->_ver._pct_of)); \ + } \ + printf("\n"); \ + } while (0) + + if (cs->version =3D=3D 15) { +#include + } else if (cs->version =3D=3D 16) { +#include + } + +#undef CPU_FIELD +#undef CALC_PCT +} + +static inline void print_domain_stats(struct perf_record_schedstat_domain = *ds, + __u64 jiffies) +{ + printf("%-65s %12s %14s\n", "DESC", "COUNT", "AVG_JIFFIES"); + +#define DOMAIN_CATEGORY(_desc) \ + do { \ + size_t _len =3D strlen(_desc); \ + size_t _pre_dash_cnt =3D (100 - _len) / 2; \ + size_t _post_dash_cnt =3D 100 - _len - _pre_dash_cnt; \ + print_separator(_pre_dash_cnt, _desc, _post_dash_cnt); \ + } while (0) + +#define CALC_AVG(_x, _y) ((_y) ? (long double)(_x) / (_y) : 0.0) + +#define DOMAIN_FIELD(_type, _name, _desc, _format, _is_jiffies, _ver) \ + do { \ + printf("%-65s: " _format, _desc, ds->_ver._name); \ + if (_is_jiffies) { \ + printf(" $ %11.2Lf $", \ + CALC_AVG(jiffies, ds->_ver._name)); \ + } \ + printf("\n"); \ + } while (0) + +#define DERIVED_CNT_FIELD(_desc, _format, _x, _y, _z, _ver) \ + printf("*%-64s: " _format "\n", _desc, \ + (ds->_ver._x) - (ds->_ver._y) - (ds->_ver._z)) + +#define DERIVED_AVG_FIELD(_desc, _format, _x, _y, _z, _w, _ver) \ + printf("*%-64s: " _format "\n", _desc, CALC_AVG(ds->_ver._w, \ + ((ds->_ver._x) - (ds->_ver._y) - (ds->_ver._z)))) + + if (ds->version =3D=3D 15) { +#include + } else if (ds->version =3D=3D 16) { +#include + } + +#undef DERIVED_AVG_FIELD +#undef DERIVED_CNT_FIELD +#undef DOMAIN_FIELD +#undef CALC_AVG +#undef DOMAIN_CATEGORY +} + +static void print_domain_cpu_list(struct perf_record_schedstat_domain *ds) +{ + char bin[16][5] =3D {"0000", "0001", "0010", "0011", + "0100", "0101", "0110", "0111", + "1000", "1001", "1010", "1011", + "1100", "1101", "1110", "1111"}; + bool print_flag =3D false, low =3D true; + int cpu =3D 0, start, end, idx; + + idx =3D ((ds->nr_cpus + 7) >> 3) - 1; + + printf("<"); + while (idx >=3D 0) { + __u8 index; + + if (low) + index =3D ds->cpu_mask[idx] & 0xf; + else + index =3D (ds->cpu_mask[idx--] & 0xf0) >> 4; + + for (int i =3D 3; i >=3D 0; i--) { + if (!print_flag && bin[index][i] =3D=3D '1') { + start =3D cpu; + print_flag =3D true; + } else if (print_flag && bin[index][i] =3D=3D '0') { + end =3D cpu - 1; + print_flag =3D false; + if (start =3D=3D end) + printf("%d, ", start); + else + printf("%d-%d, ", start, end); + } + cpu++; + } + + low =3D !low; + } + + if (print_flag) { + if (start =3D=3D cpu-1) + printf("%d, ", start); + else + printf("%d-%d, ", start, cpu-1); + } + printf("\b\b>\n"); +} + +static void summarize_schedstat_cpu(struct schedstat_cpu *summary_cpu, + struct schedstat_cpu *cptr, + int cnt, bool is_last) +{ + struct perf_record_schedstat_cpu *summary_cs =3D summary_cpu->cpu_data, + *temp_cs =3D cptr->cpu_data; + +#define CPU_FIELD(_type, _name, _desc, _format, _is_pct, _pct_of, _ver) \ + do { \ + summary_cs->_ver._name +=3D temp_cs->_ver._name; \ + if (is_last) \ + summary_cs->_ver._name /=3D cnt; \ + } while (0) + + if (cptr->cpu_data->version =3D=3D 15) { +#include + } else if (cptr->cpu_data->version =3D=3D 16) { +#include + } +#undef CPU_FIELD +} + +static void summarize_schedstat_domain(struct schedstat_domain *summary_do= main, + struct schedstat_domain *dptr, + int cnt, bool is_last) +{ + struct perf_record_schedstat_domain *summary_ds =3D summary_domain->domai= n_data, + *temp_ds =3D dptr->domain_data; + +#define DOMAIN_FIELD(_type, _name, _desc, _format, _is_jiffies, _ver) \ + do { \ + summary_ds->_ver._name +=3D temp_ds->_ver._name; \ + if (is_last) \ + summary_ds->_ver._name /=3D cnt; \ + } while (0) + + if (dptr->domain_data->version =3D=3D 15) { +#include + } else if (dptr->domain_data->version =3D=3D 16) { +#include + } +#undef DOMAIN_FIELD +} + +static void get_all_cpu_stats(struct schedstat_cpu **cptr) +{ + struct schedstat_domain *dptr =3D NULL, *tdptr =3D NULL, *dtail =3D NULL; + struct schedstat_cpu *tcptr =3D *cptr, *summary_head =3D NULL; + struct perf_record_schedstat_domain *ds =3D NULL; + struct perf_record_schedstat_cpu *cs =3D NULL; + bool is_last =3D false; + int cnt =3D 0; + + if (tcptr) { + summary_head =3D zalloc(sizeof(*summary_head)); + summary_head->cpu_data =3D zalloc(sizeof(*cs)); + memcpy(summary_head->cpu_data, tcptr->cpu_data, sizeof(*cs)); + summary_head->next =3D NULL; + summary_head->domain_head =3D NULL; + dptr =3D tcptr->domain_head; + + while (dptr) { + size_t cpu_mask_size =3D (dptr->domain_data->nr_cpus + 7) >> 3; + + tdptr =3D zalloc(sizeof(*tdptr)); + tdptr->domain_data =3D zalloc(sizeof(*ds) + cpu_mask_size); + memcpy(tdptr->domain_data, dptr->domain_data, sizeof(*ds) + cpu_mask_si= ze); + + tdptr->next =3D NULL; + if (!dtail) { + summary_head->domain_head =3D tdptr; + dtail =3D tdptr; + } else { + dtail->next =3D tdptr; + dtail =3D dtail->next; + } + dptr =3D dptr->next; + } + } + + tcptr =3D (*cptr)->next; + while (tcptr) { + if (!tcptr->next) + is_last =3D true; + + cnt++; + summarize_schedstat_cpu(summary_head, tcptr, cnt, is_last); + tdptr =3D summary_head->domain_head; + dptr =3D tcptr->domain_head; + + while (tdptr) { + summarize_schedstat_domain(tdptr, dptr, cnt, is_last); + tdptr =3D tdptr->next; + dptr =3D dptr->next; + } + tcptr =3D tcptr->next; + } + + tcptr =3D *cptr; + summary_head->next =3D tcptr; + *cptr =3D summary_head; +} + +/* FIXME: The code fails (segfaults) when one or ore cpus are offline. */ +static void show_schedstat_data(struct schedstat_cpu *cptr) +{ + struct perf_record_schedstat_domain *ds =3D NULL; + struct perf_record_schedstat_cpu *cs =3D NULL; + __u64 jiffies =3D cptr->cpu_data->timestamp; + struct schedstat_domain *dptr =3D NULL; + bool is_summary =3D true; + + printf("Columns description\n"); + print_separator(100, "", 0); + printf("DESC\t\t\t-> Description of the field\n"); + printf("COUNT\t\t\t-> Value of the field\n"); + printf("PCT_CHANGE\t\t-> Percent change with corresponding base value\n"); + printf("AVG_JIFFIES\t\t-> Avg time in jiffies between two consecutive occ= urrence of event\n"); + + print_separator(100, "", 0); + printf("Time elapsed (in jiffies) = : %11llu\n", + jiffies); + print_separator(100, "", 0); + + get_all_cpu_stats(&cptr); + + while (cptr) { + cs =3D cptr->cpu_data; + printf("\n"); + print_separator(100, "", 0); + if (is_summary) + printf("CPU \n"); + else + printf("CPU %d\n", cs->cpu); + + print_separator(100, "", 0); + print_cpu_stats(cs); + print_separator(100, "", 0); + + dptr =3D cptr->domain_head; + + while (dptr) { + ds =3D dptr->domain_data; + if (is_summary) + if (ds->name[0]) + printf("CPU , DOMAIN %s\n", ds->name); + else + printf("CPU , DOMAIN %d\n", ds->domain); + else { + if (ds->name[0]) + printf("CPU %d, DOMAIN %s CPUS ", cs->cpu, ds->name); + else + printf("CPU %d, DOMAIN %d CPUS ", cs->cpu, ds->domain); + + print_domain_cpu_list(ds); + } + print_separator(100, "", 0); + print_domain_stats(ds, jiffies); + print_separator(100, "", 0); + + dptr =3D dptr->next; + } + is_summary =3D false; + cptr =3D cptr->next; + } +} + +static int perf_sched__process_schedstat(struct perf_session *session __ma= ybe_unused, + union perf_event *event) +{ + struct perf_cpu this_cpu; + static __u32 initial_cpu; + + switch (event->header.type) { + case PERF_RECORD_SCHEDSTAT_CPU: + this_cpu.cpu =3D event->schedstat_cpu.cpu; + break; + case PERF_RECORD_SCHEDSTAT_DOMAIN: + this_cpu.cpu =3D event->schedstat_domain.cpu; + break; + default: + return 0; + } + + if (user_requested_cpus && !perf_cpu_map__has(user_requested_cpus, this_c= pu)) + return 0; + + if (event->header.type =3D=3D PERF_RECORD_SCHEDSTAT_CPU) { + struct schedstat_cpu *temp =3D zalloc(sizeof(struct schedstat_cpu)); + + temp->cpu_data =3D zalloc(sizeof(struct perf_record_schedstat_cpu)); + memcpy(temp->cpu_data, &event->schedstat_cpu, + sizeof(struct perf_record_schedstat_cpu)); + temp->next =3D NULL; + temp->domain_head =3D NULL; + + if (cpu_head && temp->cpu_data->cpu =3D=3D initial_cpu) + after_workload_flag =3D true; + + if (!after_workload_flag) { + if (!cpu_head) { + initial_cpu =3D temp->cpu_data->cpu; + cpu_head =3D temp; + } else + cpu_tail->next =3D temp; + + cpu_tail =3D temp; + } else { + if (temp->cpu_data->cpu =3D=3D initial_cpu) { + cpu_second_pass =3D cpu_head; + cpu_head->cpu_data->timestamp =3D + temp->cpu_data->timestamp - cpu_second_pass->cpu_data->timestamp; + } else { + cpu_second_pass =3D cpu_second_pass->next; + } + domain_second_pass =3D cpu_second_pass->domain_head; + store_schedtstat_cpu_diff(temp); + } + } else if (event->header.type =3D=3D PERF_RECORD_SCHEDSTAT_DOMAIN) { + size_t cpu_mask_size =3D (event->schedstat_domain.nr_cpus + 7) >> 3; + struct schedstat_domain *temp =3D zalloc(sizeof(struct schedstat_domain)= ); + + temp->domain_data =3D zalloc(sizeof(struct perf_record_schedstat_domain)= + cpu_mask_size); + memcpy(temp->domain_data, &event->schedstat_domain, + sizeof(struct perf_record_schedstat_domain) + cpu_mask_size); + temp->next =3D NULL; + + if (!after_workload_flag) { + if (cpu_tail->domain_head =3D=3D NULL) { + cpu_tail->domain_head =3D temp; + domain_tail =3D temp; + } else { + domain_tail->next =3D temp; + domain_tail =3D temp; + } + } else { + store_schedstat_domain_diff(temp); + domain_second_pass =3D domain_second_pass->next; + } + } + + return 0; +} + +static void free_schedstat(struct schedstat_cpu *cptr) +{ + struct schedstat_domain *dptr =3D NULL, *tmp_dptr; + struct schedstat_cpu *tmp_cptr; + + while (cptr) { + tmp_cptr =3D cptr; + dptr =3D cptr->domain_head; + + while (dptr) { + tmp_dptr =3D dptr; + dptr =3D dptr->next; + free(tmp_dptr); + } + cptr =3D cptr->next; + free(tmp_cptr); + } +} + +static int perf_sched__schedstat_report(struct perf_sched *sched) +{ + struct perf_session *session; + struct perf_data data =3D { + .path =3D input_name, + .mode =3D PERF_DATA_MODE_READ, + }; + int err; + + if (cpu_list) { + user_requested_cpus =3D perf_cpu_map__new(cpu_list); + if (!user_requested_cpus) + return -EINVAL; + } + + sched->tool.schedstat_cpu =3D perf_sched__process_schedstat; + sched->tool.schedstat_domain =3D perf_sched__process_schedstat; + + session =3D perf_session__new(&data, &sched->tool); + if (IS_ERR(session)) { + pr_err("Perf session creation failed.\n"); + return PTR_ERR(session); + } + + err =3D perf_session__process_events(session); + + perf_session__delete(session); + if (!err) { + setup_pager(); + show_schedstat_data(cpu_head); + free_schedstat(cpu_head); + } + return err; +} + static bool schedstat_events_exposed(void) { /* @@ -4035,6 +4518,8 @@ int cmd_sched(int argc, const char **argv) OPT_PARENT(sched_options) }; const struct option stats_options[] =3D { + OPT_STRING('i', "input", &input_name, "file", + "`stats report` with input filename"), OPT_STRING('o', "output", &output_name, "file", "`stats record` with output filename"), OPT_STRING('C', "cpu", &cpu_list, "cpu", "list of cpus to profile"), @@ -4160,7 +4645,7 @@ int cmd_sched(int argc, const char **argv) =20 return perf_sched__timehist(&sched); } else if (!strcmp(argv[0], "stats")) { - const char *const stats_subcommands[] =3D {"record", NULL}; + const char *const stats_subcommands[] =3D {"record", "report", NULL}; =20 argc =3D parse_options_subcommand(argc, argv, stats_options, stats_subcommands, @@ -4172,6 +4657,11 @@ int cmd_sched(int argc, const char **argv) argc =3D parse_options(argc, argv, stats_options, stats_usage, 0); return perf_sched__schedstat_record(&sched, argc, argv); + } else if (argv[0] && !strcmp(argv[0], "report")) { + if (argc) + argc =3D parse_options(argc, argv, stats_options, + stats_usage, 0); + return perf_sched__schedstat_report(&sched); } usage_with_options(stats_usage, stats_options); } else { diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 64f81e7b7f70..72aaf1991b6c 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -560,7 +560,7 @@ size_t perf_event__fprintf_schedstat_cpu(union perf_eve= nt *event, FILE *fp) =20 size =3D fprintf(fp, "\ncpu%u ", cs->cpu); =20 -#define CPU_FIELD(_type, _name, _ver) \ +#define CPU_FIELD(_type, _name, _desc, _format, _is_pct, _pct_of, _ver) \ size +=3D fprintf(fp, "%" PRIu64 " ", (unsigned long)cs->_ver._name) =20 if (version =3D=3D 15) { @@ -638,7 +638,7 @@ size_t perf_event__fprintf_schedstat_domain(union perf_= event *event, FILE *fp) size +=3D fprintf(fp, "%s ", cpu_mask); free(cpu_mask); =20 -#define DOMAIN_FIELD(_type, _name, _ver) \ +#define DOMAIN_FIELD(_type, _name, _desc, _format, _is_jiffies, _ver) \ size +=3D fprintf(fp, "%" PRIu64 " ", (unsigned long)ds->_ver._name) =20 if (version =3D=3D 15) { diff --git a/tools/perf/util/synthetic-events.c b/tools/perf/util/synthetic= -events.c index f200f7ece3ef..03f72cc5d5fa 100644 --- a/tools/perf/util/synthetic-events.c +++ b/tools/perf/util/synthetic-events.c @@ -2534,7 +2534,7 @@ static union perf_event *__synthesize_schedstat_cpu(s= truct io *io, __u16 version if (io__get_dec(io, (__u64 *)cpu) !=3D ' ') goto out_cpu; =20 -#define CPU_FIELD(_type, _name, _ver) \ +#define CPU_FIELD(_type, _name, _desc, _format, _is_pct, _pct_of, _ver) \ do { \ __u64 _tmp; \ ch =3D io__get_dec(io, &_tmp); \ @@ -2658,7 +2658,7 @@ static union perf_event *__synthesize_schedstat_domai= n(struct io *io, __u16 vers free(d_name); free(cpu_mask); =20 -#define DOMAIN_FIELD(_type, _name, _ver) \ +#define DOMAIN_FIELD(_type, _name, _desc, _format, _is_jiffies, _ver) \ do { \ __u64 _tmp; \ ch =3D io__get_dec(io, &_tmp); \ --=20 2.43.0 From nobody Fri Nov 29 18:47:08 2024 Received: from NAM11-CO1-obe.outbound.protection.outlook.com (mail-co1nam11on2077.outbound.protection.outlook.com [40.107.220.77]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 16E6D1BDA85; Fri, 22 Nov 2024 08:47:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.220.77 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732265276; cv=fail; b=YjVlKZkQDJ6XdYNZ3ynDeLqIo1PxrIHck1RSpVq2l+SvMFfFhOTETdF5BnRkgPMSPYAlpPWpjEtJ8Kml1JntJ588RaWE1SiyWeG4mlfApGjJL9SLKfuZ0IpXls0RiScoANPSBdByagTCX8hK7M/A8npTnkoMtUjRejkK8gqTcic= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732265276; c=relaxed/simple; bh=7baihDCyBQbXRIeRthnprVt5wVWlOHDrZGyqxeITuPg=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=KZNHZFpKPgdUvj/1kTSpBLvg1qQ+oAkFAcy9tinzPeELi5ctogQCyFlERESoXiA0fJErR/Uqux7JMYYArbjiHZ4gEgguVCR1LfgUL2/A78WbhUDeg8MF5y1EySlMmZP66QsQNnZR9uhNna+/5LsLbbVG+us77ANU92COnfUTTx8= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amd.com; spf=fail smtp.mailfrom=amd.com; dkim=pass (1024-bit key) header.d=amd.com header.i=@amd.com header.b=cWsbBI5D; arc=fail smtp.client-ip=40.107.220.77 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amd.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=amd.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=amd.com header.i=@amd.com header.b="cWsbBI5D" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=Wxbzk8W5WI9mxsCYpEc2OEZwPlW3IY1IbalS4NcWUCYL426IcGep3OQO/1JoIosEJmux1seJXbtbY9dbhWlH1AfbqV/LLh0ndkJT4NheMrzV9DeTBm9HZx6yO669rX3y4sPQiWCptjCc+I0Zh7OFcxot3xIq9Yo/gBD8Y9wfya23/06Djr3JpwAfob4v8mg6qz9JA8RETqPeuBIFQJtaeTUxcTKnv/M6MWecIRUZPnkeR8p6kX7JO6gmrf5bRAtprBa98YMbVNPOv2E3EQuLhcPEP7T1eH/wZ+rX84YUco1OixexxnsulThLdgwwNP4fMV1UL1dnRM9IONy2oG5XtA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=XJZfJEpzd8aPiTVBViqYn/Zazms5j+ky/DTLPq+gobs=; b=vQ9mT6i7OgoEKxd5prdxbiN86ToQOiMV0ZpWrQUKvcyeqS+TXoCsw1OxzO+Ju3CZcPmDSwijVwa+c6SF1F9Cwa825JdHroumgbFKqZnR9KjV8OqvMSlZvIuWEukZw4FwlV5As1YDOO8K4TxNneDm84825w+Jw5Nr15Q6RhRGSt2X+R1DW5JXUViEEbeR48gsVWajoSHpY0gLnOU2iLgMe0eqrF4xCqCi/iXeUSykYuh7GWrdBbQmVpnO9y0pEn4Mii7XdDZaoSaj9EdkyPJwCLzOgl+pNhgLrTyiplY8+OdlEovctu4YZ7wO8d9UXKbMByToKqjxkpERCyA24DZALg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.12) smtp.rcpttodomain=infradead.org smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=XJZfJEpzd8aPiTVBViqYn/Zazms5j+ky/DTLPq+gobs=; b=cWsbBI5DWsC3GGwr7x1skOCWmybiJ4uZuLA3BtMR3YATYAWJzMqdGypFN1F5WWC9HSzb/1A22eJS9ExYIJ0AscyOYwlgYtAYQRJP377L2b/Eh7hTlHcxN2lNPtQrwuGxw4iUoiBqvvB4jfR+mnNM+D26UvJlqhxOWAfzABlnV5U= Received: from BL1PR13CA0345.namprd13.prod.outlook.com (2603:10b6:208:2c6::20) by CY8PR12MB9036.namprd12.prod.outlook.com (2603:10b6:930:78::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.8182.17; Fri, 22 Nov 2024 08:47:50 +0000 Received: from BN1PEPF00004687.namprd05.prod.outlook.com (2603:10b6:208:2c6:cafe::4) by BL1PR13CA0345.outlook.office365.com (2603:10b6:208:2c6::20) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.8182.15 via Frontend Transport; Fri, 22 Nov 2024 08:47:50 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.12) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.12 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.12; helo=SATLEXMB04.amd.com; pr=C Received: from SATLEXMB04.amd.com (165.204.84.12) by BN1PEPF00004687.mail.protection.outlook.com (10.167.243.132) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.8182.16 via Frontend Transport; Fri, 22 Nov 2024 08:47:50 +0000 Received: from tapi.amd.com (10.180.168.240) by SATLEXMB04.amd.com (10.181.40.145) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.39; Fri, 22 Nov 2024 02:47:42 -0600 From: Swapnil Sapkal To: , , , , , CC: , , , , , , , , , , , , , , , , , , , , , Swapnil Sapkal , James Clark Subject: [PATCH v2 5/6] perf sched stats: Add support for live mode Date: Fri, 22 Nov 2024 08:44:51 +0000 Message-ID: <20241122084452.1064968-6-swapnil.sapkal@amd.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20241122084452.1064968-1-swapnil.sapkal@amd.com> References: <20241122084452.1064968-1-swapnil.sapkal@amd.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: SATLEXMB03.amd.com (10.181.40.144) To SATLEXMB04.amd.com (10.181.40.145) X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: BN1PEPF00004687:EE_|CY8PR12MB9036:EE_ X-MS-Office365-Filtering-Correlation-Id: 6cd72160-10e8-4bde-8df3-08dd0ad258a6 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|1800799024|36860700013|7416014|376014|82310400026; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?pxXjFpyermBSmwjpTugKllqxXO8Xun4RGthKbQCocgCIuwDM5mH4yn9PIhrm?= =?us-ascii?Q?AoKAUJh+ttkheM4paHvaKg4c3BJurR++ik8AHGuFp0kgJO0Wu2V38hh6aSYN?= =?us-ascii?Q?s/mq5zpk3H3W21IC8f585LbwuKTonanKKZ3vt9sRcq81OqVpO/Kl7NQMzlO3?= =?us-ascii?Q?drdWAnljDkZUXbXZ7FRuwI6g9xEna93mIMiCHDnh7TiZ6Py5ZXAhKp2FDN+V?= =?us-ascii?Q?304bBUdgQIaXAJ8fcx1o5Jl2V5kF89IbvgtrOGcKuwypf61RnQlB4/jhbdU7?= =?us-ascii?Q?cQC7CRmQcPNtT0FUujDG2MYLHitLY271Uz2eZ1SF58Z6oCGxVy6VXIohTcA2?= =?us-ascii?Q?B45S+cH/0DlZoxcyZlsmv4nCdicpyk319E4tCjeWz2QJ+o6PkdUAdT+lX3JF?= =?us-ascii?Q?BvA0Dvje24IRJBWHeB8SiW46fIs2gYLXfHNw66M5Eq286QhGTjQvNuCaJPP2?= =?us-ascii?Q?CWn9tt7KRHKQUgmTKzhTSF2Jwy87ohqykJCLEX1yyZZJ45Um+IAP8ZEXmFZ2?= =?us-ascii?Q?MoDWCob+3LGgIdwEgAE3bgnbgFLiZf+IWY1UvRi6OfxTcA8guQFOpo7NNWFH?= =?us-ascii?Q?RY+Y/L7T2S7L9YNYsCsrCuX0kB1HHdYhDN9By/DwbkjXEPF/hZvXUyIym2LJ?= =?us-ascii?Q?cM3EpZ5K/D2u0BT5qSolranYNRh/uuQF7UCtlcuLh/kmSdHIep8/yG8KKx2x?= =?us-ascii?Q?ejwu7dAkWqAq3S1xPBTNa5tGS9AVzfjRghcRrzAVebt6cH1O9hNfLD44NIhj?= =?us-ascii?Q?nezFWVMkVwdsnP5nMvGjogZgDNJ8nUDIrU7R/7xNlUjtk6SZU99AyRB2139C?= =?us-ascii?Q?P/57tLK0vZoEyqjrZ03XH0UpQpCUEXF1TK5RhI7m3VNxpcYgLENfRG6FWAah?= =?us-ascii?Q?UkFQCS4CMhVKykLv39d+sMKJGLGfu35hQX81UGtIWsbk6JNaw+Qn+hR4DlBn?= =?us-ascii?Q?hbiHNRPyb/pQjKpJVtWpr6bIu1LmWhERGEEecFCyBbEVf4jH2ylgxGDH6UGc?= =?us-ascii?Q?5tUfup1rcPin8LKGsgxw8d9HazkZ+x96LXnmsq8Ar4VKk8lhIagztWlkhpA7?= =?us-ascii?Q?DpSNM/01G5DtvLvarqYOXqCejfs8mlU9ltzSetNa1tAGKnmTGK3w6aDZ/86R?= =?us-ascii?Q?ibSRa8XTXkJE3vS40l5Izyjz5mr+kD9Fd/161YL5BPJZS0HaA+NFUXWgQteS?= =?us-ascii?Q?lPmntwSxfamNNvsU+1CApUForGxrXWNiPELqy2U7ACG8CVagvNHbx2BJQYca?= =?us-ascii?Q?GiJrqZMKDrJnsTy+lSW5zDoJtF64UFOFm/LouRoDt9n7LY+cpH4q9t/5BuO2?= =?us-ascii?Q?kJ9QWoWOknjVNDe5bu2MTiFt6YnlHGcCUFDgBx4pZTChK4M5y+WZrm05NuzF?= =?us-ascii?Q?VVwfdXlC5MD71nrgpnpzZcqYOBhjq4g7kEdByC8PDsCblx3Dcg=3D=3D?= X-Forefront-Antispam-Report: CIP:165.204.84.12;CTRY:US;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:SATLEXMB04.amd.com;PTR:atlvpn-bp.amd.com;CAT:NONE;SFS:(13230040)(1800799024)(36860700013)(7416014)(376014)(82310400026);DIR:OUT;SFP:1101; X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 22 Nov 2024 08:47:50.2417 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 6cd72160-10e8-4bde-8df3-08dd0ad258a6 X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d;Ip=[165.204.84.12];Helo=[SATLEXMB04.amd.com] X-MS-Exchange-CrossTenant-AuthSource: BN1PEPF00004687.namprd05.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: CY8PR12MB9036 Content-Type: text/plain; charset="utf-8" The live mode works similar to simple `perf stat` command, by profiling the target and printing results on the terminal as soon as the target finishes. Example usage: # perf sched stats -- sleep 10 Co-developed-by: Ravi Bangoria Signed-off-by: Ravi Bangoria Tested-by: James Clark Signed-off-by: Swapnil Sapkal --- tools/perf/builtin-sched.c | 87 +++++++++++++++++++++++++++++++++++++- 1 file changed, 86 insertions(+), 1 deletion(-) diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 58a4f6ce0448..004ad0952338 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -4342,6 +4342,91 @@ static int perf_sched__schedstat_report(struct perf_= sched *sched) return err; } =20 +static int process_synthesized_event_live(const struct perf_tool *tool __m= aybe_unused, + union perf_event *event, + struct perf_sample *sample __maybe_unused, + struct machine *machine __maybe_unused) +{ + return perf_sched__process_schedstat(NULL, event); +} + +static int perf_sched__schedstat_live(struct perf_sched *sched, + int argc, const char **argv) +{ + struct evlist *evlist; + struct target *target; + int reset =3D 0; + int err =3D 0; + + signal(SIGINT, sighandler); + signal(SIGCHLD, sighandler); + signal(SIGTERM, sighandler); + + evlist =3D evlist__new(); + if (!evlist) + return -ENOMEM; + + /* + * `perf sched schedstat` does not support workload profiling (-p pid) + * since /proc/schedstat file contains cpu specific data only. Hence, a + * profile target is either set of cpus or systemwide, never a process. + * Note that, although `-- ` is supported, profile data are + * still cpu/systemwide. + */ + target =3D zalloc(sizeof(struct target)); + if (cpu_list) + target->cpu_list =3D cpu_list; + else + target->system_wide =3D true; + + if (argc) { + err =3D evlist__prepare_workload(evlist, target, argv, false, NULL); + if (err) + goto out_target; + } + + if (cpu_list) { + user_requested_cpus =3D perf_cpu_map__new(cpu_list); + if (!user_requested_cpus) + goto out_target; + } + + err =3D perf_event__synthesize_schedstat(&(sched->tool), + process_synthesized_event_live, + user_requested_cpus); + if (err < 0) + goto out_target; + + err =3D enable_sched_schedstats(&reset); + if (err < 0) + goto out_target; + + if (argc) + evlist__start_workload(evlist); + + /* wait for signal */ + pause(); + + if (reset) { + err =3D disable_sched_schedstat(); + if (err < 0) + goto out_target; + } + + err =3D perf_event__synthesize_schedstat(&(sched->tool), + process_synthesized_event_live, + user_requested_cpus); + if (err) + goto out_target; + + setup_pager(); + show_schedstat_data(cpu_head); + free_schedstat(cpu_head); +out_target: + free(target); + return err; +} + static bool schedstat_events_exposed(void) { /* @@ -4663,7 +4748,7 @@ int cmd_sched(int argc, const char **argv) stats_usage, 0); return perf_sched__schedstat_report(&sched); } - usage_with_options(stats_usage, stats_options); + return perf_sched__schedstat_live(&sched, argc, argv); } else { usage_with_options(sched_usage, sched_options); } --=20 2.43.0 From nobody Fri Nov 29 18:47:08 2024 Received: from NAM11-DM6-obe.outbound.protection.outlook.com (mail-dm6nam11on2042.outbound.protection.outlook.com [40.107.223.42]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5DFD7176231; Fri, 22 Nov 2024 08:48:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.223.42 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732265302; cv=fail; b=uiU+pIvlc8/nu+lSWG94fUKjBLIeoJAw0KzJvNr3de9Jj9lZmT1XZ234t1OjggJOylve7DvrDMzX77qKFK5mWJqaBWELjpoVmAoj6e4wohLL8brXfXelP4i1Hz6j4d4ilo3z14FDhNfUuHyyePyNIG5NvdnZbb5Dwg5UBH3BrSM= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732265302; c=relaxed/simple; bh=VxEypGemKOEczqxt6cJg8viNuyfBrZnj1ZAPmuTMYsA=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=lQy4ORXkxoBc4KPzRutqAER9nZFV01VfdEwM+Yel1gO/eanzy5GbgGVexa3GNQg/q4MxJUkjUqXmKe4MH2SKiN/wPS7P0K0mjodg7lF7QseLGuFajjm+M5DW2lhcJz+cCuqq1kGxyfdRgG843ON3JHI85deZOgv2A91jxClDEYs= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amd.com; spf=fail smtp.mailfrom=amd.com; dkim=pass (1024-bit key) header.d=amd.com header.i=@amd.com header.b=ctTE/qp2; arc=fail smtp.client-ip=40.107.223.42 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amd.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=amd.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=amd.com header.i=@amd.com header.b="ctTE/qp2" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=UpM1Nws5ijWhPKF+q44cC7al5r598M7DumJAjswqmkVJGoCuNLMCblZTNpJzf12EkO1yPQMGYaHji0kcNVehnTZOKUVZBb/ibp4g2YwxNB2/qCpMlBhAfHEftANYo0Ai48tWv2/MEe8448HIcttx8fK9izLH43x7tHdHh+hsjgtV4L+L/yd/PBqDRWOg0C2SWrPG0wQiNMYYHIuMrIQA5Zf2tFmGHqzM0zMJXpApgM3oJ144n+14aY19WJEbSLnPmRVEePoHniuyfperDScQq5sswAAIPfCCQ3nVV/aXt0eUY3MVwS3JgRK5ptGZhWfBpB0B+QIelIXP3icyy7mbCA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=nsW8H/2p54qynLbu0UIh1gh0M+if7ZRs2yqKMdiHrH4=; b=cDSCoa/Q8yWUB8ZfFxH2LY/8u7N/uSqWFPPfid5MZljptzNLZfikibr13G4bcAkMeF28Bl8EB2wqgqc1EOP+Y4r4ADPv/Wng2denFe6noMaSOTPRJd5aMcUJJWVLDmtuFIvsUVr7VhR5m3sTp7hXGuCfZlJdu6WsCef4KgtWuTLa8HNNvEfcKuU1K6LcFQJc02r2ZxhDSFgJi7bKiMT3uOHO2Be5pOugurMzq52bqywgIYU6TsJBriE2kkeCUtG0w+xdqCbM6Rn5uqej88CKkdBFiD4E7Cba48TzKtBb0DiJPLSXMwvriV9tASedv2DPDpq1AECr9tE0GZDc0OS1uA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.12) smtp.rcpttodomain=infradead.org smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=nsW8H/2p54qynLbu0UIh1gh0M+if7ZRs2yqKMdiHrH4=; b=ctTE/qp2I0md7ckDCu7d82i59sF/8d77pmLGWfIEvGeHntMoXY/518a0wHoT29TjmuMgudjTsuXFvYXLgNsWlakG6TfbY0eC/M/qwx59UQES1hGvFScIhminDaCGNkxx2XClrUTyYEKBE/wwbnRGboXPQGhkCXEjRKgMa9Zzxao= Received: from BN8PR07CA0031.namprd07.prod.outlook.com (2603:10b6:408:ac::44) by SA1PR12MB9472.namprd12.prod.outlook.com (2603:10b6:806:45b::15) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.8158.22; Fri, 22 Nov 2024 08:48:13 +0000 Received: from BN1PEPF0000468E.namprd05.prod.outlook.com (2603:10b6:408:ac:cafe::e0) by BN8PR07CA0031.outlook.office365.com (2603:10b6:408:ac::44) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.8158.23 via Frontend Transport; Fri, 22 Nov 2024 08:48:13 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.12) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.12 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.12; helo=SATLEXMB04.amd.com; pr=C Received: from SATLEXMB04.amd.com (165.204.84.12) by BN1PEPF0000468E.mail.protection.outlook.com (10.167.243.139) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.8182.16 via Frontend Transport; Fri, 22 Nov 2024 08:48:12 +0000 Received: from tapi.amd.com (10.180.168.240) by SATLEXMB04.amd.com (10.181.40.145) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.39; Fri, 22 Nov 2024 02:48:04 -0600 From: Swapnil Sapkal To: , , , , , CC: , , , , , , , , , , , , , , , , , , , , , Swapnil Sapkal Subject: [PATCH v2 6/6] perf sched stats: Add support for diff subcommand Date: Fri, 22 Nov 2024 08:44:52 +0000 Message-ID: <20241122084452.1064968-7-swapnil.sapkal@amd.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20241122084452.1064968-1-swapnil.sapkal@amd.com> References: <20241122084452.1064968-1-swapnil.sapkal@amd.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: SATLEXMB03.amd.com (10.181.40.144) To SATLEXMB04.amd.com (10.181.40.145) X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: BN1PEPF0000468E:EE_|SA1PR12MB9472:EE_ X-MS-Office365-Filtering-Correlation-Id: 83684f61-af4b-4e6c-2431-08dd0ad26626 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|7416014|1800799024|82310400026|376014|36860700013; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?NCarFj13KmKjrTBDu8lYW+QBJKAW62UHxrzQGiKCkrhjHNzz+YdXpC66rdh+?= =?us-ascii?Q?jTzcI1UcAbHlcQeZHUT3M0/tDBqs3yRCsg2g81nFEiy0TMcK/m7E8LHoqDS+?= =?us-ascii?Q?ugzjXTLOrgm6nSYLrdHqaELDMFBTm2f/80R7TxMUA/xgl1suZYpHtYBEuqH+?= =?us-ascii?Q?xdbr1902tHUrFluyeUPooxuoTszQ234i9tmgnLgXT1gRsxCDfm54eIvPszKH?= =?us-ascii?Q?/+RYaGMNll04alml6JjF7QovcRa8cTbkrsFlgzrhDMTSs4jQUX6utXMSfp3V?= =?us-ascii?Q?y0jpufNVxIYvYDGp3NT7Yyi8WM1+/14Y91mjHN1uH1B18rm3kAc9FnXHmvKD?= =?us-ascii?Q?4zv/mDMoKusPbBrgenQPvibyGKCfMxax560oB8b3/6B/5lShO8nyYVtObPNe?= =?us-ascii?Q?VkOzkHc1WIRjnKM1RSvM0YJc8js6AkNqPTODxYOGtBnzrxkKW0402BePDvck?= =?us-ascii?Q?1wUeYV0AvI0kvyxE19f+VW6AGrUbpq5HZFGTacRgpMzgv6f2VUHX6E/q+1UN?= =?us-ascii?Q?PrL3/UUDGMUAibeHh9xTve+d2KqM2mK05tyeiSti/q45xU7Zo5lCRwR8Iq7L?= =?us-ascii?Q?cKTFZ1cqTC0tylrhO8co7R1OpCl50q5oksB6vRypQwmBMyl5nqBlTGilqBf+?= =?us-ascii?Q?hcK7DevcpO12yHv7QOxOdYYhFvupMocWW4kU+bbdCG6AWIE37Ehp58iXdWwT?= =?us-ascii?Q?otkh3KsGtWLbt8tT3zKtqr8ekwzUZ55wQgS8RyrYLr7nN3tHiJiDCapkinD6?= =?us-ascii?Q?bQx/oZoOSQt0D2U0uqvxkVYGk+eSASEpiqUMIqfgPKVOm7ZzhV3SuJupj6IB?= =?us-ascii?Q?H6AG5gSMN2Ak2ZemD6tAOzDmLn9EUkgvAxnsM8lIfMMwp1wfXNHoPQJ8+ZMB?= =?us-ascii?Q?+Ad8HJ8EXi7BJwBVOburjYdOp1yrr4s4gl4qTymr1e5osrIRk1oXAsZ8ayPn?= =?us-ascii?Q?zABhEE6hIVxWJHsMM3lBTgWFuACAWcP9wCRWpcg8nUISM0mUI03GE93+4Mqj?= =?us-ascii?Q?v3jhk0tIaEBynIkOlmnyR5P00px8TA51hePIRtvah+EjqlkfDS4ekgrsp8Nf?= =?us-ascii?Q?hsY4l26TJoxmjjORd4eLcuMGlLbTLdUyKwFVASOSuIR9bZkOFtLsBbasjRsS?= =?us-ascii?Q?qmKH46QG/5l/Enm0eTZMYe7XOIiCZD3dGV6EYjYWGJYDbx2SSLe0OEPXX5Hh?= =?us-ascii?Q?kuiZh5NYrgeZkRz9A0rN9YFhu1dFqXvW6UAOX6SqpjkEDzTdoTKsl/DsN8T5?= =?us-ascii?Q?tgGX8TzyXCcLGlOYjetztBsle+w51n957/ht6c8uDdQakz3e+5iuR3Jcuh8o?= =?us-ascii?Q?SCb2uDr39KQeJI3TXRh4zewGBRvx8WjkJU4A+jfe6o2uyv974pX62DTgkNXz?= =?us-ascii?Q?yk8BerLKbmg0AHgG5mvW+JAcIeBYPESXR5GQtNtJEfc7vdfTWQ=3D=3D?= X-Forefront-Antispam-Report: CIP:165.204.84.12;CTRY:US;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:SATLEXMB04.amd.com;PTR:atlvpn-bp.amd.com;CAT:NONE;SFS:(13230040)(7416014)(1800799024)(82310400026)(376014)(36860700013);DIR:OUT;SFP:1101; X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 22 Nov 2024 08:48:12.8882 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 83684f61-af4b-4e6c-2431-08dd0ad26626 X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d;Ip=[165.204.84.12];Helo=[SATLEXMB04.amd.com] X-MS-Exchange-CrossTenant-AuthSource: BN1PEPF0000468E.namprd05.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: SA1PR12MB9472 Content-Type: text/plain; charset="utf-8" `perf sched stats diff` subcommand will take two perf.data files as an input and it will print the diff between the two perf.data files. The default input to this subcommnd is perf.data.old and perf.data. Example usage: # perf sched stats diff sample1.data sample2.data Signed-off-by: Swapnil Sapkal --- tools/perf/builtin-sched.c | 270 +++++++++++++++++++++++++++++-------- 1 file changed, 217 insertions(+), 53 deletions(-) diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 004ad0952338..d9a3412ed749 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -3924,26 +3924,42 @@ static void print_separator(size_t pre_dash_cnt, co= nst char *s, size_t post_dash printf("\n"); } =20 -static inline void print_cpu_stats(struct perf_record_schedstat_cpu *cs) +#define PCT_CHNG(_x, _y) ((_x) ? ((double)((double)(_y) - (_x)) / (= _x)) * 100 : 0.0) +static inline void print_cpu_stats(struct perf_record_schedstat_cpu *cs1, + struct perf_record_schedstat_cpu *cs2) { - printf("%-65s %12s %12s\n", "DESC", "COUNT", "PCT_CHANGE"); + printf("%-65s ", "DESC"); + if (!cs2) + printf("%12s %12s", "COUNT", "PCT_CHANGE"); + else + printf("%12s %11s %12s %14s %10s", "COUNT1", "COUNT2", "PCT_CHANGE", + "PCT_CHANGE1", "PCT_CHANGE2"); + + printf("\n"); print_separator(100, "", 0); =20 #define CALC_PCT(_x, _y) ((_y) ? ((double)(_x) / (_y)) * 100 : 0.0) - -#define CPU_FIELD(_type, _name, _desc, _format, _is_pct, _pct_of, _ver) \ - do { \ - printf("%-65s: " _format, _desc, cs->_ver._name); \ - if (_is_pct) { \ - printf(" ( %8.2lf%% )", \ - CALC_PCT(cs->_ver._name, cs->_ver._pct_of)); \ - } \ - printf("\n"); \ +#define CPU_FIELD(_type, _name, _desc, _format, _is_pct, _pct_of, _ver) \ + do { \ + printf("%-65s: " _format, _desc, cs1->_ver._name); \ + if (!cs2) { \ + if (_is_pct) \ + printf(" ( %8.2lf%% )", \ + CALC_PCT(cs1->_ver._name, cs1->_ver._pct_of)); \ + } else { \ + printf("," _format " | %8.2lf%% |", cs2->_ver._name, \ + PCT_CHNG(cs1->_ver._name, cs2->_ver._name)); \ + if (_is_pct) \ + printf(" ( %8.2lf%%, %8.2lf%% )", \ + CALC_PCT(cs1->_ver._name, cs1->_ver._pct_of), \ + CALC_PCT(cs2->_ver._name, cs2->_ver._pct_of)); \ + } \ + printf("\n"); \ } while (0) =20 - if (cs->version =3D=3D 15) { + if (cs1->version =3D=3D 15) { #include - } else if (cs->version =3D=3D 16) { + } else if (cs1->version =3D=3D 16) { #include } =20 @@ -3951,10 +3967,17 @@ static inline void print_cpu_stats(struct perf_reco= rd_schedstat_cpu *cs) #undef CALC_PCT } =20 -static inline void print_domain_stats(struct perf_record_schedstat_domain = *ds, - __u64 jiffies) +static inline void print_domain_stats(struct perf_record_schedstat_domain = *ds1, + struct perf_record_schedstat_domain *ds2, + __u64 jiffies1, __u64 jiffies2) { - printf("%-65s %12s %14s\n", "DESC", "COUNT", "AVG_JIFFIES"); + printf("%-65s ", "DESC"); + if (!ds2) + printf("%12s %14s", "COUNT", "AVG_JIFFIES"); + else + printf("%12s %11s %12s %16s %12s", "COUNT1", "COUNT2", "PCT_CHANGE", + "AVG_JIFFIES1", "AVG_JIFFIES2"); + printf("\n"); =20 #define DOMAIN_CATEGORY(_desc) \ do { \ @@ -3968,25 +3991,52 @@ static inline void print_domain_stats(struct perf_r= ecord_schedstat_domain *ds, =20 #define DOMAIN_FIELD(_type, _name, _desc, _format, _is_jiffies, _ver) \ do { \ - printf("%-65s: " _format, _desc, ds->_ver._name); \ - if (_is_jiffies) { \ - printf(" $ %11.2Lf $", \ - CALC_AVG(jiffies, ds->_ver._name)); \ + printf("%-65s: " _format, _desc, ds1->_ver._name); \ + if (!ds2) { \ + if (_is_jiffies) \ + printf(" $ %11.2Lf $", \ + CALC_AVG(jiffies1, ds1->_ver._name)); \ + } else { \ + printf("," _format " | %8.2lf%% |", ds2->_ver._name, \ + PCT_CHNG(ds1->_ver._name, ds2->_ver._name)); \ + if (_is_jiffies) \ + printf(" $ %11.2Lf, %11.2Lf $", \ + CALC_AVG(jiffies1, ds1->_ver._name), \ + CALC_AVG(jiffies2, ds2->_ver._name)); \ } \ printf("\n"); \ } while (0) =20 #define DERIVED_CNT_FIELD(_desc, _format, _x, _y, _z, _ver) \ - printf("*%-64s: " _format "\n", _desc, \ - (ds->_ver._x) - (ds->_ver._y) - (ds->_ver._z)) + do { \ + __u32 t1 =3D ds1->_ver._x - ds1->_ver._y - ds1->_ver._z; \ + printf("*%-64s: " _format, _desc, t1); \ + if (ds2) { \ + __u32 t2 =3D ds2->_ver._x - ds2->_ver._y - ds2->_ver._z; \ + printf("," _format " | %8.2lf%% |", t2, \ + PCT_CHNG(t1, t2)); \ + } \ + printf("\n"); \ + } while (0) =20 #define DERIVED_AVG_FIELD(_desc, _format, _x, _y, _z, _w, _ver) \ - printf("*%-64s: " _format "\n", _desc, CALC_AVG(ds->_ver._w, \ - ((ds->_ver._x) - (ds->_ver._y) - (ds->_ver._z)))) + do { \ + __u32 t1 =3D ds1->_ver._x - ds1->_ver._y - ds1->_ver._z; \ + printf("*%-64s: " _format, _desc, \ + CALC_AVG(ds1->_ver._w, t1)); \ + if (ds2) { \ + __u32 t2 =3D ds2->_ver._x - ds2->_ver._y - ds2->_ver._z; \ + printf("," _format " | %8.2Lf%% |", \ + CALC_AVG(ds2->_ver._w, t2), \ + PCT_CHNG(CALC_AVG(ds1->_ver._w, t1), \ + CALC_AVG(ds2->_ver._w, t2))); \ + } \ + printf("\n"); \ + } while (0) =20 - if (ds->version =3D=3D 15) { + if (ds1->version =3D=3D 15) { #include - } else if (ds->version =3D=3D 16) { + } else if (ds1->version =3D=3D 16) { #include } =20 @@ -3996,6 +4046,7 @@ static inline void print_domain_stats(struct perf_rec= ord_schedstat_domain *ds, #undef CALC_AVG #undef DOMAIN_CATEGORY } +#undef PCT_CHNG =20 static void print_domain_cpu_list(struct perf_record_schedstat_domain *ds) { @@ -4148,12 +4199,12 @@ static void get_all_cpu_stats(struct schedstat_cpu = **cptr) } =20 /* FIXME: The code fails (segfaults) when one or ore cpus are offline. */ -static void show_schedstat_data(struct schedstat_cpu *cptr) +static void show_schedstat_data(struct schedstat_cpu *cptr1, struct scheds= tat_cpu *cptr2) { - struct perf_record_schedstat_domain *ds =3D NULL; - struct perf_record_schedstat_cpu *cs =3D NULL; - __u64 jiffies =3D cptr->cpu_data->timestamp; - struct schedstat_domain *dptr =3D NULL; + struct perf_record_schedstat_domain *ds1 =3D NULL, *ds2 =3D NULL; + struct perf_record_schedstat_cpu *cs1 =3D NULL, *cs2 =3D NULL; + struct schedstat_domain *dptr1 =3D NULL, *dptr2 =3D NULL; + __u64 jiffies1 =3D 0, jiffies2 =3D 0; bool is_summary =3D true; =20 printf("Columns description\n"); @@ -4164,50 +4215,82 @@ static void show_schedstat_data(struct schedstat_cp= u *cptr) printf("AVG_JIFFIES\t\t-> Avg time in jiffies between two consecutive occ= urrence of event\n"); =20 print_separator(100, "", 0); - printf("Time elapsed (in jiffies) = : %11llu\n", - jiffies); + printf("Time elapsed (in jiffies) = : "); + jiffies1 =3D cptr1->cpu_data->timestamp; + printf("%11llu", jiffies1); + if (cptr2) { + jiffies2 =3D cptr2->cpu_data->timestamp; + printf(",%11llu", jiffies2); + } + printf("\n"); + print_separator(100, "", 0); =20 - get_all_cpu_stats(&cptr); + get_all_cpu_stats(&cptr1); + if (cptr2) + get_all_cpu_stats(&cptr2); + + while (cptr1) { + cs1 =3D cptr1->cpu_data; + if (cptr2) { + cs2 =3D cptr2->cpu_data; + dptr2 =3D cptr2->domain_head; + } + + if (cs2 && cs1->cpu !=3D cs2->cpu) { + pr_err("Failed because matching cpus not found for diff\n"); + return; + } =20 - while (cptr) { - cs =3D cptr->cpu_data; printf("\n"); print_separator(100, "", 0); if (is_summary) printf("CPU \n"); else - printf("CPU %d\n", cs->cpu); + printf("CPU %d\n", cs1->cpu); =20 print_separator(100, "", 0); - print_cpu_stats(cs); + print_cpu_stats(cs1, cs2); print_separator(100, "", 0); =20 - dptr =3D cptr->domain_head; + dptr1 =3D cptr1->domain_head; + + while (dptr1) { + ds1 =3D dptr1->domain_data; + + if (dptr2) + ds2 =3D dptr2->domain_data; + + if (dptr2 && ds1->domain !=3D ds2->domain) { + pr_err("Failed because matching domain not found for diff\n"); + return; + } =20 - while (dptr) { - ds =3D dptr->domain_data; if (is_summary) - if (ds->name[0]) - printf("CPU , DOMAIN %s\n", ds->name); + if (ds1->name[0]) + printf("CPU , DOMAIN %s\n", ds1->name); else - printf("CPU , DOMAIN %d\n", ds->domain); + printf("CPU , DOMAIN %d\n", ds1->domain); else { - if (ds->name[0]) - printf("CPU %d, DOMAIN %s CPUS ", cs->cpu, ds->name); + if (ds1->name[0]) + printf("CPU %d, DOMAIN %s CPUS ", cs1->cpu, ds1->name); else - printf("CPU %d, DOMAIN %d CPUS ", cs->cpu, ds->domain); + printf("CPU %d, DOMAIN %d CPUS ", cs1->cpu, ds1->domain); =20 - print_domain_cpu_list(ds); + print_domain_cpu_list(ds1); } print_separator(100, "", 0); - print_domain_stats(ds, jiffies); + print_domain_stats(ds1, ds2, jiffies1, jiffies2); print_separator(100, "", 0); =20 - dptr =3D dptr->next; + dptr1 =3D dptr1->next; + if (dptr2) + dptr2 =3D dptr2->next; } is_summary =3D false; - cptr =3D cptr->next; + cptr1 =3D cptr1->next; + if (cptr2) + cptr2 =3D cptr2->next; } } =20 @@ -4336,12 +4419,88 @@ static int perf_sched__schedstat_report(struct perf= _sched *sched) perf_session__delete(session); if (!err) { setup_pager(); - show_schedstat_data(cpu_head); + show_schedstat_data(cpu_head, NULL); free_schedstat(cpu_head); } return err; } =20 +static int perf_sched__schedstat_diff(struct perf_sched *sched, + int argc, const char **argv) +{ + struct schedstat_cpu *cpu_head_ses0 =3D NULL, *cpu_head_ses1 =3D NULL; + struct perf_session *session[2]; + struct perf_data data[2]; + int ret, err; + static const char *defaults[] =3D { + "perf.data.old", + "perf.data", + }; + + if (argc) { + if (argc =3D=3D 1) + defaults[1] =3D argv[0]; + else if (argc =3D=3D 2) { + defaults[0] =3D argv[0]; + defaults[1] =3D argv[1]; + } else { + pr_err("perf sched stats diff is not supported with more than 2 files.\= n"); + goto out_ret; + } + } + + sched->tool.schedstat_cpu =3D perf_sched__process_schedstat; + sched->tool.schedstat_domain =3D perf_sched__process_schedstat; + + data[0].path =3D defaults[0]; + data[0].mode =3D PERF_DATA_MODE_READ; + session[0] =3D perf_session__new(&data[0], &sched->tool); + if (IS_ERR(session[0])) { + ret =3D PTR_ERR(session[0]); + pr_err("Failed to open %s\n", data[0].path); + goto out_delete_ses0; + } + + err =3D perf_session__process_events(session[0]); + if (err) + goto out_delete_ses0; + + cpu_head_ses0 =3D cpu_head; + after_workload_flag =3D false; + cpu_head =3D NULL; + + data[1].path =3D defaults[1]; + data[1].mode =3D PERF_DATA_MODE_READ; + session[1] =3D perf_session__new(&data[1], &sched->tool); + if (IS_ERR(session[1])) { + ret =3D PTR_ERR(session[1]); + pr_err("Failed to open %s\n", data[1].path); + goto out_delete_ses1; + } + + err =3D perf_session__process_events(session[1]); + if (err) + goto out_delete_ses1; + + cpu_head_ses1 =3D cpu_head; + after_workload_flag =3D false; + setup_pager(); + show_schedstat_data(cpu_head_ses0, cpu_head_ses1); + free_schedstat(cpu_head_ses0); + free_schedstat(cpu_head_ses1); + +out_delete_ses1: + if (!IS_ERR(session[1])) + perf_session__delete(session[1]); + +out_delete_ses0: + if (!IS_ERR(session[0])) + perf_session__delete(session[0]); + +out_ret: + return ret; +} + static int process_synthesized_event_live(const struct perf_tool *tool __m= aybe_unused, union perf_event *event, struct perf_sample *sample __maybe_unused, @@ -4420,7 +4579,7 @@ static int perf_sched__schedstat_live(struct perf_sch= ed *sched, goto out_target; =20 setup_pager(); - show_schedstat_data(cpu_head); + show_schedstat_data(cpu_head, NULL); free_schedstat(cpu_head); out_target: free(target); @@ -4747,6 +4906,11 @@ int cmd_sched(int argc, const char **argv) argc =3D parse_options(argc, argv, stats_options, stats_usage, 0); return perf_sched__schedstat_report(&sched); + } else if (argv[0] && !strcmp(argv[0], "diff")) { + if (argc) + argc =3D parse_options(argc, argv, stats_options, + stats_usage, 0); + return perf_sched__schedstat_diff(&sched, argc, argv); } return perf_sched__schedstat_live(&sched, argc, argv); } else { --=20 2.43.0