From patchwork Mon Nov 14 18:12:43 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Rogers X-Patchwork-Id: 19975 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:6687:0:0:0:0:0 with SMTP id l7csp2292182wru; Mon, 14 Nov 2022 10:19:40 -0800 (PST) X-Google-Smtp-Source: AA0mqf4RVFze3fqML6xegfJWAHyUHfhgRf5ZcRMVOngSl1ymrZtmQq3CKREZ47zTNuiKVecPXGwA X-Received: by 2002:a17:902:ce0b:b0:188:9542:515 with SMTP id k11-20020a170902ce0b00b0018895420515mr447446plg.102.1668449979833; Mon, 14 Nov 2022 10:19:39 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1668449979; cv=none; d=google.com; s=arc-20160816; b=BHhYciLJbjB/pk13psFmKICL1dpvZWVrzKGlBqqmvYQym8ekiRnQQmyLfwW5kpjF3c 1CltRRZKhHzi167apQ3Rx8uMk1RCHTwaUrdbB6NO8kDkgwTZuM3ls9vbUruUx7Xth1zk U4GX8LK67rGrDkPIDoaIsOKDl6LX0bjf7b1/c4awKgtq2OvCxyCMRGv8abM+xCHD4Qbi PkyGtgl0HvNuPFGAzQ57lFjHJoiCfSiJ27PEC7uqrk5SwN4H3WcaOCFI8FvaJu+3Frxc fHQcHUo89WutbEqf8LkqLVbXChK1vRMKhRzeka7tHfXplED6XYxYfwNAVvX2BbfyH88z PIxg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:from:subject:references:mime-version :message-id:in-reply-to:date:dkim-signature; bh=IWjziziyWCL9ANTddckpRcCDgTKHv1YzBEeGesj8X4M=; b=XPDL+J8PCGjiU1w1n3zL10c3QYxTq8vgB9dMozsnHYGkGE1rCEAitM6dmYIWM0ZqvH BiQHEGvUlGZFJtdmqS4xJGNobEvWwzb98g+S63y1JA/mob+kZ+hG1096NkMbOqwcOOjn vUFNIT3KfGjgXRmTpHXaw9r52/jQx2QVUVR5AS3VmehJgOWGLhNYsrvuwkmgrcIu5l3d /pNjkwrq0THE0EQOVu5Z3ET3tJK4jxj/BTZtQ5Gka7UWKFDw+MiRTp2V1alnSbYATDlV /O3OAWTdTfg6yernwlU3kUSH+wxeEL7zvVK/6YRdFOnw7C2ZqClE1qYNUwtagesIwwaf 7X+w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20210112 header.b=Z1vW6YtB; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id ft10-20020a17090b0f8a00b00213945884d5si9877356pjb.126.2022.11.14.10.19.18; Mon, 14 Nov 2022 10:19:39 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20210112 header.b=Z1vW6YtB; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237710AbiKNSNq (ORCPT + 99 others); Mon, 14 Nov 2022 13:13:46 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41690 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238290AbiKNSNY (ORCPT ); Mon, 14 Nov 2022 13:13:24 -0500 Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EDE6B286D2 for ; Mon, 14 Nov 2022 10:13:17 -0800 (PST) Received: by mail-yb1-xb49.google.com with SMTP id z125-20020a25c983000000b006dc905e6ccfso10995300ybf.1 for ; Mon, 14 Nov 2022 10:13:17 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:references:mime-version:message-id:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=IWjziziyWCL9ANTddckpRcCDgTKHv1YzBEeGesj8X4M=; b=Z1vW6YtBcmpz1uRXy9oUq83oCkscQDF4giyMlLAQnSqvcegJHwh6TZx1ptKlHFWfOL jKmvOd42xB4ddU6IaOmWcD5nh4uwLZAU7AEk9ev5yXDzw1FlAlmd+HEBIENpBYaavm3M Y+NBiKeW13mbxd6E3CWao4LE2D9+UOc1IHXBcrra20VTJBnFJj4CJHT8wn/ecpjx6T4l OiN6Rtd7JAzfe4FHhjFT2nLKh9173k/1W/OBC0o7GTL9GHJv+sTrmfAkKnrYm5xR6NKt eREIO3mxZPXOZJVsNEuZDLN64PxvLVENYHCdgMAtAdAr/zfoqGpglm0MXTg58fpcb3tH AfHw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:references:mime-version:message-id:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=IWjziziyWCL9ANTddckpRcCDgTKHv1YzBEeGesj8X4M=; b=pKAZxumDfHbiZf0OCiEfz0YZTsUK2Q3z8fUqht32wmtMR63X5/6P0wd5EhEXVPdn1F 72DT/+aKzaum8YN3NlTj3AEH2iw8FW5IpEY5S2UYtLjMakaPJDm1VAdo1LzOb6aDXF1/ Z+a23+NzWtZnfWQnkKI6usvGjzimlWmlzd+UVWUaMo8eKj1O3jtl3deeCAvrXSiNoAzS cFjEKGH50C4lyoflGp/C7uFRWoLHGI5rs086/wZ16jKSytrjA9vwL3eV9/oy+8wFw3tE VkTC3XdwhpgcLqvolFuSJUThsunCCabAby+XKpngVgMAp3hiGY0hzkrlpq5UbfKq6Ns+ XOmw== X-Gm-Message-State: ANoB5pmlvbAor0Gr83S0nRNFIHS/RS9Ov/Nwx9V4ZSPNb+QgLm8he4x2 97gNLD588cqByRhiE/P3eYgppIsStfU3 X-Received: from irogers.svl.corp.google.com ([2620:15c:2d4:203:553:438f:b86a:87f]) (user=irogers job=sendgmr) by 2002:a0d:d442:0:b0:377:e4ac:6c3b with SMTP id w63-20020a0dd442000000b00377e4ac6c3bmr13752108ywd.285.1668449597176; Mon, 14 Nov 2022 10:13:17 -0800 (PST) Date: Mon, 14 Nov 2022 10:12:43 -0800 In-Reply-To: <20221114181251.2683871-1-irogers@google.com> Message-Id: <20221114181251.2683871-2-irogers@google.com> Mime-Version: 1.0 References: <20221114181251.2683871-1-irogers@google.com> X-Mailer: git-send-email 2.38.1.431.g37b22c650d-goog Subject: [PATCH v2 1/9] perf pmu: Add documentation From: Ian Rogers To: Weilin Wang , Perry Taylor , Caleb Biggers , Leo Yan , Adrian Hunter , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Mark Rutland , Alexander Shishkin , Jiri Olsa , Namhyung Kim , Sandipan Das , Kajol Jain , Zhengjun Xing , Kan Liang , Ravi Bangoria , Xin Gao , Rob Herring , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org Cc: Stephane Eranian , Ian Rogers X-Spam-Status: No, score=-9.6 required=5.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1749496606038376180?= X-GMAIL-MSGID: =?utf-8?q?1749496606038376180?= Add documentation to struct perf_pmu and the associated structs of perf_pmu_alias and perf_pmu_format. Signed-off-by: Ian Rogers --- tools/perf/util/pmu.c | 16 ++++++ tools/perf/util/pmu.h | 123 +++++++++++++++++++++++++++++++++++++++--- 2 files changed, 133 insertions(+), 6 deletions(-) diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 6a86e6af0903..8396504855cc 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -31,10 +31,26 @@ struct perf_pmu perf_pmu__fake; +/** + * struct perf_pmu_format - Values from a format file read from + * /devices/cpu/format/ held in struct perf_pmu. + * + * For example, the contents of /devices/cpu/format/event may be + * "config:0-7" and will be represented here as name="event", + * value=PERF_PMU_FORMAT_VALUE_CONFIG and bits 0 to 7 will be set. + */ struct perf_pmu_format { + /** @name: The modifier/file name. */ char *name; + /** + * @value : Which config value the format relates to. Supported values + * are from PERF_PMU_FORMAT_VALUE_CONFIG to + * PERF_PMU_FORMAT_VALUE_CONFIG_END. + */ int value; + /** @bits: Which config bits are set by this format value. */ DECLARE_BITMAP(bits, PERF_PMU_FORMAT_BITS); + /** @list: Element on list within struct perf_pmu. */ struct list_head list; }; diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h index 68e15c38ae71..ce718bab3018 100644 --- a/tools/perf/util/pmu.h +++ b/tools/perf/util/pmu.h @@ -33,31 +33,103 @@ struct perf_pmu_caps { struct list_head list; }; +/** + * struct perf_pmu - hi + */ struct perf_pmu { + /** @name: The name of the PMU such as "cpu". */ char *name; + /** + * @alias_name: Optional alternate name for the PMU determined in + * architecture specific code. + */ char *alias_name; + /** + * @id: Optional PMU identifier read from + * /bus/event_source/devices//identifier. + */ char *id; + /** + * @type: Perf event attributed type value, read from + * /bus/event_source/devices//type. + */ __u32 type; + /** + * @selectable: Can the PMU name be selected as if it were an event? + */ bool selectable; + /** + * @is_uncore: Is the PMU not within the CPU core? Determined by the + * presence of /bus/event_source/devices//cpumask. + */ bool is_uncore; + /** @is_hybrid: Is the PMU name either cpu_core or cpu_atom. */ bool is_hybrid; + /** + * @auxtrace: Are events auxiliary events? Determined in architecture + * specific code. + */ bool auxtrace; + /** + * @max_precise: Number of levels of :ppp precision supported by the + * PMU, read from + * /bus/event_source/devices//caps/max_precise. + */ int max_precise; + /** + * @default_config: Optional default perf_event_attr determined in + * architecture specific code. + */ struct perf_event_attr *default_config; + /** + * @cpus: Empty or the contents of either of: + * /bus/event_source/devices//cpumask. + * /bus/event_source/devices//cpus. + */ struct perf_cpu_map *cpus; - struct list_head format; /* HEAD struct perf_pmu_format -> list */ - struct list_head aliases; /* HEAD struct perf_pmu_alias -> list */ + /** + * @format: Holds the contents of files read from + * /bus/event_source/devices//format/. The contents specify + * which event parameter changes what config, config1 or config2 bits. + */ + struct list_head format; + /** + * @aliases: List of struct perf_pmu_alias. Each alias corresponds to an + * event read from /bus/event_source/devices//events/ or + * from json events in pmu-events.c. + */ + struct list_head aliases; + /** @caps_initialized: Has the list caps been initialized? */ bool caps_initialized; + /** @nr_caps: The length of the list caps. */ u32 nr_caps; - struct list_head caps; /* HEAD struct perf_pmu_caps -> list */ - struct list_head list; /* ELEM */ + /** + * @caps: Holds the contents of files read from + * /bus/event_source/devices//caps/. + * + * The contents are pairs of the filename with the value of its + * contents, for example, max_precise (see above) may have a value of 3. + */ + struct list_head caps; + /** @list: Element on pmus list in pmu.c. */ + struct list_head list; + /** @hybrid_list: Element on perf_pmu__hybrid_pmus. */ struct list_head hybrid_list; + /** + * @missing_features: Features to inhibit when events on this PMU are + * opened. + */ struct { + /** + * @exclude_guest: Disables perf_event_attr exclude_guest and + * exclude_host. + */ bool exclude_guest; } missing_features; }; +/** @perf_pmu__fake: A special global PMU used for testing. */ extern struct perf_pmu perf_pmu__fake; struct perf_pmu_info { @@ -71,21 +143,60 @@ struct perf_pmu_info { #define UNIT_MAX_LEN 31 /* max length for event unit name */ +/** + * struct perf_pmu_alias - An event either read from sysfs or builtin in + * pmu-events.c, created by parsing the pmu-events json files. + */ struct perf_pmu_alias { + /** @name: Name of the event like "mem-loads". */ char *name; + /** @desc: Optional short description of the event. */ char *desc; + /** @long_desc: Optional long description. */ char *long_desc; + /** + * @topic: Optional topic such as cache or pipeline, particularly for + * json events. + */ char *topic; + /** + * @str: Comma separated parameter list like + * "event=0xcd,umask=0x1,ldlat=0x3". + */ char *str; - struct list_head terms; /* HEAD struct parse_events_term -> list */ - struct list_head list; /* ELEM */ + /** @terms: Owned list of the original parsed parameters. */ + struct list_head terms; + /** @list: List element of struct perf_pmu aliases. */ + struct list_head list; + /** @unit: Units for the event, such as bytes or cache lines. */ char unit[UNIT_MAX_LEN+1]; + /** @scale: Value to scale read counter values by. */ double scale; + /** + * @per_pkg: Does the file + * /bus/event_source/devices//events/.per-pkg or + * equivalent json value exist and have the value 1. + */ bool per_pkg; + /** + * @snapshot: Does the file + * /bus/event_source/devices//events/.snapshot + * exist and have the value 1. + */ bool snapshot; + /** + * @deprecated: Is the event hidden and so not shown in perf list by + * default. + */ bool deprecated; + /** + * @metric_expr: A metric expression associated with an event. Doing + * this makes little sense due to scale and unit applying to both. + */ char *metric_expr; + /** @metric_name: A name for the metric. unit applying to both. */ char *metric_name; + /** @pmu_name: The name copied from struct perf_pmu. */ char *pmu_name; }; From patchwork Mon Nov 14 18:12:44 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Rogers X-Patchwork-Id: 19982 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:6687:0:0:0:0:0 with SMTP id l7csp2292861wru; Mon, 14 Nov 2022 10:21:02 -0800 (PST) X-Google-Smtp-Source: AA0mqf6KOe8TWvixAjPTo1YUi1+QkJUhxOybZlRnGBzK6cttP6LSU1jF2gImw0zI3roXEeAGt6Mc X-Received: by 2002:a17:906:1cd0:b0:7a1:6786:4566 with SMTP id i16-20020a1709061cd000b007a167864566mr11111473ejh.433.1668450062170; Mon, 14 Nov 2022 10:21:02 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1668450062; cv=none; d=google.com; s=arc-20160816; b=uVjDcxewUVJEH6NO74i0kB70MnTX+tM82a+3PsQGhyNg28/QoIXuogDw/H11B2He2F mORe8mOkEeLfpiFSLHSWND01sd8GEiFvkp3NsJsITvrIBfE7l53ILMFtNTEgdvs0VwnY 59trfnw8d42tDFSllLAfBQ+GaIw5N83iesJtFiDSTtED8d7avB6J1qK74Go8YL+Acj3K zqw+R1nDaSr4z0w+xSAw3xpKTZLe+MzdI9Fjvz0odvE0lQ9UOnR00NPhPNJShZQBJx9s Wc8mtwPIANBk2+646d4HwknFxMmavobNScB22WoLPWbklLQel70YybTXWPf7rX8iwVsJ Nfhg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:from:subject:references:mime-version :message-id:in-reply-to:date:dkim-signature; bh=Se2me6lbjg4dS4DNtZbL4NOOrQgzrO1DuLy7bKVPgtE=; b=n4DJW0BMQ3l7h1v2Kd88scUtzzwbbFpiQtXlHv3KyTws+Hngl568TYY0nk9GyeoeGK MnJtWOCSQexafOQe299+wifSn2ceE77zJqNpxaVEBXfKNbqnSbFqLf+GYdpkpQ8gCEp1 rkPTbCtzO8GNWlaaPI8yQDq88f2wx9FhClFwJIEdGUMKWw95ct7tFmqYKyB2vC+1XNsT zmozgfdA5GWo7VuD1llOHChQTAxBGk2I0kQYsd9nKwDiImkImlrGiyVQcPvPHZicv/YN C+3AbpRtcbaHSppxok7Zsw8WZhOfIfctgw8fKIL4J8POIu7p6luzYS8H9Bc7PeXnKWPC av+w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20210112 header.b=Udp1PTHK; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id bc10-20020a056402204a00b00457f5aa9dc6si8675346edb.528.2022.11.14.10.20.36; Mon, 14 Nov 2022 10:21:02 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20210112 header.b=Udp1PTHK; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238299AbiKNSNx (ORCPT + 99 others); Mon, 14 Nov 2022 13:13:53 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41632 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238354AbiKNSNc (ORCPT ); Mon, 14 Nov 2022 13:13:32 -0500 Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C2B3617A98 for ; Mon, 14 Nov 2022 10:13:29 -0800 (PST) Received: by mail-yb1-xb49.google.com with SMTP id 204-20020a250fd5000000b006ccc0e91098so11129384ybp.13 for ; Mon, 14 Nov 2022 10:13:29 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:references:mime-version:message-id:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=Se2me6lbjg4dS4DNtZbL4NOOrQgzrO1DuLy7bKVPgtE=; b=Udp1PTHKxUUEwOqdgvMUBoS44uHDNucmnfPc1wYaH/Eaj3JkdwS1KeKqeAZOzlQrsX xBTR9whWAVfnvkCVljv/bx91QT8WQafusEqzylUtudDl/GEJfrd1i1liZVtH2vko+2H5 bt14BPmXoGjUfQV+rmPJb6f6rY6hfl2pfEz+gPNYzA6vBH8xk2kSlMV1KMpjVvx3w3xM CSm1/uSgSEJ6Is8EtJq8s9kT/lnMYVYnsJXysDAQaeu7a6c+4MUZ34saLOmYhKO+lb7k G9bJ0JXt9fyiSu2MfOhjnx63lMQi92IweinE5pmYDVc31iZR6FLDggptsMx3AW4BVjmd itMw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:references:mime-version:message-id:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=Se2me6lbjg4dS4DNtZbL4NOOrQgzrO1DuLy7bKVPgtE=; b=xlq1/gbwEYtA2zZog+aEru4c5A/8ns8jDEiJyBWB1yukMWOEJKbgTZoZW5uL4rhmVp IBuoMqt1zPsaplc9Go5SztutlZxQy8xG2S7WSIwNyGfsvfefE5j0jxE6czV0qZyBbyos v5FirBAKJxHSpF4I1ZP2v82Q/6Jd4O0wl0vLWTWPMwu2SIAAP61ipy5EPwBjIPsk/OZF 7b64RaHse0wgHonQ0teilzOPnirZNCbU1BouXjQ2ZOuGoh11QP0eVDEgx3tpV9h81ipE 8ceS0DO7EKyzl1WQb1NNbYuON/XW+ScRzLgLcxNSS0celS2VaNUXul1Pa5zmzQJ29FfC Q3pg== X-Gm-Message-State: ACrzQf13d5qHEp6rFAWUwoLxFoRGNATU3Q8v8lXk1USAGBm3EdDoaWok QY0bzlh0ASsg+TFRp/AvXp0viQdsKCoZ X-Received: from irogers.svl.corp.google.com ([2620:15c:2d4:203:553:438f:b86a:87f]) (user=irogers job=sendgmr) by 2002:a81:9214:0:b0:36c:7b94:aa57 with SMTP id j20-20020a819214000000b0036c7b94aa57mr63231927ywg.221.1668449608551; Mon, 14 Nov 2022 10:13:28 -0800 (PST) Date: Mon, 14 Nov 2022 10:12:44 -0800 In-Reply-To: <20221114181251.2683871-1-irogers@google.com> Message-Id: <20221114181251.2683871-3-irogers@google.com> Mime-Version: 1.0 References: <20221114181251.2683871-1-irogers@google.com> X-Mailer: git-send-email 2.38.1.431.g37b22c650d-goog Subject: [PATCH v2 2/9] tools lib api fs tracing_path: Add scandir alphasort From: Ian Rogers To: Weilin Wang , Perry Taylor , Caleb Biggers , Leo Yan , Adrian Hunter , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Mark Rutland , Alexander Shishkin , Jiri Olsa , Namhyung Kim , Sandipan Das , Kajol Jain , Zhengjun Xing , Kan Liang , Ravi Bangoria , Xin Gao , Rob Herring , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org Cc: Stephane Eranian , Ian Rogers X-Spam-Status: No, score=-9.6 required=5.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1749496692324617682?= X-GMAIL-MSGID: =?utf-8?q?1749496692324617682?= tracing_events__opendir allows iteration over files in /tracing/events but with an arbitrary sort order. Add a scandir alternative where the results are alphabetically sorted. Signed-off-by: Ian Rogers --- tools/lib/api/fs/tracing_path.c | 16 ++++++++++++++++ tools/lib/api/fs/tracing_path.h | 1 + 2 files changed, 17 insertions(+) diff --git a/tools/lib/api/fs/tracing_path.c b/tools/lib/api/fs/tracing_path.c index 5afb11b30fca..b8e457c841ab 100644 --- a/tools/lib/api/fs/tracing_path.c +++ b/tools/lib/api/fs/tracing_path.c @@ -113,6 +113,22 @@ DIR *tracing_events__opendir(void) return dir; } +int tracing_events__scandir_alphasort(struct dirent ***namelist) +{ + char *path = get_tracing_file("events"); + int ret; + + if (!path) { + *namelist = NULL; + return 0; + } + + ret = scandir(path, namelist, NULL, alphasort); + put_events_file(path); + + return ret; +} + int tracing_path__strerror_open_tp(int err, char *buf, size_t size, const char *sys, const char *name) { diff --git a/tools/lib/api/fs/tracing_path.h b/tools/lib/api/fs/tracing_path.h index a19136b086dc..fc6347c11deb 100644 --- a/tools/lib/api/fs/tracing_path.h +++ b/tools/lib/api/fs/tracing_path.h @@ -6,6 +6,7 @@ #include DIR *tracing_events__opendir(void); +int tracing_events__scandir_alphasort(struct dirent ***namelist); void tracing_path_set(const char *mountpoint); const char *tracing_path_mount(void); From patchwork Mon Nov 14 18:12:45 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Rogers X-Patchwork-Id: 19970 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:6687:0:0:0:0:0 with SMTP id l7csp2291831wru; Mon, 14 Nov 2022 10:19:01 -0800 (PST) X-Google-Smtp-Source: AA0mqf6kdKaaWLRozlRBkkWiK0f4MXePvKoBuGXkTsj/3MS3kfyLnraXIBhJuQwbITuRWQjJDhuJ X-Received: by 2002:a17:906:1416:b0:78d:e869:f328 with SMTP id p22-20020a170906141600b0078de869f328mr10547740ejc.696.1668449941255; Mon, 14 Nov 2022 10:19:01 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1668449941; cv=none; d=google.com; s=arc-20160816; b=mIuA3JgP1FiKtooGtZ6znWcP5vg22WYXkGxP6mknf9lugIx5I6wwt62l4rMptZ8moS IRoClbzQ91gXRQJeFRIRanrYSM+KJiVQgz1sWCuUFG7RxANIDKkK3EFsA/FEw5mS3HJj tOP62dxxOUfCyLSX6vcF7vjjqjAe8aX1LDHzOC/novHR2OEL/jgnOfKTFnEjlQe9SUrw FiRnSE5vNsTHAft1jhVNwZHQHwNs1+pkomBy/QexbNwMTGetE8xDiMFKLKL0VvF1qAfm ARqTbb9EnGP6Z2irLjUpDcIKV7MWFzpT5KBD/egNivCvU5lRtkAA5zEL1UZBDy3p0HVY yF5A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:from:subject:references:mime-version :message-id:in-reply-to:date:dkim-signature; bh=FAjkIdGz/j9kJ1xDL5dYREJTueL8AT+RXQYxwRGY3ak=; b=uMVn06bKOfvEPa+boKI6fyWi1jecikJ0hxq2yXDhNDMwJfOM8ypv8sOxOQZ5kSJnYP Lxps9itA8mZ/w/k12GXHrRKBjhkGIKiv90WV06A++aBrRevxECwPIxmlHBMwQKdkLc8b iiU9ISgK4qXGgjzJWiYWntUcO5EzvSIGDNenp3NooAZKMWf7U+RJW/3Sm4Dvo1Y5Anuf yLGex1SjyN+DGoxNY2fg58A6WiLXNnD/Z/H3ALpAisuNKGkgxg+lZrpLI0gweB0oDMfv XxlS9B563r4n9o+jPe4dC8kbg1GCxMLA7RmolZfTOqpp3bDxrZrLzHV29nm87XjYVbq8 EWYw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20210112 header.b=DAt71PWr; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id a9-20020a50e709000000b0045c7c7b95easi2389733edn.73.2022.11.14.10.18.31; Mon, 14 Nov 2022 10:19:01 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20210112 header.b=DAt71PWr; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238331AbiKNSN5 (ORCPT + 99 others); Mon, 14 Nov 2022 13:13:57 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42280 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238387AbiKNSNk (ORCPT ); Mon, 14 Nov 2022 13:13:40 -0500 Received: from mail-pf1-x449.google.com (mail-pf1-x449.google.com [IPv6:2607:f8b0:4864:20::449]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 692AF23BC2 for ; Mon, 14 Nov 2022 10:13:38 -0800 (PST) Received: by mail-pf1-x449.google.com with SMTP id e8-20020a056a00162800b0056e953c5088so6432336pfc.2 for ; Mon, 14 Nov 2022 10:13:38 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:references:mime-version:message-id:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=FAjkIdGz/j9kJ1xDL5dYREJTueL8AT+RXQYxwRGY3ak=; b=DAt71PWrjoITyAdCRE+Lj7mQUuYa3hVc6OS4Titnc+6zDLr3m+IeSlbkwTB6xk6oAd AU8DRW0kfELM38hqTfMjyQNKlY+Dh0CKMtbk4hcok0lcIPw/QATk/mSHf91CbDRs8LzN 05NmLbPTsgxnyzdeNLFGxmNsbHYmt23xWbDfE8JADZ7xCzr1vbbZJvQismQ10uBBliui f5uPz/rLFtmacHATZY8F028mZc4jctekE3UW+E8OpgRaKLJiqA3KSUJjss3XJ2ly9Sv7 b1DcSaDPmU7fPr2aZrVhVVFpBLVwI3bzM1TuY3iI1Pvn+sqF4U3YlbiFZhh7OzavwCud RjoQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:references:mime-version:message-id:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=FAjkIdGz/j9kJ1xDL5dYREJTueL8AT+RXQYxwRGY3ak=; b=zlSx6cM8NOrFtvo8pimwOYn4F0KIpw5p+kwiRxYDRUisAs0GPX2kXyn06WK0lK7eKl iZp861XKvlzF24eGD3gpH9EpZ3VLx40DY8Gpj09zK3SX4msu2MMZ52uScu1DIAItI5jT +GGGPxwiOvHNxb9VBMBXwQEMD6YSkfqhvIWtq3pWjBd68HfHOx3t1MaVaFQ6+QW2COEF hh+p8CTeZDi7XSnDQJpnWTD5xKD1ER0K1IlwfrCz3ryg3ay1PC5zRaG/+u97DQxFjFll zC8Exqn2kTcLYv5tklalBKiKz1S7b6zu7x+2lOPFhDJeMEy1qo1ulXVuWV8Ovc3C0qeF /U0Q== X-Gm-Message-State: ANoB5pm3MMCP5wlm85NJqZ3xYZ2HV13Z7WazyzC7z5RVMr3i3bLHjfGR rMdDsEiUnwf8dE+ehYfPp9fUmRwsnZ8v X-Received: from irogers.svl.corp.google.com ([2620:15c:2d4:203:553:438f:b86a:87f]) (user=irogers job=sendgmr) by 2002:a62:f245:0:b0:56c:3696:ad5f with SMTP id y5-20020a62f245000000b0056c3696ad5fmr14860112pfl.30.1668449617898; Mon, 14 Nov 2022 10:13:37 -0800 (PST) Date: Mon, 14 Nov 2022 10:12:45 -0800 In-Reply-To: <20221114181251.2683871-1-irogers@google.com> Message-Id: <20221114181251.2683871-4-irogers@google.com> Mime-Version: 1.0 References: <20221114181251.2683871-1-irogers@google.com> X-Mailer: git-send-email 2.38.1.431.g37b22c650d-goog Subject: [PATCH v2 3/9] perf tracepoint: Sort events in iterator From: Ian Rogers To: Weilin Wang , Perry Taylor , Caleb Biggers , Leo Yan , Adrian Hunter , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Mark Rutland , Alexander Shishkin , Jiri Olsa , Namhyung Kim , Sandipan Das , Kajol Jain , Zhengjun Xing , Kan Liang , Ravi Bangoria , Xin Gao , Rob Herring , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org Cc: Stephane Eranian , Ian Rogers X-Spam-Status: No, score=-9.6 required=5.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1749496565760209498?= X-GMAIL-MSGID: =?utf-8?q?1749496565760209498?= In print_tracepoint_events use tracing_events__scandir_alphasort and scandir alphasort so that the subsystem and events are sorted and don't need a secondary qsort. Locally this results in the following change: ... ext4:ext4_zero_range [Tracepoint event] - fib6:fib6_table_lookup [Tracepoint event] fib:fib_table_lookup [Tracepoint event] + fib6:fib6_table_lookup [Tracepoint event] filelock:break_lease_block [Tracepoint event] ... ie fib6 now is after fib and not before it. This is more consistent with how numbers are more generally sorted, such as: ... syscalls:sys_enter_renameat [Tracepoint event] syscalls:sys_enter_renameat2 [Tracepoint event] ... and so an improvement over the qsort approach. Signed-off-by: Ian Rogers --- tools/perf/util/print-events.c | 108 +++++++++++---------------------- 1 file changed, 37 insertions(+), 71 deletions(-) diff --git a/tools/perf/util/print-events.c b/tools/perf/util/print-events.c index c4d5d87fae2f..fefc025bc259 100644 --- a/tools/perf/util/print-events.c +++ b/tools/perf/util/print-events.c @@ -66,26 +66,21 @@ static int cmp_string(const void *a, const void *b) void print_tracepoint_events(const char *subsys_glob, const char *event_glob, bool name_only) { - DIR *sys_dir, *evt_dir; - struct dirent *sys_dirent, *evt_dirent; - char evt_path[MAXPATHLEN]; - char *dir_path; - char **evt_list = NULL; - unsigned int evt_i = 0, evt_num = 0; - bool evt_num_known = false; - -restart: - sys_dir = tracing_events__opendir(); - if (!sys_dir) - return; - - if (evt_num_known) { - evt_list = zalloc(sizeof(char *) * evt_num); - if (!evt_list) - goto out_close_sys_dir; - } + struct dirent **sys_namelist = NULL; + bool printed = false; + int sys_items = tracing_events__scandir_alphasort(&sys_namelist); + + for (int i = 0; i < sys_items; i++) { + struct dirent *sys_dirent = sys_namelist[i]; + struct dirent **evt_namelist = NULL; + char *dir_path; + int evt_items; + + if (sys_dirent->d_type != DT_DIR || + !strcmp(sys_dirent->d_name, ".") || + !strcmp(sys_dirent->d_name, "..")) + continue; - for_each_subsystem(sys_dir, sys_dirent) { if (subsys_glob != NULL && !strglobmatch(sys_dirent->d_name, subsys_glob)) continue; @@ -93,69 +88,40 @@ void print_tracepoint_events(const char *subsys_glob, dir_path = get_events_file(sys_dirent->d_name); if (!dir_path) continue; - evt_dir = opendir(dir_path); - if (!evt_dir) - goto next; - for_each_event(dir_path, evt_dir, evt_dirent) { - if (event_glob != NULL && - !strglobmatch(evt_dirent->d_name, event_glob)) + evt_items = scandir(dir_path, &evt_namelist, NULL, alphasort); + for (int j = 0; j < evt_items; j++) { + struct dirent *evt_dirent = evt_namelist[j]; + char evt_path[MAXPATHLEN]; + + if (evt_dirent->d_type != DT_DIR || + !strcmp(evt_dirent->d_name, ".") || + !strcmp(evt_dirent->d_name, "..")) continue; - if (!evt_num_known) { - evt_num++; + if (tp_event_has_id(dir_path, evt_dirent) != 0) + continue; + + if (event_glob != NULL && + !strglobmatch(evt_dirent->d_name, event_glob)) continue; - } snprintf(evt_path, MAXPATHLEN, "%s:%s", sys_dirent->d_name, evt_dirent->d_name); - - evt_list[evt_i] = strdup(evt_path); - if (evt_list[evt_i] == NULL) { - put_events_file(dir_path); - goto out_close_evt_dir; + if (name_only) + printf("%s ", evt_path); + else { + printf(" %-50s [%s]\n", evt_path, + event_type_descriptors[PERF_TYPE_TRACEPOINT]); } - evt_i++; + printed = true; } - closedir(evt_dir); -next: - put_events_file(dir_path); + free(dir_path); + free(evt_namelist); } - closedir(sys_dir); - - if (!evt_num_known) { - evt_num_known = true; - goto restart; - } - qsort(evt_list, evt_num, sizeof(char *), cmp_string); - evt_i = 0; - while (evt_i < evt_num) { - if (name_only) { - printf("%s ", evt_list[evt_i++]); - continue; - } - printf(" %-50s [%s]\n", evt_list[evt_i++], - event_type_descriptors[PERF_TYPE_TRACEPOINT]); - } - if (evt_num && pager_in_use()) + free(sys_namelist); + if (printed && pager_in_use()) printf("\n"); - -out_free: - evt_num = evt_i; - for (evt_i = 0; evt_i < evt_num; evt_i++) - zfree(&evt_list[evt_i]); - zfree(&evt_list); - return; - -out_close_evt_dir: - closedir(evt_dir); -out_close_sys_dir: - closedir(sys_dir); - - printf("FATAL: not enough memory to print %s\n", - event_type_descriptors[PERF_TYPE_TRACEPOINT]); - if (evt_list) - goto out_free; } void print_sdt_events(const char *subsys_glob, const char *event_glob, From patchwork Mon Nov 14 18:12:46 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Rogers X-Patchwork-Id: 19971 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:6687:0:0:0:0:0 with SMTP id l7csp2291931wru; Mon, 14 Nov 2022 10:19:13 -0800 (PST) X-Google-Smtp-Source: AA0mqf5dtKqVVY4o4fFtBs2HhSlIPb6aZlQ4NX3SuO/FyXNI2ZVkrnoWLtZ+jNA4jVDt/izfflB0 X-Received: by 2002:a17:902:7488:b0:188:a40b:47cd with SMTP id h8-20020a170902748800b00188a40b47cdmr464790pll.72.1668449952851; Mon, 14 Nov 2022 10:19:12 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1668449952; cv=none; d=google.com; s=arc-20160816; b=mXyE0XF6WLSXp1PhqlQ6HWmEP0Toxaq0TTeeg5obX6iDgIFHXSZsAtIx25ko9+4jkB A0LbRQvFIY2tDEZESnboO6WLR0lKfWNkFsV9PrzQhOl1gg6SmnbEHahPZ+L5+OwpYy0w XLVQXWGS76SbrnGfy40/YiPvlBnAkKLlu/CJb30+C/b7fvOebR5SFXfV5CRBb5DJCu8I dRDna1u3IFmivM1K9Acckd09DytGUbioejj7P0NLM9n3kzWbfNUBL16Adl1jkPBFwL1R 4K2ZYBeOZ5gaJmecScTh1ukQpCO2UVgrQByZSeVeUwL3th/yHvZHnav0SWUmSDVxJmY8 YsMA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:from:subject:references:mime-version :message-id:in-reply-to:date:dkim-signature; bh=9hnG/tZfedfD7kZp3YcxBNSD1DkQV4xbq+gqS8LIB1s=; b=H9qYXuigCNzZ4qTS4qY8PsNXv5Mj41xgCrjYYuJzrHOQ94Our8Pwk20V3LzWTBCJu5 0cZt9Qc5TTLMdc9GcbVvLRZWV+Wv9EUcj8WAQKCsGWOj781aT5NCLubMkCVMNu5gC3WF Vf3dCGwD7h+dYSg7Kf9sruKHaHIdQx1uln248xbmZoNuyGA/m+dnHfb1sTEGmh0ooNOm TjWJhJP7qEvBR9AmYxc1Svs005IaLETdyMM2nJr6c7wVqEoJ6JW/8s5tKlCjN+mzFiGW AmdLh/uF24qdA3vmpWkFqeBy6jpFZPaQv4Y+ii0bdII57V0QudUO1hX7JAqmdkI8kN+N 0u2w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20210112 header.b=HyrY1Y+X; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id f15-20020a056a0022cf00b0056b972a8cfasi10742122pfj.121.2022.11.14.10.18.58; Mon, 14 Nov 2022 10:19:12 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20210112 header.b=HyrY1Y+X; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238330AbiKNSOY (ORCPT + 99 others); Mon, 14 Nov 2022 13:14:24 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42598 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238304AbiKNSNz (ORCPT ); Mon, 14 Nov 2022 13:13:55 -0500 Received: from mail-yw1-x114a.google.com (mail-yw1-x114a.google.com [IPv6:2607:f8b0:4864:20::114a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C76F923BC7 for ; Mon, 14 Nov 2022 10:13:47 -0800 (PST) Received: by mail-yw1-x114a.google.com with SMTP id 00721157ae682-373569200ceso111806947b3.4 for ; Mon, 14 Nov 2022 10:13:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:references:mime-version:message-id:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=9hnG/tZfedfD7kZp3YcxBNSD1DkQV4xbq+gqS8LIB1s=; b=HyrY1Y+Xx86vg03nHkyU3umeFhhUR4CLNDRYP4KrojHNuXKY/D4P9BxYVco/N9GbPL i6W2IQXpl1rwPi9h1dwBOC+QVQSVuosYPrnObBug5QzAq63R8rOfaZJOqbpYa09K+L+u fj/dOq1eSB7ZP+1EgFIjL1UjD1cwNnkGgakJ9UT1lFFj/m1+gz5MmO6MnaK1Q2WuxnHi XxizBmJuqGs11LBseX8QO7ZfuLjfONuDot9BaZFDvf1KwRoRHrEWFu5WvHbhCYME1JTr xCxPSJflHJVoYcKh4DxOq2dHbk79l5yv97EF4BErWnq8BQqyNqXuHkMc5Ad+OPwKYh0D YAnw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:references:mime-version:message-id:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=9hnG/tZfedfD7kZp3YcxBNSD1DkQV4xbq+gqS8LIB1s=; b=3pyqtO8GgBkRDJ74KN6NMt4lJBPK9bU1EhudVh1Q2CH5x8kqPXI3aO7vEi/Bor2M6i 2FqayHL4xKmNtIMt9vgiCWAmHcBAcO2ZFcpQ+DCi1MMfB0zrzNyM9QE6WEP/nxvDhU2M AgLcpKM7SlqtCZoMB8W9dYDfoW4rFn07CB8dIuh6ff2vn6UWUWuu/RSO7p1KXf7CIwtN M22oBnJDz9QQjfkDGwvQ1m7gRvUzanMWSS1sPHRutzyi7k1688WDELAmZs/CMNTVtyJk uwImtupsQBROXjnyPg+D5yaHhPQAvxO7gLeKrJiU+id4fOKyEAwtPewE4BFWiC85TAvU JZiA== X-Gm-Message-State: ACrzQf0KwjBMIwS4bxOmXDXw7fsv3IP3XrJVxACP/VWHfEEy7s1SEqmX NT0MjR6XBPduSJVr4N5LxT04we1b9xaW X-Received: from irogers.svl.corp.google.com ([2620:15c:2d4:203:553:438f:b86a:87f]) (user=irogers job=sendgmr) by 2002:a0d:f246:0:b0:373:5992:dd23 with SMTP id b67-20020a0df246000000b003735992dd23mr43961109ywf.36.1668449626510; Mon, 14 Nov 2022 10:13:46 -0800 (PST) Date: Mon, 14 Nov 2022 10:12:46 -0800 In-Reply-To: <20221114181251.2683871-1-irogers@google.com> Message-Id: <20221114181251.2683871-5-irogers@google.com> Mime-Version: 1.0 References: <20221114181251.2683871-1-irogers@google.com> X-Mailer: git-send-email 2.38.1.431.g37b22c650d-goog Subject: [PATCH v2 4/9] perf list: Generalize limiting to a PMU name From: Ian Rogers To: Weilin Wang , Perry Taylor , Caleb Biggers , Leo Yan , Adrian Hunter , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Mark Rutland , Alexander Shishkin , Jiri Olsa , Namhyung Kim , Sandipan Das , Kajol Jain , Zhengjun Xing , Kan Liang , Ravi Bangoria , Xin Gao , Rob Herring , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org Cc: Stephane Eranian , Ian Rogers X-Spam-Status: No, score=-9.6 required=5.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1749496578005965692?= X-GMAIL-MSGID: =?utf-8?q?1749496578005965692?= Deprecate the --cputype option and add a --unit option where '--unit cpu_atom' behaves like '--cputype atom'. The --unit option can be used with arbitrary PMUs, for example: ``` $ perf list --unit msr pmu List of pre-defined events (to be used in -e or -M): msr/aperf/ [Kernel PMU event] msr/cpu_thermal_margin/ [Kernel PMU event] msr/mperf/ [Kernel PMU event] msr/pperf/ [Kernel PMU event] msr/smi/ [Kernel PMU event] msr/tsc/ [Kernel PMU event] ``` Signed-off-by: Ian Rogers --- tools/perf/Documentation/perf-list.txt | 6 +++--- tools/perf/builtin-list.c | 18 ++++++++++++------ tools/perf/util/metricgroup.c | 3 ++- tools/perf/util/pmu.c | 4 +--- 4 files changed, 18 insertions(+), 13 deletions(-) diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt index 57384a97c04f..44a819af573d 100644 --- a/tools/perf/Documentation/perf-list.txt +++ b/tools/perf/Documentation/perf-list.txt @@ -39,9 +39,9 @@ any extra expressions computed by perf stat. --deprecated:: Print deprecated events. By default the deprecated events are hidden. ---cputype:: -Print events applying cpu with this type for hybrid platform -(e.g. --cputype core or --cputype atom) +--unit:: +Print PMU events and metrics limited to the specific PMU name. +(e.g. --unit cpu, --unit msr, --unit cpu_core, --unit cpu_atom) [[EVENT_MODIFIERS]] EVENT MODIFIERS diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c index 58e1ec1654ef..cc84ced6da26 100644 --- a/tools/perf/builtin-list.c +++ b/tools/perf/builtin-list.c @@ -21,7 +21,6 @@ static bool desc_flag = true; static bool details_flag; -static const char *hybrid_type; int cmd_list(int argc, const char **argv) { @@ -30,6 +29,8 @@ int cmd_list(int argc, const char **argv) bool long_desc_flag = false; bool deprecated = false; char *pmu_name = NULL; + const char *hybrid_name = NULL; + const char *unit_name = NULL; struct option list_options[] = { OPT_BOOLEAN(0, "raw-dump", &raw_dump, "Dump raw events"), OPT_BOOLEAN('d', "desc", &desc_flag, @@ -40,9 +41,10 @@ int cmd_list(int argc, const char **argv) "Print information on the perf event names and expressions used internally by events."), OPT_BOOLEAN(0, "deprecated", &deprecated, "Print deprecated events."), - OPT_STRING(0, "cputype", &hybrid_type, "hybrid cpu type", - "Print events applying cpu with this type for hybrid platform " - "(e.g. core or atom)"), + OPT_STRING(0, "cputype", &hybrid_name, "hybrid cpu type", + "Limit PMU or metric printing to the given hybrid PMU (e.g. core or atom)."), + OPT_STRING(0, "unit", &unit_name, "PMU name", + "Limit PMU or metric printing to the specified PMU."), OPT_INCR(0, "debug", &verbose, "Enable debugging output"), OPT_END() @@ -53,6 +55,8 @@ int cmd_list(int argc, const char **argv) }; set_option_flag(list_options, 0, "raw-dump", PARSE_OPT_HIDDEN); + /* Hide hybrid flag for the more generic 'unit' flag. */ + set_option_flag(list_options, 0, "cputype", PARSE_OPT_HIDDEN); argc = parse_options(argc, argv, list_options, list_usage, PARSE_OPT_STOP_AT_NON_OPTION); @@ -62,8 +66,10 @@ int cmd_list(int argc, const char **argv) if (!raw_dump && pager_in_use()) printf("\nList of pre-defined events (to be used in -e or -M):\n\n"); - if (hybrid_type) { - pmu_name = perf_pmu__hybrid_type_to_pmu(hybrid_type); + if (unit_name) + pmu_name = strdup(unit_name); + else if (hybrid_name) { + pmu_name = perf_pmu__hybrid_type_to_pmu(hybrid_name); if (!pmu_name) pr_warning("WARNING: hybrid cputype is not supported!\n"); } diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index 4c98ac29ee13..1943fed9b6d9 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -556,11 +556,12 @@ static int metricgroup__print_callback(const struct pmu_event *pe, void *vdata) { struct metricgroup_print_data *data = vdata; + const char *pmu = pe->pmu ?: "cpu"; if (!pe->metric_expr) return 0; - if (data->pmu_name && perf_pmu__is_hybrid(pe->pmu) && strcmp(data->pmu_name, pe->pmu)) + if (data->pmu_name && strcmp(data->pmu_name, pmu)) return 0; return metricgroup__print_pmu_event(pe, data->metricgroups, data->filter, diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 8396504855cc..779839525437 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -1696,10 +1696,8 @@ void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag, pmu = NULL; j = 0; while ((pmu = perf_pmu__scan(pmu)) != NULL) { - if (pmu_name && perf_pmu__is_hybrid(pmu->name) && - strcmp(pmu_name, pmu->name)) { + if (pmu_name && pmu->name && strcmp(pmu_name, pmu->name)) continue; - } list_for_each_entry(alias, &pmu->aliases, list) { char *name = alias->desc ? alias->name : From patchwork Mon Nov 14 18:12:47 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Rogers X-Patchwork-Id: 19973 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:6687:0:0:0:0:0 with SMTP id l7csp2292157wru; Mon, 14 Nov 2022 10:19:37 -0800 (PST) X-Google-Smtp-Source: AA0mqf4jodE0Y0M9t8Ad86QRt5LpB3Kur9YxUC8r68laHCEqGATjNk/ffdDWVP7rNJ5NRw/svVHP X-Received: by 2002:a63:4622:0:b0:46f:9c0c:809c with SMTP id t34-20020a634622000000b0046f9c0c809cmr12713646pga.523.1668449976795; Mon, 14 Nov 2022 10:19:36 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1668449976; cv=none; d=google.com; s=arc-20160816; b=rvU0ODlOJPy8Ac8/hpSSewq6R7fv0gc4Me+Bsh9PQZ9KJ+aJHFS2VrdMTshDaY5tGq SSilwCLgXTWMeiXiwzfVR+110GCKvCC0T1ROmv163rzBH1SyQTvn5jqPFP9U0ulAba/0 YwH0IkRFwWmV1OLe3VuAoqJarQ8oOrYesg8+J/n4ljJmBB9c3d4IOSpVXj0TuqlbsLTB hiYN1J00UeZq1Xus97sya297Bum+8aur/lslPuJ2iqOrLHNxZM2RORoHVl6MP1m0xIV/ oq/F6i0sHlmDWS3kRfYEA5d8wz9Iks9ZHkcC7upWbzrEm3mglWuwOpQvp/n/40EwOZ37 E5CA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:from:subject:references:mime-version :message-id:in-reply-to:date:dkim-signature; bh=05I6atWVl+qVT8yMUMb7x3GwtdO61HeIYnH9Cn+25jQ=; b=G2nclVKaqlezJiwSn/udm+Lk3E996bMFlHIaETfZTVkjDnS/eHyrfz/d2Eyv4Zm4DI jhTcQOI+dfojfr5tHGdhr8at/yiiKqAQFVvO/GacGXwEeweaXflhOR+YjCIclXVyWd6h M4X7tSjVXidHqm1/rxvsQ90FuihTNA5/lVBqoIuQseoOGlXh6ufhhTSuyHjuZJGfaEZb uSwMRqw2goH75h92PEVuTVnY14j2TusyFEoDJbxt3sXdEdtuSr1ZYL7o9ItvvZqBfCXl PcQVtWGcs+YTBbT0o/+SAS08VIGkVjWLCzKXdfkxweOpNONW4/OeCFWiOVLt2521p35f 1ORA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20210112 header.b="HD0dZKX/"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id p2-20020a170902c70200b001855797d813si8798112plp.397.2022.11.14.10.19.06; Mon, 14 Nov 2022 10:19:36 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20210112 header.b="HD0dZKX/"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238354AbiKNSOw (ORCPT + 99 others); Mon, 14 Nov 2022 13:14:52 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42496 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238344AbiKNSOM (ORCPT ); Mon, 14 Nov 2022 13:14:12 -0500 Received: from mail-pf1-x44a.google.com (mail-pf1-x44a.google.com [IPv6:2607:f8b0:4864:20::44a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D431E2CDD0 for ; Mon, 14 Nov 2022 10:13:55 -0800 (PST) Received: by mail-pf1-x44a.google.com with SMTP id cw4-20020a056a00450400b00561ec04e77aso6468738pfb.12 for ; Mon, 14 Nov 2022 10:13:55 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:references:mime-version:message-id:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=05I6atWVl+qVT8yMUMb7x3GwtdO61HeIYnH9Cn+25jQ=; b=HD0dZKX/zpcmKiR0/x22oJSMUWSoBaIB/60Hp+/dGOhcoJl1//+/82X2dORp3TfECX Yq32Gm3pFb/YIlZblDyDYMdQRpMA0nberC8wLLbABDgD9IrhWATnxMgaJtKc3moLicQ7 0iiRwC65/hY6+Oz4heaY3gBkAori2q87o14+ZScxaxs8KRgB4aqZMo9gjHOvmCEIbRqK 6A/2soRIV8ICOzF3tT+/EZhEX/KflLrZSJfPxiUSreLCXORYg7YmLIiYMNc0RvwkGvxw ca3jSWJpDTFN7a9S2r//MNSoV3AqD3N9wfTBc/S3ZCkc2weI+0idGXBB9xICp5rwD2VT WyhQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:references:mime-version:message-id:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=05I6atWVl+qVT8yMUMb7x3GwtdO61HeIYnH9Cn+25jQ=; b=boCaEbFSqoFmr8GtLsXZEwmXBxWRinosoITNr2Ve4s+pCb9FU6Zui6VYo5YAu59nCG Nis574pTu9rgA+UO5FQU8fgZKxFnVfu85YWv6SWrBtvQfYJnxfOsuBmIthry+KIXN/4l npQGG+gPuqOJp9Mgjos266T+vkmLThF+ZqAMAAN8gVpdQdWbpGrbwlZNdn0DRtO1W6CG xcfgj9XJAB96Vo7Nkimw3ynAok9037K0h6oQLICIK05TTU5Ytrs5GeT4uOI8IApj3rzY dMA1/hxKJXCKC5eIjYQU8bbk1wEM0wJBPOyeVX0kcr83AGUl6U3jWK/KNtcNGrUAQNXe OSGQ== X-Gm-Message-State: ANoB5pmsQHtWCmYfDiVyLzPPvmR8xlPUKu/C3fzIoUxAoWRi6GPRoRJl cDVNophvFymlva8EGG0RNF6hoFbW6lFb X-Received: from irogers.svl.corp.google.com ([2620:15c:2d4:203:553:438f:b86a:87f]) (user=irogers job=sendgmr) by 2002:a62:7b53:0:b0:56b:83d3:a22 with SMTP id w80-20020a627b53000000b0056b83d30a22mr14955364pfc.32.1668449635264; Mon, 14 Nov 2022 10:13:55 -0800 (PST) Date: Mon, 14 Nov 2022 10:12:47 -0800 In-Reply-To: <20221114181251.2683871-1-irogers@google.com> Message-Id: <20221114181251.2683871-6-irogers@google.com> Mime-Version: 1.0 References: <20221114181251.2683871-1-irogers@google.com> X-Mailer: git-send-email 2.38.1.431.g37b22c650d-goog Subject: [PATCH v2 5/9] perf list: Simplify cache event printing From: Ian Rogers To: Weilin Wang , Perry Taylor , Caleb Biggers , Leo Yan , Adrian Hunter , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Mark Rutland , Alexander Shishkin , Jiri Olsa , Namhyung Kim , Sandipan Das , Kajol Jain , Zhengjun Xing , Kan Liang , Ravi Bangoria , Xin Gao , Rob Herring , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org Cc: Stephane Eranian , Ian Rogers X-Spam-Status: No, score=-9.6 required=5.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1749496602610166024?= X-GMAIL-MSGID: =?utf-8?q?1749496602610166024?= The current code computes an array of cache names then sorts and prints them. Use a strlist to create a list of names that is sorted. Keep the hybrid names, it is unclear how to generalize it, but drop the computation of evt_pmus that is never used. Signed-off-by: Ian Rogers --- tools/perf/util/print-events.c | 132 +++++++-------------------------- 1 file changed, 27 insertions(+), 105 deletions(-) diff --git a/tools/perf/util/print-events.c b/tools/perf/util/print-events.c index fefc025bc259..ff7793944246 100644 --- a/tools/perf/util/print-events.c +++ b/tools/perf/util/print-events.c @@ -206,137 +206,59 @@ void print_sdt_events(const char *subsys_glob, const char *event_glob, int print_hwcache_events(const char *event_glob, bool name_only) { - unsigned int type, op, i, evt_i = 0, evt_num = 0, npmus = 0; - char name[64], new_name[128]; - char **evt_list = NULL, **evt_pmus = NULL; - bool evt_num_known = false; - struct perf_pmu *pmu = NULL; - - if (perf_pmu__has_hybrid()) { - npmus = perf_pmu__hybrid_pmu_num(); - evt_pmus = zalloc(sizeof(char *) * npmus); - if (!evt_pmus) - goto out_enomem; - } + struct strlist *evt_name_list = strlist__new(NULL, NULL); + struct str_node *nd; -restart: - if (evt_num_known) { - evt_list = zalloc(sizeof(char *) * evt_num); - if (!evt_list) - goto out_enomem; + if (!evt_name_list) { + pr_debug("Failed to allocate new strlist for hwcache events\n"); + return -ENOMEM; } - - for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) { - for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) { + for (int type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) { + for (int op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) { /* skip invalid cache type */ if (!evsel__is_cache_op_valid(type, op)) continue; - for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) { - unsigned int hybrid_supported = 0, j; - bool supported; + for (int i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) { + struct perf_pmu *pmu = NULL; + char name[64]; __evsel__hw_cache_type_op_res_name(type, op, i, name, sizeof(name)); if (event_glob != NULL && !strglobmatch(name, event_glob)) continue; if (!perf_pmu__has_hybrid()) { - if (!is_event_supported(PERF_TYPE_HW_CACHE, - type | (op << 8) | (i << 16))) { - continue; - } - } else { - perf_pmu__for_each_hybrid_pmu(pmu) { - if (!evt_num_known) { - evt_num++; - continue; - } - - supported = is_event_supported( - PERF_TYPE_HW_CACHE, - type | (op << 8) | (i << 16) | - ((__u64)pmu->type << PERF_PMU_TYPE_SHIFT)); - if (supported) { - snprintf(new_name, sizeof(new_name), - "%s/%s/", pmu->name, name); - evt_pmus[hybrid_supported] = - strdup(new_name); - hybrid_supported++; - } - } - - if (hybrid_supported == 0) - continue; - } - - if (!evt_num_known) { - evt_num++; + if (is_event_supported(PERF_TYPE_HW_CACHE, + type | (op << 8) | (i << 16))) + strlist__add(evt_name_list, name); continue; } - - if ((hybrid_supported == 0) || - (hybrid_supported == npmus)) { - evt_list[evt_i] = strdup(name); - if (npmus > 0) { - for (j = 0; j < npmus; j++) - zfree(&evt_pmus[j]); - } - } else { - for (j = 0; j < hybrid_supported; j++) { - evt_list[evt_i++] = evt_pmus[j]; - evt_pmus[j] = NULL; + perf_pmu__for_each_hybrid_pmu(pmu) { + if (is_event_supported(PERF_TYPE_HW_CACHE, + type | (op << 8) | (i << 16) | + ((__u64)pmu->type << PERF_PMU_TYPE_SHIFT))) { + char new_name[128]; + snprintf(new_name, sizeof(new_name), + "%s/%s/", pmu->name, name); + strlist__add(evt_name_list, new_name); } - continue; } - - if (evt_list[evt_i] == NULL) - goto out_enomem; - evt_i++; } } } - if (!evt_num_known) { - evt_num_known = true; - goto restart; - } - - for (evt_i = 0; evt_i < evt_num; evt_i++) { - if (!evt_list[evt_i]) - break; - } - - evt_num = evt_i; - qsort(evt_list, evt_num, sizeof(char *), cmp_string); - evt_i = 0; - while (evt_i < evt_num) { + strlist__for_each_entry(nd, evt_name_list) { if (name_only) { - printf("%s ", evt_list[evt_i++]); + printf("%s ", nd->s); continue; } - printf(" %-50s [%s]\n", evt_list[evt_i++], - event_type_descriptors[PERF_TYPE_HW_CACHE]); + printf(" %-50s [%s]\n", nd->s, event_type_descriptors[PERF_TYPE_HW_CACHE]); } - if (evt_num && pager_in_use()) + if (!strlist__empty(evt_name_list) && pager_in_use()) printf("\n"); -out_free: - evt_num = evt_i; - for (evt_i = 0; evt_i < evt_num; evt_i++) - zfree(&evt_list[evt_i]); - zfree(&evt_list); - - for (evt_i = 0; evt_i < npmus; evt_i++) - zfree(&evt_pmus[evt_i]); - zfree(&evt_pmus); - return evt_num; - -out_enomem: - printf("FATAL: not enough memory to print %s\n", - event_type_descriptors[PERF_TYPE_HW_CACHE]); - if (evt_list) - goto out_free; - return evt_num; + strlist__delete(evt_name_list); + return 0; } static void print_tool_event(const struct event_symbol *syms, const char *event_glob, From patchwork Mon Nov 14 18:12:48 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Rogers X-Patchwork-Id: 19974 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:6687:0:0:0:0:0 with SMTP id l7csp2292158wru; Mon, 14 Nov 2022 10:19:37 -0800 (PST) X-Google-Smtp-Source: AA0mqf6A3CG+bGxZvu3xRVgJxkavvAmPbQRYc4txY3aE5VqOFlqwX1tIOUZmn7SMH4ONAuYrKppj X-Received: by 2002:a17:90a:9a8b:b0:20c:c0f:7c69 with SMTP id e11-20020a17090a9a8b00b0020c0c0f7c69mr14550779pjp.196.1668449976863; Mon, 14 Nov 2022 10:19:36 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1668449976; cv=none; d=google.com; s=arc-20160816; b=qF/ayJbIiJyzaLGnG2LUP46xCzdzegyWyIaY0hoN45wNQY955jZQK/SaL55hQA2a6I xKKiEGpCfUjphHZVJlELv23ecf+mxMLGiOgvwfaRkfsDyFh/RiYtC2axwFWoQcXI6Azr 5YccKsgCz0piYVBbJCfwdYqxbgV+FucBppSsxsN4n5UzWbwP5ghje+mmFtB+KKugPNy+ +TgjH7d1lA+00czg8VPWb6yVtj1KmWGoS6JftF9S1Phii+hFrNz16FgUue9ufB4wH17N oqRcJ5Y5IdMg+1Obps/RC1YaZwDTtoOE6sh0NGGoeu5yPzBKHvV58NeChh0xeLBfryv8 oE5A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:from:subject:references:mime-version :message-id:in-reply-to:date:dkim-signature; bh=HIf5Y9gptGCDfzfHbnNjnA19mp6qRpBDngBttcXhem0=; b=UDkZozlY2L/B2JZGnKd1rD3I5E0jApwbkxqBhUBokwd2VeSC8kiPoyUUvXk2OTq/PY ovjkEmntX6gCxPhuXWxNvdqcQuLWKWzUICCkwVF/eXd7gpUBiFxzUALJPBvw14dczen+ uqXtqJKs5g+JlVWuB0MnUgN1L3h/Rm5p8TQ3KQi59nUfgBKqwAq4Tb86sfV2HYhYwsAv +G7KGamYBKAiEBWjOYwt2KtK5nJ40ilSctXei+qaRe9/54QTmRfKQHGkq8ZlYXyfnQ3R OEA9IVzrWqMgDWr0oXQswkjljQoduba4q/Nd0iiD2D0aBo0hhwhgaNfjUUJytl9zxSyN pYvQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20210112 header.b=ms3hkkK9; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id x24-20020a63db58000000b004625c2dbc5csi9418643pgi.718.2022.11.14.10.19.11; Mon, 14 Nov 2022 10:19:36 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20210112 header.b=ms3hkkK9; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237122AbiKNSO7 (ORCPT + 99 others); Mon, 14 Nov 2022 13:14:59 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42634 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238309AbiKNSOR (ORCPT ); Mon, 14 Nov 2022 13:14:17 -0500 Received: from mail-pg1-x54a.google.com (mail-pg1-x54a.google.com [IPv6:2607:f8b0:4864:20::54a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B06642CE26 for ; Mon, 14 Nov 2022 10:14:03 -0800 (PST) Received: by mail-pg1-x54a.google.com with SMTP id h19-20020a63e153000000b00434dfee8dbaso6177723pgk.18 for ; Mon, 14 Nov 2022 10:14:03 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:references:mime-version:message-id:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=HIf5Y9gptGCDfzfHbnNjnA19mp6qRpBDngBttcXhem0=; b=ms3hkkK95AjV+ioKEVEzkclXhnmqtE13D4LhndsjTMdIUDHQQXNB8UOSp2+OFTFRFK ViC7tHBGKBTJNv7KryjTbINFQI5fSv39fXjaAD5iZypgA1bxtBjBkHjH2M85yh6ALa2h 1r1lslPr4brLR45T0lMkmoq02U6kvVZouc8YCevM+z0aijHfPQjqgUTaoPOiWwSwRN9c 89CwAlZ0BJ7onnoeLlDSwM5RNnDzvUBjgPlZTeANeCa6chbAE3MnVd+zdOGqb3wd27t1 N9EDnlvusDE3+Mge/bfb7XJjnpg5n905IcTGtJ2BUzKJFtPCYmXEhsLg0SgWUwtRxGB7 /p3Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:references:mime-version:message-id:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=HIf5Y9gptGCDfzfHbnNjnA19mp6qRpBDngBttcXhem0=; b=GNmLFJTFoP1skRE50L5cBSh8ilVrKPjft7Ysz6MddfyYAEhO5h1YtHWSyA7aQV2pYK XGKPvs4waoC4b7CeikXeApOfqwr3zZlQ552wVn0KntNaHxNeTykldlZ/fVnXyrySDmXc 21JxfRVdedY1zfq5l/fIKD+6gU6oJXD9UYiiXPPO/opcBJF/nK3R5ug0cWKrg9XMgNLD MOu77wdeH/RhiM1f7C5uu5ouvfQUvONjS7yj1nCdc4ZXAV+56lALwf6a+LlTUmBs4kL1 3aKfOcPlotRje2jd1DRZsBF2ds09Uq7RT4+LVX0HRHm1Mb/UGAFAUgGgsFzmX5WXbx3t LLDg== X-Gm-Message-State: ANoB5pkH6kv+9F1Jr1L8wLF0eX9EB4bpj9ZJDwOTWyVMqDIXn/0IPIP5 /V8WoaNgWVEW81INJAeBHMlG4POWacAu X-Received: from irogers.svl.corp.google.com ([2620:15c:2d4:203:553:438f:b86a:87f]) (user=irogers job=sendgmr) by 2002:a62:b402:0:b0:56e:8f96:6b2e with SMTP id h2-20020a62b402000000b0056e8f966b2emr14862845pfn.18.1668449643208; Mon, 14 Nov 2022 10:14:03 -0800 (PST) Date: Mon, 14 Nov 2022 10:12:48 -0800 In-Reply-To: <20221114181251.2683871-1-irogers@google.com> Message-Id: <20221114181251.2683871-7-irogers@google.com> Mime-Version: 1.0 References: <20221114181251.2683871-1-irogers@google.com> X-Mailer: git-send-email 2.38.1.431.g37b22c650d-goog Subject: [PATCH v2 6/9] perf list: Simplify symbol event printing From: Ian Rogers To: Weilin Wang , Perry Taylor , Caleb Biggers , Leo Yan , Adrian Hunter , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Mark Rutland , Alexander Shishkin , Jiri Olsa , Namhyung Kim , Sandipan Das , Kajol Jain , Zhengjun Xing , Kan Liang , Ravi Bangoria , Xin Gao , Rob Herring , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org Cc: Stephane Eranian , Ian Rogers X-Spam-Status: No, score=-9.6 required=5.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS,USER_IN_DEF_DKIM_WL autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1749496603279081356?= X-GMAIL-MSGID: =?utf-8?q?1749496603279081356?= The current code computes an array of symbol names then sorts and prints them. Use a strlist to create a list of names that is sorted and then print it. Signed-off-by: Ian Rogers --- tools/perf/util/print-events.c | 79 +++++++++------------------------- 1 file changed, 21 insertions(+), 58 deletions(-) diff --git a/tools/perf/util/print-events.c b/tools/perf/util/print-events.c index ff7793944246..d53dba033597 100644 --- a/tools/perf/util/print-events.c +++ b/tools/perf/util/print-events.c @@ -52,14 +52,6 @@ static const struct event_symbol event_symbols_tool[PERF_TOOL_MAX] = { }, }; -static int cmp_string(const void *a, const void *b) -{ - const char * const *as = a; - const char * const *bs = b; - - return strcmp(*as, *bs); -} - /* * Print the events from /tracing/events */ @@ -298,77 +290,48 @@ void print_symbol_events(const char *event_glob, unsigned int type, struct event_symbol *syms, unsigned int max, bool name_only) { - unsigned int i, evt_i = 0, evt_num = 0; - char name[MAX_NAME_LEN]; - char **evt_list = NULL; - bool evt_num_known = false; - -restart: - if (evt_num_known) { - evt_list = zalloc(sizeof(char *) * evt_num); - if (!evt_list) - goto out_enomem; - syms -= max; - } + struct strlist *evt_name_list = strlist__new(NULL, NULL); + struct str_node *nd; - for (i = 0; i < max; i++, syms++) { + if (!evt_name_list) { + pr_debug("Failed to allocate new strlist for symbol events\n"); + return; + } + for (unsigned int i = 0; i < max; i++) { /* * New attr.config still not supported here, the latest * example was PERF_COUNT_SW_CGROUP_SWITCHES */ - if (syms->symbol == NULL) + if (syms[i].symbol == NULL) continue; - if (event_glob != NULL && !(strglobmatch(syms->symbol, event_glob) || - (syms->alias && strglobmatch(syms->alias, event_glob)))) + if (event_glob != NULL && !(strglobmatch(syms[i].symbol, event_glob) || + (syms[i].alias && strglobmatch(syms[i].alias, event_glob)))) continue; if (!is_event_supported(type, i)) continue; - if (!evt_num_known) { - evt_num++; - continue; - } - - if (!name_only && strlen(syms->alias)) - snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias); - else - strlcpy(name, syms->symbol, MAX_NAME_LEN); + if (strlen(syms[i].alias)) { + char name[MAX_NAME_LEN]; - evt_list[evt_i] = strdup(name); - if (evt_list[evt_i] == NULL) - goto out_enomem; - evt_i++; + snprintf(name, MAX_NAME_LEN, "%s OR %s", syms[i].symbol, syms[i].alias); + strlist__add(evt_name_list, name); + } else + strlist__add(evt_name_list, syms[i].symbol); } - if (!evt_num_known) { - evt_num_known = true; - goto restart; - } - qsort(evt_list, evt_num, sizeof(char *), cmp_string); - evt_i = 0; - while (evt_i < evt_num) { + strlist__for_each_entry(nd, evt_name_list) { if (name_only) { - printf("%s ", evt_list[evt_i++]); + printf("%s ", nd->s); continue; } - printf(" %-50s [%s]\n", evt_list[evt_i++], event_type_descriptors[type]); + printf(" %-50s [%s]\n", nd->s, event_type_descriptors[type]); } - if (evt_num && pager_in_use()) + if (!strlist__empty(evt_name_list) && pager_in_use()) printf("\n"); -out_free: - evt_num = evt_i; - for (evt_i = 0; evt_i < evt_num; evt_i++) - zfree(&evt_list[evt_i]); - zfree(&evt_list); - return; - -out_enomem: - printf("FATAL: not enough memory to print %s\n", event_type_descriptors[type]); - if (evt_list) - goto out_free; + strlist__delete(evt_name_list); } /* From patchwork Mon Nov 14 18:12:49 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Rogers X-Patchwork-Id: 19981 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:6687:0:0:0:0:0 with SMTP id l7csp2292721wru; Mon, 14 Nov 2022 10:20:42 -0800 (PST) X-Google-Smtp-Source: AA0mqf7Xr3VVBCVUA8Kb3LKu9LF+o+TQTS3r+Xpr91sPmaKTXMXOuALg8MGvChXxELQRkueeSe/i X-Received: by 2002:a17:902:6b02:b0:186:9890:97cd with SMTP id o2-20020a1709026b0200b00186989097cdmr427191plk.104.1668450042335; Mon, 14 Nov 2022 10:20:42 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1668450042; cv=none; d=google.com; s=arc-20160816; b=JFc01yH1OIRTU3sBnRCFx0o2KjeOVP6Ak7MPPaj7KPjPsWlRz/gqVqLuYCb0KWMjwa vRPKOnZqLPf70HNxc+2Er/hBzW1wzb9nBOdL+CdYcWxGnUTIKAgqekNTsrG4rxuxhqHm TOSZdWtRXkqKj2Xz1C2/kE6Agf4IBaSEViqjolxNRnOl+pUnMEyXs/FrMo6qewlLtlOv +UQC6AEC1Ut2rfXp54BlfaDHG6X1bWzoF8mUddNgrzap6r8DnvqgD35+OmXoa1C6/exw IlrX9rfqwe5A7HMK07OFZFgKWBqIeczJzq103yzOgRKyXZfvCpSTgkPCNSXnuBjZP2Td oEAQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:from:subject:references:mime-version :message-id:in-reply-to:date:dkim-signature; bh=p0sFG9H+Jdt/7rD1rWzkttpjmL0LLUKjEOvGlXV4TqY=; b=wN9wJ8vTZRJ2chHWSUsMPgknAZZ0HP5JaOiDS2e756QQq5wIBvq6qlWfXrVQ+XIsJi 1iwwTO5wXCmBz2eGyHvQlG5+h/7fVc0qY6g8nXWu4PF6vkU7/ZEOd7eMbey93Fb4Xzaz ieancffStPiDyiKfiZP96VKdRj0gTdPSSDrnTi7moeImQ3LQWu8MUEW6rj++5yaNSatW g1RfFYdVjqRirF6Wq4vgKYjc8X/hu+lh4TsPCU+5XpCE1B/hi64u7EMt5S3k+pjF5Vpv rJoQDguo5t9JH6JVUsiygDJYK3VarCR/aAyYBWok6cwnj35VePh+aUEx1erQgONalunW xbsw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20210112 header.b=pSvjPn+9; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id o11-20020a170902d4cb00b0017f577878edsi11392097plg.368.2022.11.14.10.20.28; Mon, 14 Nov 2022 10:20:42 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20210112 header.b=pSvjPn+9; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238415AbiKNSPW (ORCPT + 99 others); Mon, 14 Nov 2022 13:15:22 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44730 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238410AbiKNSO5 (ORCPT ); Mon, 14 Nov 2022 13:14:57 -0500 Received: from mail-yw1-x114a.google.com (mail-yw1-x114a.google.com [IPv6:2607:f8b0:4864:20::114a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D58E02B263 for ; Mon, 14 Nov 2022 10:14:12 -0800 (PST) Received: by mail-yw1-x114a.google.com with SMTP id 00721157ae682-367f94b9b16so112177367b3.11 for ; Mon, 14 Nov 2022 10:14:12 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:references:mime-version:message-id:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=p0sFG9H+Jdt/7rD1rWzkttpjmL0LLUKjEOvGlXV4TqY=; b=pSvjPn+9c3QfCFIjYQab5YrlTKk7davFY3ZSvqrmKI2ah6JokR3pUKr/2/Z/Mqvfe+ HTpDUsNwwgs5ZgNij5QV6srhx3nBMDo21/iVmno2sJq9Emo3DOkV9o1suBBVQlMKB5/9 Q5nDSS6fTm3pShpJLg/6YXlgbzskTWUgslnIafEBlgLtfjBenNeGAisr8dQgfuSwBylG SS1rX7GGJ1U+eENkORTG6TMXCTSzCheCRnZHbJiX1CsyKYNHExvv3oZzSMXxt2sMsMPG qznIJYljcJw7YVmTo/w1KrPDP52wjGKL5KMBspjGDle1oLEU4S6zEiBISdYxa5YoKQ+Z P/mA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:references:mime-version:message-id:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=p0sFG9H+Jdt/7rD1rWzkttpjmL0LLUKjEOvGlXV4TqY=; b=et2xhDm8RBaVPitH4Byufp65qNW/UsWbHE4lpfNE+mLmpj3yCnWgWZ2fxLXpghDGEw LgvvqYI2A0JgNgFw94hlFOFwR4wPUjjjL0g8xm3RtQX6iKxhv0Foq6hsfBRAccAxkRF4 FmVYqIo44pFmqybV+jDgAZaEpwvTZcIPkPn4hpG3o4wMqx/SF6zLPc6m/GR+IVXGPCCB gsrttuJL/70TfsIH6VeO0U+0f7gQQKZv3fLtq6QiZ6aU3GyNRXLMpVeUKfBxXqT8G6qL 0iT/8h0kwY60N8exg19edZhPkRJNo9IgYG1blc6PrG3oC3VtgAKGScX9hXItbeHg6jSP i7SA== X-Gm-Message-State: ANoB5plY/Jr9QuHei+ToXWtARmeyRjv80R9QjrBX9k/SAq6JU7ks2a6+ woSHGmSsBPvvxBIzEKRzaFwhQVsNcy0u X-Received: from irogers.svl.corp.google.com ([2620:15c:2d4:203:553:438f:b86a:87f]) (user=irogers job=sendgmr) by 2002:a81:7703:0:b0:360:65a3:46c with SMTP id s3-20020a817703000000b0036065a3046cmr14018869ywc.119.1668449652158; Mon, 14 Nov 2022 10:14:12 -0800 (PST) Date: Mon, 14 Nov 2022 10:12:49 -0800 In-Reply-To: <20221114181251.2683871-1-irogers@google.com> Message-Id: <20221114181251.2683871-8-irogers@google.com> Mime-Version: 1.0 References: <20221114181251.2683871-1-irogers@google.com> X-Mailer: git-send-email 2.38.1.431.g37b22c650d-goog Subject: [PATCH v2 7/9] perf pmu: Restructure print_pmu_events From: Ian Rogers To: Weilin Wang , Perry Taylor , Caleb Biggers , Leo Yan , Adrian Hunter , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Mark Rutland , Alexander Shishkin , Jiri Olsa , Namhyung Kim , Sandipan Das , Kajol Jain , Zhengjun Xing , Kan Liang , Ravi Bangoria , Xin Gao , Rob Herring , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org Cc: Stephane Eranian , Ian Rogers X-Spam-Status: No, score=-9.6 required=5.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1749496671293410549?= X-GMAIL-MSGID: =?utf-8?q?1749496671293410549?= Previously print_pmu_events would compute the values to be printed, place them in struct sevent, sort them and then print them. Modify the code so that struct sevent holds just the PMU and event, sort these and then in the main print loop calculate aliases for names, etc. This avoids memory allocations for copied values as they are computed then printed. Signed-off-by: Ian Rogers --- tools/perf/util/pmu.c | 208 ++++++++++++++++++++++-------------------- 1 file changed, 110 insertions(+), 98 deletions(-) diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 779839525437..2dd543fd6b4d 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -1554,8 +1554,8 @@ static int sub_non_neg(int a, int b) return a - b; } -static char *format_alias(char *buf, int len, struct perf_pmu *pmu, - struct perf_pmu_alias *alias) +static char *format_alias(char *buf, int len, const struct perf_pmu *pmu, + const struct perf_pmu_alias *alias) { struct parse_events_term *term; int used = snprintf(buf, len, "%s/%s", pmu->name, alias->name); @@ -1580,51 +1580,67 @@ static char *format_alias(char *buf, int len, struct perf_pmu *pmu, return buf; } -static char *format_alias_or(char *buf, int len, struct perf_pmu *pmu, - struct perf_pmu_alias *alias) +static char *format_alias_or(char *buf, int len, const struct perf_pmu *pmu, + const struct perf_pmu_alias *alias) { snprintf(buf, len, "%s OR %s/%s/", alias->name, pmu->name, alias->name); return buf; } +/** Struct for ordering events as output in perf list. */ struct sevent { - char *name; - char *desc; - char *topic; - char *str; - char *pmu; - char *metric_expr; - char *metric_name; - int is_cpu; + /** PMU for event. */ + const struct perf_pmu *pmu; + /** + * Optional event for name, desc, etc. If not present then this is a + * selectable PMU and the event name is shown as "//". + */ + const struct perf_pmu_alias *event; + /** Is the PMU for the CPU? */ + bool is_cpu; }; static int cmp_sevent(const void *a, const void *b) { const struct sevent *as = a; const struct sevent *bs = b; + const char *a_pmu_name, *b_pmu_name; + const char *a_name = "//", *a_desc = NULL, *a_topic = ""; + const char *b_name = "//", *b_desc = NULL, *b_topic = ""; int ret; - /* Put extra events last */ - if (!!as->desc != !!bs->desc) - return !!as->desc - !!bs->desc; - if (as->topic && bs->topic) { - int n = strcmp(as->topic, bs->topic); - - if (n) - return n; + if (as->event) { + a_name = as->event->name; + a_desc = as->event->desc; + a_topic = as->event->topic ?: ""; } + if (bs->event) { + b_name = bs->event->name; + b_desc = bs->event->desc; + b_topic = bs->event->topic ?: ""; + } + /* Put extra events last. */ + if (!!a_desc != !!b_desc) + return !!a_desc - !!b_desc; + + /* Order by topics. */ + ret = strcmp(a_topic, b_topic); + if (ret) + return ret; /* Order CPU core events to be first */ if (as->is_cpu != bs->is_cpu) return bs->is_cpu - as->is_cpu; - ret = strcmp(as->name, bs->name); - if (!ret) { - if (as->pmu && bs->pmu) - return strcmp(as->pmu, bs->pmu); - } + /* Order by PMU name. */ + a_pmu_name = as->pmu->name ?: ""; + b_pmu_name = bs->pmu->name ?: ""; + ret = strcmp(a_pmu_name, b_pmu_name); + if (ret) + return ret; - return ret; + /* Order by event name. */ + return strcmp(a_name, b_name); } static void wordwrap(char *s, int start, int max, int corr) @@ -1656,16 +1672,18 @@ bool is_pmu_core(const char *name) static bool pmu_alias_is_duplicate(struct sevent *alias_a, struct sevent *alias_b) { - /* Different names -> never duplicates */ - if (strcmp(alias_a->name, alias_b->name)) - return false; + const char *a_pmu_name, *b_pmu_name; + const char *a_name = alias_a->event ? alias_a->event->name : "//"; + const char *b_name = alias_b->event ? alias_b->event->name : "//"; - /* Don't remove duplicates for hybrid PMUs */ - if (perf_pmu__is_hybrid(alias_a->pmu) && - perf_pmu__is_hybrid(alias_b->pmu)) + /* Different names -> never duplicates */ + if (strcmp(a_name, b_name)) return false; - return true; + /* Don't remove duplicates for different PMUs */ + a_pmu_name = alias_a->pmu->name ?: ""; + b_pmu_name = alias_b->pmu->name ?: ""; + return strcmp(a_pmu_name, b_pmu_name) == 0; } void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag, @@ -1691,110 +1709,104 @@ void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag, len++; } aliases = zalloc(sizeof(struct sevent) * len); - if (!aliases) - goto out_enomem; + if (!aliases) { + pr_err("FATAL: not enough memory to print PMU events\n"); + return; + } pmu = NULL; j = 0; while ((pmu = perf_pmu__scan(pmu)) != NULL) { + bool is_cpu; + if (pmu_name && pmu->name && strcmp(pmu_name, pmu->name)) continue; - list_for_each_entry(alias, &pmu->aliases, list) { - char *name = alias->desc ? alias->name : - format_alias(buf, sizeof(buf), pmu, alias); - bool is_cpu = is_pmu_core(pmu->name) || - perf_pmu__is_hybrid(pmu->name); + is_cpu = is_pmu_core(pmu->name) || pmu->is_hybrid; + list_for_each_entry(alias, &pmu->aliases, list) { if (alias->deprecated && !deprecated) continue; if (event_glob != NULL && - !(strglobmatch_nocase(name, event_glob) || - (!is_cpu && strglobmatch_nocase(alias->name, - event_glob)) || + !(strglobmatch_nocase(alias->name, event_glob) || + (!is_cpu && + strglobmatch_nocase(alias->name, event_glob)) || (alias->topic && strglobmatch_nocase(alias->topic, event_glob)))) continue; - if (is_cpu && !name_only && !alias->desc) - name = format_alias_or(buf, sizeof(buf), pmu, alias); - - aliases[j].name = name; - if (is_cpu && !name_only && !alias->desc) - aliases[j].name = format_alias_or(buf, - sizeof(buf), - pmu, alias); - aliases[j].name = strdup(aliases[j].name); - if (!aliases[j].name) - goto out_enomem; - - aliases[j].desc = long_desc ? alias->long_desc : - alias->desc; - aliases[j].topic = alias->topic; - aliases[j].str = alias->str; - aliases[j].pmu = pmu->name; - aliases[j].metric_expr = alias->metric_expr; - aliases[j].metric_name = alias->metric_name; + aliases[j].event = alias; + aliases[j].pmu = pmu; aliases[j].is_cpu = is_cpu; j++; } if (pmu->selectable && (event_glob == NULL || strglobmatch(pmu->name, event_glob))) { - char *s; - if (asprintf(&s, "%s//", pmu->name) < 0) - goto out_enomem; - aliases[j].name = s; + aliases[j].event = NULL; + aliases[j].pmu = pmu; + aliases[j].is_cpu = is_cpu; j++; } } len = j; qsort(aliases, len, sizeof(struct sevent), cmp_sevent); for (j = 0; j < len; j++) { + char *name, *desc; + /* Skip duplicates */ if (j > 0 && pmu_alias_is_duplicate(&aliases[j], &aliases[j - 1])) continue; + if (!aliases[j].event) { + /* A selectable event. */ + snprintf(buf, sizeof(buf), "%s//", aliases[j].pmu->name); + name = buf; + } else if (aliases[j].event->desc) { + name = aliases[j].event->name; + } else { + if (!name_only && aliases[j].is_cpu) { + name = format_alias_or(buf, sizeof(buf), aliases[j].pmu, + aliases[j].event); + } else { + name = format_alias(buf, sizeof(buf), aliases[j].pmu, + aliases[j].event); + } + } if (name_only) { - printf("%s ", aliases[j].name); + printf("%s ", name); continue; } - if (aliases[j].desc && !quiet_flag) { - if (numdesc++ == 0) - printf("\n"); - if (aliases[j].topic && (!topic || - strcmp(topic, aliases[j].topic))) { - printf("%s%s:\n", topic ? "\n" : "", - aliases[j].topic); - topic = aliases[j].topic; - } - printf(" %-50s\n", aliases[j].name); - printf("%*s", 8, "["); - wordwrap(aliases[j].desc, 8, columns, 0); - printf("]\n"); - if (details_flag) { - printf("%*s%s/%s/ ", 8, "", aliases[j].pmu, aliases[j].str); - if (aliases[j].metric_name) - printf(" MetricName: %s", aliases[j].metric_name); - if (aliases[j].metric_expr) - printf(" MetricExpr: %s", aliases[j].metric_expr); - putchar('\n'); - } - } else - printf(" %-50s [Kernel PMU event]\n", aliases[j].name); printed++; + if (!aliases[j].event || !aliases[j].event->desc || quiet_flag) { + printf(" %-50s [Kernel PMU event]\n", name); + continue; + } + if (numdesc++ == 0) + printf("\n"); + if (aliases[j].event->topic && (!topic || + strcmp(topic, aliases[j].event->topic))) { + printf("%s%s:\n", topic ? "\n" : "", aliases[j].event->topic); + topic = aliases[j].event->topic; + } + printf(" %-50s\n", name); + printf("%*s", 8, "["); + desc = long_desc ? aliases[j].event->long_desc : aliases[j].event->desc; + wordwrap(desc, 8, columns, 0); + printf("]\n"); + if (details_flag) { + printf("%*s%s/%s/ ", 8, "", aliases[j].pmu->name, aliases[j].event->str); + if (aliases[j].event->metric_name) + printf(" MetricName: %s", aliases[j].event->metric_name); + if (aliases[j].event->metric_expr) + printf(" MetricExpr: %s", aliases[j].event->metric_expr); + putchar('\n'); + } } if (printed && pager_in_use()) printf("\n"); -out_free: - for (j = 0; j < len; j++) - zfree(&aliases[j].name); + zfree(&aliases); return; - -out_enomem: - printf("FATAL: not enough memory to print PMU events\n"); - if (aliases) - goto out_free; } bool pmu_have_event(const char *pname, const char *name) From patchwork Mon Nov 14 18:12:50 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Rogers X-Patchwork-Id: 19978 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:6687:0:0:0:0:0 with SMTP id l7csp2292345wru; Mon, 14 Nov 2022 10:20:01 -0800 (PST) X-Google-Smtp-Source: AA0mqf5mkU4YpyHJL/Aa/YK2iLRKSkbglD6KXkA1H5gAXJCjkmd/X0BRQPpUL5ZSOVq54ODm7qzH X-Received: by 2002:a05:6a00:4215:b0:548:4e65:348d with SMTP id cd21-20020a056a00421500b005484e65348dmr14706584pfb.56.1668450001222; Mon, 14 Nov 2022 10:20:01 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1668450001; cv=none; d=google.com; s=arc-20160816; b=hvccLBYSI0Yb6Mpw5CF/yGj/MiBxUOGxoW1XbJiQ6pnsJxnrVi4fWOyOewKbJHDsY/ Xy+UonjPx3ry4rguMgHRi4m0KWHNkp8cIzjItXJk1fB3mCEb/J3XA6Zrr8m4Han0A3E9 MKxWPUdN2I5UE2kRntIqnJJZwgNRDtmwBTX5Q7Skxad5X3GT3ZeEr7IeTZr4UstbeGS4 8xofoR3NcsTa8Awq9vnSFpES7r0ORP+JjKl7d5jiNFGBx2PR0yjt4eAuhVRlsODe/Fvw oUAdTK6tw5bDKX87QKxSjbjAheDEkyhUWr6CO//ASoYmGWh7lV3cg2Xr/ExkqhZf0S5H a69A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:from:subject:references:mime-version :message-id:in-reply-to:date:dkim-signature; bh=D94OoRuVLxPq5+z3E/FO/cKd1uq1gbLznyvqkoPgER0=; b=NfcpWi61jeBjf36dT8/644wIxzJPJb7yjuZhCCXIcHxA8SMRKClsmkzcUgOfWA6soB eDQJl6deshRtab8a2TbUncVtNmuOO7WN1uhVEqKNFNyXehpT1rVV9dzS4K3YIsSctRvU /U8m66EGT064bM2MgTHAZb72eDFWXLwYtOeloF6GM4Gb95EIAu7T9pCrQQNBb60kLP68 LAz2R+TtzPYmHhu7z3KE+xpbedl7vml9BDPBTIsKIVkgLeNB7ygvOnIKr5l7FAknS3fC 3LCMrdZBCUQb0IaWSRSvBTBivLngpmjRRdzFnztXHzuJffTVlOqP9/DbyxHEVdgECWxW qpZA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20210112 header.b="oR/m/cyz"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id ik17-20020a170902ab1100b00188a51cb587si9653930plb.576.2022.11.14.10.19.47; Mon, 14 Nov 2022 10:20:01 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20210112 header.b="oR/m/cyz"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238419AbiKNSPp (ORCPT + 99 others); Mon, 14 Nov 2022 13:15:45 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43112 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238390AbiKNSPQ (ORCPT ); Mon, 14 Nov 2022 13:15:16 -0500 Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D5AF531ECA for ; Mon, 14 Nov 2022 10:14:21 -0800 (PST) Received: by mail-yb1-xb49.google.com with SMTP id f8-20020a25bd88000000b006dda2c86272so9423689ybh.5 for ; Mon, 14 Nov 2022 10:14:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:references:mime-version:message-id:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=D94OoRuVLxPq5+z3E/FO/cKd1uq1gbLznyvqkoPgER0=; b=oR/m/cyzcA2eWRVQOE9KbDkQZfT3qhg6kR20iNbQxXnRjQujTGp8uk6XMgePK3jipT tUlBXFzfJ5TFkh/be4lMkfIYXbAbRXppGagzdhD1/7fCl8C6HInxydl1jB74NPvjBYGH vbIqMnEP5ie1uDurSf3ObBzsQVpHIfECMoGMJbQN4fpH1XJkzuPQAiBYhybieLegQkX9 nHDLp5i3hsvZ8MdZQUw2KVMiqKTWoVxFnSZDKcZBvxtylVeFLB/x3HlxrYcDMnOs20pl HlxTrJR/nLIkIgMysUaIXWCKba9LqUlWsbBznFx8hdPipbNrOcuuXH252nfyOPC9HaF/ jh/w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:references:mime-version:message-id:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=D94OoRuVLxPq5+z3E/FO/cKd1uq1gbLznyvqkoPgER0=; b=OQogq1jxE9xCmDhvRJ9h0s84Dm1kF//ROhvQkRNsE/EnXjeR5JyxP/sNubxkpi5Xxo Nll5p6tFzqj+WXZ+4u/nQ/Txf5iIZlTsmkaAjlpvEnCT+LdAeR/C4wHmgVXiOMcxLg1N iJjGwZryH/iluSsSHTwp/E3k8cjUU1p7UuMdJD6s+T7Papm6ubrdxeVK7hnOXWzcKA0Z uNG/TXmB7Iod8kMyrY8l08cUJ052Tlk+r+FIFKk5imu5UO5myZSJLpf13+tPznEgUU5E D1ZV5DdsCito/rA0U9uIwck2QGlQqJsbga0MWLicl3O26x/CtC2rc3hnLJ9xxstRzDLJ A9eQ== X-Gm-Message-State: ACrzQf2GttEitKeJ+bCqiH457TWQ4SCCyowgArbACs7Cy+Jg++/6rMbs WNTComWZVktXU4mGWx8PAv3k0CbWr1nl X-Received: from irogers.svl.corp.google.com ([2620:15c:2d4:203:553:438f:b86a:87f]) (user=irogers job=sendgmr) by 2002:a25:bb44:0:b0:6bb:a336:7762 with SMTP id b4-20020a25bb44000000b006bba3367762mr63581241ybk.501.1668449660633; Mon, 14 Nov 2022 10:14:20 -0800 (PST) Date: Mon, 14 Nov 2022 10:12:50 -0800 In-Reply-To: <20221114181251.2683871-1-irogers@google.com> Message-Id: <20221114181251.2683871-9-irogers@google.com> Mime-Version: 1.0 References: <20221114181251.2683871-1-irogers@google.com> X-Mailer: git-send-email 2.38.1.431.g37b22c650d-goog Subject: [PATCH v2 8/9] perf list: Reorganize to use callbacks From: Ian Rogers To: Weilin Wang , Perry Taylor , Caleb Biggers , Leo Yan , Adrian Hunter , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Mark Rutland , Alexander Shishkin , Jiri Olsa , Namhyung Kim , Sandipan Das , Kajol Jain , Zhengjun Xing , Kan Liang , Ravi Bangoria , Xin Gao , Rob Herring , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org Cc: Stephane Eranian , Ian Rogers X-Spam-Status: No, score=-9.6 required=5.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1749496628192136649?= X-GMAIL-MSGID: =?utf-8?q?1749496628192136649?= Rather than controlling the list output with passed flags, add callbacks that are called when an event or metric are encountered. State is passed to the callback so that command line options can be respected, alternatively the callbacks can be changed. Fix a few bugs: - wordwrap to columns metric descriptions and expressions; - remove unnecessary whitespace after PMU event names; - the metric filter is a glob but matched using strstr which will always fail, switch to using a proper globmatch, - the detail flag gives details for extra kernel PMU events like branch-instructions. In metricgroup.c switch from struct mep being a rbtree of metricgroups containing a list of metrics, to the tree directly containing all the metrics. In general the alias for a name is passed to the print routine rather than being contained in the name with OR. Signed-off-by: Ian Rogers --- tools/perf/builtin-list.c | 320 ++++++++++++++++++++++++----- tools/perf/util/metricgroup.c | 239 ++++++---------------- tools/perf/util/metricgroup.h | 4 +- tools/perf/util/pmu.c | 137 ++++--------- tools/perf/util/pmu.h | 5 +- tools/perf/util/print-events.c | 355 +++++++++++++++++---------------- tools/perf/util/print-events.h | 40 ++-- 7 files changed, 588 insertions(+), 512 deletions(-) diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c index cc84ced6da26..91e2b6f52548 100644 --- a/tools/perf/builtin-list.c +++ b/tools/perf/builtin-list.c @@ -15,31 +15,229 @@ #include "util/pmu-hybrid.h" #include "util/debug.h" #include "util/metricgroup.h" +#include "util/string2.h" +#include "util/strlist.h" #include #include #include -static bool desc_flag = true; -static bool details_flag; +struct print_state { + /** + * Optionally restrict PMU and metric matching to PMU or debugfs + * subsystem name. + */ + char *pmu_glob; + /** Optional pattern matching glob. */ + char *event_glob; + /** Print event or metric names only. */ + bool name_only; + /** Print the event or metric description. */ + bool desc; + /** Print longer event or metric description. */ + bool long_desc; + /** Print deprecated events or metrics. */ + bool deprecated; + /** + * Print extra information on the perf event such as names and + * expressions used internally by events. + */ + bool detailed; + bool metrics; + bool metricgroups; + char *last_topic; + char *last_metricgroups; + struct strlist *visited_metrics; +}; + +static void default_print_start(void *ps) +{ + struct print_state *print_state = ps; + + if (!print_state->name_only && pager_in_use()) + printf("\nList of pre-defined events (to be used in -e or -M):\n\n"); +} + +static void default_print_end(void *print_state __maybe_unused) {} + +static void wordwrap(const char *s, int start, int max, int corr) +{ + int column = start; + int n; + + while (*s) { + int wlen = strcspn(s, " \t"); + + if (column + wlen >= max && column > start) { + printf("\n%*s", start, ""); + column = start + corr; + } + n = printf("%s%.*s", column > start ? " " : "", wlen, s); + if (n <= 0) + break; + s += wlen; + column += n; + s = skip_spaces(s); + } +} + +static void default_print_event(void *ps, const char *pmu_name, const char *topic, + const char *event_name, const char *event_alias, + bool deprecated, const char *event_type_desc, + const char *desc, const char *long_desc, + const char *encoding_desc, + const char *metric_name, const char *metric_expr) +{ + struct print_state *print_state = ps; + int pos; + + if (deprecated && !print_state->deprecated) + return; + + if (print_state->pmu_glob && !strglobmatch(pmu_name, print_state->pmu_glob)) + return; + + if (print_state->event_glob && + (!event_name || !strglobmatch(event_name, print_state->event_glob)) && + (!event_alias || !strglobmatch(event_alias, print_state->event_glob)) && + (!topic || !strglobmatch_nocase(topic, print_state->event_glob))) + return; + + if (print_state->name_only) { + if (event_alias && strlen(event_alias)) + printf("%s ", event_alias); + else + printf("%s ", event_name); + return; + } + + if (strcmp(print_state->last_topic, topic ?: "")) { + if (topic) + printf("\n%s:\n", topic); + free(print_state->last_topic); + print_state->last_topic = strdup(topic ?: ""); + } + + if (event_alias && strlen(event_alias)) + pos = printf(" %s OR %s", event_name, event_alias); + else + pos = printf(" %s", event_name); + + if (!topic && event_type_desc) { + for (; pos < 53; pos++) + putchar(' '); + printf("[%s]\n", event_type_desc); + } else + putchar('\n'); + + if (desc && print_state->desc) { + printf("%*s", 8, "["); + wordwrap(desc, 8, pager_get_columns(), 0); + printf("]\n"); + } + + if (long_desc && print_state->long_desc) { + printf("%*s", 8, "["); + wordwrap(long_desc, 8, pager_get_columns(), 0); + printf("]\n"); + } + + if (print_state->detailed && encoding_desc) { + printf("%*s%s", 8, "", encoding_desc); + if (metric_name) + printf(" MetricName: %s", metric_name); + if (metric_expr) + printf(" MetricExpr: %s", metric_expr); + putchar('\n'); + } +} + +static void default_print_metric(void *ps, + const char *group, + const char *name, + const char *desc, + const char *long_desc, + const char *expr) +{ + struct print_state *print_state = ps; + + if (print_state->event_glob && + (!print_state->metrics || !name || !strglobmatch(name, print_state->event_glob)) && + (!print_state->metricgroups || !group || !strglobmatch(group, print_state->event_glob))) + return; + + if (!print_state->name_only && !print_state->last_metricgroups) { + if (print_state->metricgroups) { + printf("\nMetric Groups:\n"); + if (!print_state->metrics) + putchar('\n'); + } else { + printf("\nMetrics:\n\n"); + } + } + if (!print_state->last_metricgroups || + strcmp(print_state->last_metricgroups, group ?: "")) { + if (group && print_state->metricgroups) { + if (print_state->name_only) + printf("%s ", group); + else if (print_state->metrics) + printf("\n%s:\n", group); + else + printf("%s\n", group); + } + free(print_state->last_metricgroups); + print_state->last_metricgroups = strdup(group ?: ""); + } + if (!print_state->metrics) + return; + + if (print_state->name_only) { + if (print_state->metrics && + !strlist__has_entry(print_state->visited_metrics, name)) { + printf("%s ", name); + strlist__add(print_state->visited_metrics, name); + } + return; + } + printf(" %s\n", name); + + if (desc && print_state->desc) { + printf("%*s", 8, "["); + wordwrap(desc, 8, pager_get_columns(), 0); + printf("]\n"); + } + if (long_desc && print_state->long_desc) { + printf("%*s", 8, "["); + wordwrap(long_desc, 8, pager_get_columns(), 0); + printf("]\n"); + } + if (expr && print_state->detailed) { + printf("%*s", 8, "["); + wordwrap(expr, 8, pager_get_columns(), 0); + printf("]\n"); + } +} int cmd_list(int argc, const char **argv) { int i, ret = 0; - bool raw_dump = false; - bool long_desc_flag = false; - bool deprecated = false; - char *pmu_name = NULL; + struct print_state ps = {}; + struct print_callbacks print_cb = { + .print_start = default_print_start, + .print_end = default_print_end, + .print_event = default_print_event, + .print_metric = default_print_metric, + }; const char *hybrid_name = NULL; const char *unit_name = NULL; struct option list_options[] = { - OPT_BOOLEAN(0, "raw-dump", &raw_dump, "Dump raw events"), - OPT_BOOLEAN('d', "desc", &desc_flag, + OPT_BOOLEAN(0, "raw-dump", &ps.name_only, "Dump raw events"), + OPT_BOOLEAN('d', "desc", &ps.desc, "Print extra event descriptions. --no-desc to not print."), - OPT_BOOLEAN('v', "long-desc", &long_desc_flag, + OPT_BOOLEAN('v', "long-desc", &ps.long_desc, "Print longer event descriptions."), - OPT_BOOLEAN(0, "details", &details_flag, + OPT_BOOLEAN(0, "details", &ps.detailed, "Print information on the perf event names and expressions used internally by events."), - OPT_BOOLEAN(0, "deprecated", &deprecated, + OPT_BOOLEAN(0, "deprecated", &ps.deprecated, "Print deprecated events."), OPT_STRING(0, "cputype", &hybrid_name, "hybrid cpu type", "Limit PMU or metric printing to the given hybrid PMU (e.g. core or atom)."), @@ -63,20 +261,28 @@ int cmd_list(int argc, const char **argv) setup_pager(); - if (!raw_dump && pager_in_use()) - printf("\nList of pre-defined events (to be used in -e or -M):\n\n"); + if (!ps.name_only) + setup_pager(); + ps.desc = !ps.long_desc; + ps.last_topic = strdup(""); + assert(ps.last_topic); + ps.visited_metrics = strlist__new(NULL, NULL); + assert(ps.visited_metrics); if (unit_name) - pmu_name = strdup(unit_name); + ps.pmu_glob = strdup(unit_name); else if (hybrid_name) { - pmu_name = perf_pmu__hybrid_type_to_pmu(hybrid_name); - if (!pmu_name) + ps.pmu_glob = perf_pmu__hybrid_type_to_pmu(hybrid_name); + if (!ps.pmu_glob) pr_warning("WARNING: hybrid cputype is not supported!\n"); } + print_cb.print_start(&ps); + if (argc == 0) { - print_events(NULL, raw_dump, !desc_flag, long_desc_flag, - details_flag, deprecated, pmu_name); + ps.metrics = true; + ps.metricgroups = true; + print_events(&print_cb, &ps); goto out; } @@ -84,30 +290,33 @@ int cmd_list(int argc, const char **argv) char *sep, *s; if (strcmp(argv[i], "tracepoint") == 0) - print_tracepoint_events(NULL, NULL, raw_dump); + print_tracepoint_events(&print_cb, &ps); else if (strcmp(argv[i], "hw") == 0 || strcmp(argv[i], "hardware") == 0) - print_symbol_events(NULL, PERF_TYPE_HARDWARE, - event_symbols_hw, PERF_COUNT_HW_MAX, raw_dump); + print_symbol_events(&print_cb, &ps, PERF_TYPE_HARDWARE, + event_symbols_hw, PERF_COUNT_HW_MAX); else if (strcmp(argv[i], "sw") == 0 || strcmp(argv[i], "software") == 0) { - print_symbol_events(NULL, PERF_TYPE_SOFTWARE, - event_symbols_sw, PERF_COUNT_SW_MAX, raw_dump); - print_tool_events(NULL, raw_dump); + print_symbol_events(&print_cb, &ps, PERF_TYPE_SOFTWARE, + event_symbols_sw, PERF_COUNT_SW_MAX); + print_tool_events(&print_cb, &ps); } else if (strcmp(argv[i], "cache") == 0 || strcmp(argv[i], "hwcache") == 0) - print_hwcache_events(NULL, raw_dump); + print_hwcache_events(&print_cb, &ps); else if (strcmp(argv[i], "pmu") == 0) - print_pmu_events(NULL, raw_dump, !desc_flag, - long_desc_flag, details_flag, - deprecated, pmu_name); + print_pmu_events(&print_cb, &ps); else if (strcmp(argv[i], "sdt") == 0) - print_sdt_events(NULL, NULL, raw_dump); - else if (strcmp(argv[i], "metric") == 0 || strcmp(argv[i], "metrics") == 0) - metricgroup__print(true, false, NULL, raw_dump, details_flag, pmu_name); - else if (strcmp(argv[i], "metricgroup") == 0 || strcmp(argv[i], "metricgroups") == 0) - metricgroup__print(false, true, NULL, raw_dump, details_flag, pmu_name); - else if ((sep = strchr(argv[i], ':')) != NULL) { + print_sdt_events(&print_cb, &ps); + else if (strcmp(argv[i], "metric") == 0 || strcmp(argv[i], "metrics") == 0) { + ps.metricgroups = false; + ps.metrics = true; + metricgroup__print(&print_cb, &ps); + } else if (strcmp(argv[i], "metricgroup") == 0 || + strcmp(argv[i], "metricgroups") == 0) { + ps.metricgroups = true; + ps.metrics = false; + metricgroup__print(&print_cb, &ps); + } else if ((sep = strchr(argv[i], ':')) != NULL) { int sep_idx; sep_idx = sep - argv[i]; @@ -118,34 +327,41 @@ int cmd_list(int argc, const char **argv) } s[sep_idx] = '\0'; - print_tracepoint_events(s, s + sep_idx + 1, raw_dump); - print_sdt_events(s, s + sep_idx + 1, raw_dump); - metricgroup__print(true, true, s, raw_dump, details_flag, pmu_name); + ps.pmu_glob = s; + ps.event_glob = s + sep_idx + 1; + print_tracepoint_events(&print_cb, &ps); + print_sdt_events(&print_cb, &ps); + ps.metrics = true; + ps.metricgroups = true; + metricgroup__print(&print_cb, &ps); free(s); } else { if (asprintf(&s, "*%s*", argv[i]) < 0) { printf("Critical: Not enough memory! Trying to continue...\n"); continue; } - print_symbol_events(s, PERF_TYPE_HARDWARE, - event_symbols_hw, PERF_COUNT_HW_MAX, raw_dump); - print_symbol_events(s, PERF_TYPE_SOFTWARE, - event_symbols_sw, PERF_COUNT_SW_MAX, raw_dump); - print_tool_events(s, raw_dump); - print_hwcache_events(s, raw_dump); - print_pmu_events(s, raw_dump, !desc_flag, - long_desc_flag, - details_flag, - deprecated, - pmu_name); - print_tracepoint_events(NULL, s, raw_dump); - print_sdt_events(NULL, s, raw_dump); - metricgroup__print(true, true, s, raw_dump, details_flag, pmu_name); + ps.event_glob = s; + print_symbol_events(&print_cb, &ps, PERF_TYPE_HARDWARE, + event_symbols_hw, PERF_COUNT_HW_MAX); + print_symbol_events(&print_cb, &ps, PERF_TYPE_SOFTWARE, + event_symbols_sw, PERF_COUNT_SW_MAX); + print_tool_events(&print_cb, &ps); + print_hwcache_events(&print_cb, &ps); + print_pmu_events(&print_cb, &ps); + print_tracepoint_events(&print_cb, &ps); + print_sdt_events(&print_cb, &ps); + ps.metrics = true; + ps.metricgroups = true; + metricgroup__print(&print_cb, &ps); free(s); } } out: - free(pmu_name); + print_cb.print_end(&ps); + free(ps.pmu_glob); + free(ps.last_topic); + free(ps.last_metricgroups); + strlist__delete(ps.visited_metrics); return ret; } diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index 1943fed9b6d9..4cb2a193c0f2 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -12,6 +12,7 @@ #include "strbuf.h" #include "pmu.h" #include "pmu-hybrid.h" +#include "print-events.h" #include "expr.h" #include "rblist.h" #include @@ -352,51 +353,63 @@ static bool match_pe_metric(const struct pmu_event *pe, const char *metric) match_metric(pe->metric_name, metric); } +/** RB-tree node for building printing information. */ struct mep { struct rb_node nd; - const char *name; - struct strlist *metrics; + /** Owned metric group name, separated others with ';'. */ + char *metric_group; + const char *metric_name; + const char *metric_desc; + const char *metric_long_desc; + const char *metric_expr; }; static int mep_cmp(struct rb_node *rb_node, const void *entry) { struct mep *a = container_of(rb_node, struct mep, nd); struct mep *b = (struct mep *)entry; + int ret; - return strcmp(a->name, b->name); + ret = strcmp(a->metric_group, b->metric_group); + if (ret) + return ret; + + return strcmp(a->metric_name, b->metric_name); } -static struct rb_node *mep_new(struct rblist *rl __maybe_unused, - const void *entry) +static struct rb_node *mep_new(struct rblist *rl __maybe_unused, const void *entry) { struct mep *me = malloc(sizeof(struct mep)); if (!me) return NULL; + memcpy(me, entry, sizeof(struct mep)); - me->name = strdup(me->name); - if (!me->name) - goto out_me; - me->metrics = strlist__new(NULL, NULL); - if (!me->metrics) - goto out_name; return &me->nd; -out_name: - zfree(&me->name); -out_me: +} + +static void mep_delete(struct rblist *rl __maybe_unused, + struct rb_node *nd) +{ + struct mep *me = container_of(nd, struct mep, nd); + + zfree(&me->metric_group); free(me); - return NULL; } -static struct mep *mep_lookup(struct rblist *groups, const char *name) +static struct mep *mep_lookup(struct rblist *groups, const char *metric_group, + const char *metric_name) { struct rb_node *nd; struct mep me = { - .name = name + .metric_group = strdup(metric_group), + .metric_name = metric_name, }; nd = rblist__find(groups, &me); - if (nd) + if (nd) { + free(me.metric_group); return container_of(nd, struct mep, nd); + } rblist__add_node(groups, &me); nd = rblist__find(groups, &me); if (nd) @@ -404,107 +417,36 @@ static struct mep *mep_lookup(struct rblist *groups, const char *name) return NULL; } -static void mep_delete(struct rblist *rl __maybe_unused, - struct rb_node *nd) -{ - struct mep *me = container_of(nd, struct mep, nd); - - strlist__delete(me->metrics); - zfree(&me->name); - free(me); -} - -static void metricgroup__print_strlist(struct strlist *metrics, bool raw) -{ - struct str_node *sn; - int n = 0; - - strlist__for_each_entry (sn, metrics) { - if (raw) - printf("%s%s", n > 0 ? " " : "", sn->s); - else - printf(" %s\n", sn->s); - n++; - } - if (raw) - putchar('\n'); -} - -static int metricgroup__print_pmu_event(const struct pmu_event *pe, - bool metricgroups, char *filter, - bool raw, bool details, - struct rblist *groups, - struct strlist *metriclist) +static int metricgroup__add_to_mep_groups(const struct pmu_event *pe, + struct rblist *groups) { const char *g; char *omg, *mg; - g = pe->metric_group; - if (!g && pe->metric_name) { - if (pe->name) - return 0; - g = "No_group"; - } - - if (!g) - return 0; - - mg = strdup(g); - + mg = strdup(pe->metric_group ?: "No_group"); if (!mg) return -ENOMEM; omg = mg; while ((g = strsep(&mg, ";")) != NULL) { struct mep *me; - char *s; g = skip_spaces(g); - if (*g == 0) - g = "No_group"; - if (filter && !strstr(g, filter)) - continue; - if (raw) - s = (char *)pe->metric_name; - else { - if (asprintf(&s, "%s\n%*s%s]", - pe->metric_name, 8, "[", pe->desc) < 0) - return -1; - if (details) { - if (asprintf(&s, "%s\n%*s%s]", - s, 8, "[", pe->metric_expr) < 0) - return -1; - } - } - - if (!s) - continue; + if (strlen(g)) + me = mep_lookup(groups, g, pe->metric_name); + else + me = mep_lookup(groups, "No_group", pe->metric_name); - if (!metricgroups) { - strlist__add(metriclist, s); - } else { - me = mep_lookup(groups, g); - if (!me) - continue; - strlist__add(me->metrics, s); + if (me) { + me->metric_desc = pe->desc; + me->metric_long_desc = pe->long_desc; + me->metric_expr = pe->metric_expr; } - - if (!raw) - free(s); } free(omg); return 0; } -struct metricgroup_print_sys_idata { - struct strlist *metriclist; - char *filter; - struct rblist *groups; - bool metricgroups; - bool raw; - bool details; -}; - struct metricgroup_iter_data { pmu_event_iter_fn fn; void *data; @@ -527,61 +469,26 @@ static int metricgroup__sys_event_iter(const struct pmu_event *pe, return d->fn(pe, table, d->data); } - return 0; } -static int metricgroup__print_sys_event_iter(const struct pmu_event *pe, - const struct pmu_events_table *table __maybe_unused, - void *data) -{ - struct metricgroup_print_sys_idata *d = data; - - return metricgroup__print_pmu_event(pe, d->metricgroups, d->filter, d->raw, - d->details, d->groups, d->metriclist); -} - -struct metricgroup_print_data { - const char *pmu_name; - struct strlist *metriclist; - char *filter; - struct rblist *groups; - bool metricgroups; - bool raw; - bool details; -}; - -static int metricgroup__print_callback(const struct pmu_event *pe, - const struct pmu_events_table *table __maybe_unused, - void *vdata) +static int metricgroup__add_to_mep_groups_callback(const struct pmu_event *pe, + const struct pmu_events_table *table __maybe_unused, + void *vdata) { - struct metricgroup_print_data *data = vdata; - const char *pmu = pe->pmu ?: "cpu"; + struct rblist *groups = vdata; - if (!pe->metric_expr) + if (!pe->metric_name) return 0; - if (data->pmu_name && strcmp(data->pmu_name, pmu)) - return 0; - - return metricgroup__print_pmu_event(pe, data->metricgroups, data->filter, - data->raw, data->details, data->groups, - data->metriclist); + return metricgroup__add_to_mep_groups(pe, groups); } -void metricgroup__print(bool metrics, bool metricgroups, char *filter, - bool raw, bool details, const char *pmu_name) +void metricgroup__print(const struct print_callbacks *print_cb, void *print_state) { struct rblist groups; - struct rb_node *node, *next; - struct strlist *metriclist = NULL; const struct pmu_events_table *table; - - if (!metricgroups) { - metriclist = strlist__new(NULL, NULL); - if (!metriclist) - return; - } + struct rb_node *node, *next; rblist__init(&groups); groups.node_new = mep_new; @@ -589,56 +496,30 @@ void metricgroup__print(bool metrics, bool metricgroups, char *filter, groups.node_delete = mep_delete; table = pmu_events_table__find(); if (table) { - struct metricgroup_print_data data = { - .pmu_name = pmu_name, - .metriclist = metriclist, - .metricgroups = metricgroups, - .filter = filter, - .raw = raw, - .details = details, - .groups = &groups, - }; - pmu_events_table_for_each_event(table, - metricgroup__print_callback, - &data); + metricgroup__add_to_mep_groups_callback, + &groups); } { struct metricgroup_iter_data data = { - .fn = metricgroup__print_sys_event_iter, - .data = (void *) &(struct metricgroup_print_sys_idata){ - .metriclist = metriclist, - .metricgroups = metricgroups, - .filter = filter, - .raw = raw, - .details = details, - .groups = &groups, - }, + .fn = metricgroup__add_to_mep_groups_callback, + .data = &groups, }; - pmu_for_each_sys_event(metricgroup__sys_event_iter, &data); } - if (!filter || !rblist__empty(&groups)) { - if (metricgroups && !raw) - printf("\nMetric Groups:\n\n"); - else if (metrics && !raw) - printf("\nMetrics:\n\n"); - } - for (node = rb_first_cached(&groups.entries); node; node = next) { struct mep *me = container_of(node, struct mep, nd); - if (metricgroups) - printf("%s%s%s", me->name, metrics && !raw ? ":" : "", raw ? " " : "\n"); - if (metrics) - metricgroup__print_strlist(me->metrics, raw); + print_cb->print_metric(print_state, + me->metric_group, + me->metric_name, + me->metric_desc, + me->metric_long_desc, + me->metric_expr); next = rb_next(node); rblist__remove_node(&groups, node); } - if (!metricgroups) - metricgroup__print_strlist(metriclist, raw); - strlist__delete(metriclist); } static const char *code_characters = ",-=@"; diff --git a/tools/perf/util/metricgroup.h b/tools/perf/util/metricgroup.h index 732d3a0d3334..0013cf582173 100644 --- a/tools/perf/util/metricgroup.h +++ b/tools/perf/util/metricgroup.h @@ -10,6 +10,7 @@ struct evlist; struct evsel; struct option; +struct print_callbacks; struct rblist; struct cgroup; @@ -78,8 +79,7 @@ int metricgroup__parse_groups_test(struct evlist *evlist, bool metric_no_merge, struct rblist *metric_events); -void metricgroup__print(bool metrics, bool groups, char *filter, - bool raw, bool details, const char *pmu_name); +void metricgroup__print(const struct print_callbacks *print_cb, void *print_state); bool metricgroup__has_metric(const char *metric); int arch_get_runtimeparam(const struct pmu_event *pe __maybe_unused); void metricgroup__rblist_exit(struct rblist *metric_events); diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 2dd543fd6b4d..99c2dac268ec 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -23,6 +23,7 @@ #include "evsel.h" #include "pmu.h" #include "parse-events.h" +#include "print-events.h" #include "header.h" #include "string2.h" #include "strbuf.h" @@ -1580,13 +1581,6 @@ static char *format_alias(char *buf, int len, const struct perf_pmu *pmu, return buf; } -static char *format_alias_or(char *buf, int len, const struct perf_pmu *pmu, - const struct perf_pmu_alias *alias) -{ - snprintf(buf, len, "%s OR %s/%s/", alias->name, pmu->name, alias->name); - return buf; -} - /** Struct for ordering events as output in perf list. */ struct sevent { /** PMU for event. */ @@ -1630,7 +1624,7 @@ static int cmp_sevent(const void *a, const void *b) /* Order CPU core events to be first */ if (as->is_cpu != bs->is_cpu) - return bs->is_cpu - as->is_cpu; + return as->is_cpu ? -1 : 1; /* Order by PMU name. */ a_pmu_name = as->pmu->name ?: ""; @@ -1643,27 +1637,6 @@ static int cmp_sevent(const void *a, const void *b) return strcmp(a_name, b_name); } -static void wordwrap(char *s, int start, int max, int corr) -{ - int column = start; - int n; - - while (*s) { - int wlen = strcspn(s, " \t"); - - if (column + wlen >= max && column > start) { - printf("\n%*s", start, ""); - column = start + corr; - } - n = printf("%s%.*s", column > start ? " " : "", wlen, s); - if (n <= 0) - break; - s += wlen; - column += n; - s = skip_spaces(s); - } -} - bool is_pmu_core(const char *name) { return !strcmp(name, "cpu") || is_arm_pmu_core(name); @@ -1686,24 +1659,19 @@ static bool pmu_alias_is_duplicate(struct sevent *alias_a, return strcmp(a_pmu_name, b_pmu_name) == 0; } -void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag, - bool long_desc, bool details_flag, bool deprecated, - const char *pmu_name) +void print_pmu_events(const struct print_callbacks *print_cb, void *print_state) { struct perf_pmu *pmu; - struct perf_pmu_alias *alias; + struct perf_pmu_alias *event; char buf[1024]; int printed = 0; int len, j; struct sevent *aliases; - int numdesc = 0; - int columns = pager_get_columns(); - char *topic = NULL; pmu = NULL; len = 0; while ((pmu = perf_pmu__scan(pmu)) != NULL) { - list_for_each_entry(alias, &pmu->aliases, list) + list_for_each_entry(event, &pmu->aliases, list) len++; if (pmu->selectable) len++; @@ -1716,32 +1684,15 @@ void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag, pmu = NULL; j = 0; while ((pmu = perf_pmu__scan(pmu)) != NULL) { - bool is_cpu; + bool is_cpu = is_pmu_core(pmu->name) || pmu->is_hybrid; - if (pmu_name && pmu->name && strcmp(pmu_name, pmu->name)) - continue; - - is_cpu = is_pmu_core(pmu->name) || pmu->is_hybrid; - - list_for_each_entry(alias, &pmu->aliases, list) { - if (alias->deprecated && !deprecated) - continue; - - if (event_glob != NULL && - !(strglobmatch_nocase(alias->name, event_glob) || - (!is_cpu && - strglobmatch_nocase(alias->name, event_glob)) || - (alias->topic && - strglobmatch_nocase(alias->topic, event_glob)))) - continue; - - aliases[j].event = alias; + list_for_each_entry(event, &pmu->aliases, list) { + aliases[j].event = event; aliases[j].pmu = pmu; aliases[j].is_cpu = is_cpu; j++; } - if (pmu->selectable && - (event_glob == NULL || strglobmatch(pmu->name, event_glob))) { + if (pmu->selectable) { aliases[j].event = NULL; aliases[j].pmu = pmu; aliases[j].is_cpu = is_cpu; @@ -1751,7 +1702,11 @@ void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag, len = j; qsort(aliases, len, sizeof(struct sevent), cmp_sevent); for (j = 0; j < len; j++) { - char *name, *desc; + const char *name, *alias = NULL, *desc = NULL, *long_desc = NULL, + *encoding_desc = NULL, *topic = NULL, + *metric_name = NULL, *metric_expr = NULL; + bool deprecated = false; + size_t buf_used; /* Skip duplicates */ if (j > 0 && pmu_alias_is_duplicate(&aliases[j], &aliases[j - 1])) @@ -1759,48 +1714,44 @@ void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag, if (!aliases[j].event) { /* A selectable event. */ - snprintf(buf, sizeof(buf), "%s//", aliases[j].pmu->name); + buf_used = snprintf(buf, sizeof(buf), "%s//", aliases[j].pmu->name) + 1; name = buf; - } else if (aliases[j].event->desc) { - name = aliases[j].event->name; } else { - if (!name_only && aliases[j].is_cpu) { - name = format_alias_or(buf, sizeof(buf), aliases[j].pmu, - aliases[j].event); + if (aliases[j].event->desc) { + name = aliases[j].event->name; + buf_used = 0; } else { name = format_alias(buf, sizeof(buf), aliases[j].pmu, aliases[j].event); + if (aliases[j].is_cpu) { + alias = name; + name = aliases[j].event->name; + } + buf_used = strlen(buf) + 1; } - } - if (name_only) { - printf("%s ", name); - continue; - } - printed++; - if (!aliases[j].event || !aliases[j].event->desc || quiet_flag) { - printf(" %-50s [Kernel PMU event]\n", name); - continue; - } - if (numdesc++ == 0) - printf("\n"); - if (aliases[j].event->topic && (!topic || - strcmp(topic, aliases[j].event->topic))) { - printf("%s%s:\n", topic ? "\n" : "", aliases[j].event->topic); + desc = aliases[j].event->desc; + long_desc = aliases[j].event->long_desc; topic = aliases[j].event->topic; + encoding_desc = buf + buf_used; + buf_used += snprintf(buf + buf_used, sizeof(buf) - buf_used, + "%s/%s/", aliases[j].pmu->name, + aliases[j].event->str) + 1; + metric_name = aliases[j].event->metric_name; + metric_expr = aliases[j].event->metric_expr; + deprecated = aliases[j].event->deprecated; } - printf(" %-50s\n", name); - printf("%*s", 8, "["); - desc = long_desc ? aliases[j].event->long_desc : aliases[j].event->desc; - wordwrap(desc, 8, columns, 0); - printf("]\n"); - if (details_flag) { - printf("%*s%s/%s/ ", 8, "", aliases[j].pmu->name, aliases[j].event->str); - if (aliases[j].event->metric_name) - printf(" MetricName: %s", aliases[j].event->metric_name); - if (aliases[j].event->metric_expr) - printf(" MetricExpr: %s", aliases[j].event->metric_expr); - putchar('\n'); - } + print_cb->print_event(print_state, + aliases[j].pmu->name, + topic, + name, + alias, + deprecated, + "Kernel PMU event", + desc, + long_desc, + encoding_desc, + metric_name, + metric_expr); } if (printed && pager_in_use()) printf("\n"); diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h index ce718bab3018..198a5a8dbc09 100644 --- a/tools/perf/util/pmu.h +++ b/tools/perf/util/pmu.h @@ -12,6 +12,7 @@ struct evsel_config_term; struct perf_cpu_map; +struct print_callbacks; enum { PERF_PMU_FORMAT_VALUE_CONFIG, @@ -227,9 +228,7 @@ void perf_pmu__del_formats(struct list_head *formats); struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu); bool is_pmu_core(const char *name); -void print_pmu_events(const char *event_glob, bool name_only, bool quiet, - bool long_desc, bool details_flag, - bool deprecated, const char *pmu_name); +void print_pmu_events(const struct print_callbacks *print_cb, void *print_state); bool pmu_have_event(const char *pname, const char *name); int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt, ...) __scanf(3, 4); diff --git a/tools/perf/util/print-events.c b/tools/perf/util/print-events.c index d53dba033597..9aa53e43bda0 100644 --- a/tools/perf/util/print-events.c +++ b/tools/perf/util/print-events.c @@ -28,6 +28,7 @@ #define MAX_NAME_LEN 100 +/** Strings corresponding to enum perf_type_id. */ static const char * const event_type_descriptors[] = { "Hardware event", "Software event", @@ -55,11 +56,9 @@ static const struct event_symbol event_symbols_tool[PERF_TOOL_MAX] = { /* * Print the events from /tracing/events */ -void print_tracepoint_events(const char *subsys_glob, - const char *event_glob, bool name_only) +void print_tracepoint_events(const struct print_callbacks *print_cb, void *print_state) { struct dirent **sys_namelist = NULL; - bool printed = false; int sys_items = tracing_events__scandir_alphasort(&sys_namelist); for (int i = 0; i < sys_items; i++) { @@ -73,10 +72,6 @@ void print_tracepoint_events(const char *subsys_glob, !strcmp(sys_dirent->d_name, "..")) continue; - if (subsys_glob != NULL && - !strglobmatch(sys_dirent->d_name, subsys_glob)) - continue; - dir_path = get_events_file(sys_dirent->d_name); if (!dir_path) continue; @@ -94,41 +89,40 @@ void print_tracepoint_events(const char *subsys_glob, if (tp_event_has_id(dir_path, evt_dirent) != 0) continue; - if (event_glob != NULL && - !strglobmatch(evt_dirent->d_name, event_glob)) - continue; - snprintf(evt_path, MAXPATHLEN, "%s:%s", sys_dirent->d_name, evt_dirent->d_name); - if (name_only) - printf("%s ", evt_path); - else { - printf(" %-50s [%s]\n", evt_path, - event_type_descriptors[PERF_TYPE_TRACEPOINT]); - } - printed = true; + print_cb->print_event(print_state, + /*topic=*/NULL, + /*pmu_name=*/NULL, + evt_path, + /*event_alias=*/NULL, + /*deprecated=*/false, + "Tracepoint event", + /*desc=*/NULL, + /*long_desc=*/NULL, + /*encoding_desc=*/NULL, + /*metric_name=*/NULL, + /*metric_expr=*/NULL); } free(dir_path); free(evt_namelist); } free(sys_namelist); - if (printed && pager_in_use()) - printf("\n"); } -void print_sdt_events(const char *subsys_glob, const char *event_glob, - bool name_only) +void print_sdt_events(const struct print_callbacks *print_cb, void *print_state) { - struct probe_cache *pcache; - struct probe_cache_entry *ent; struct strlist *bidlist, *sdtlist; - struct strlist_config cfg = {.dont_dupstr = true}; - struct str_node *nd, *nd2; - char *buf, *path, *ptr = NULL; - bool show_detail = false; - int ret; - - sdtlist = strlist__new(NULL, &cfg); + struct str_node *bid_nd, *sdt_name, *next_sdt_name; + const char *last_sdt_name = NULL; + + /* + * The implicitly sorted sdtlist will hold the tracepoint name followed + * by @. If the tracepoint name is unique (determined by + * looking at the adjacent nodes) the @ is dropped otherwise + * the executable path and buildid are added to the name. + */ + sdtlist = strlist__new(NULL, NULL); if (!sdtlist) { pr_debug("Failed to allocate new strlist for SDT\n"); return; @@ -138,65 +132,76 @@ void print_sdt_events(const char *subsys_glob, const char *event_glob, pr_debug("Failed to get buildids: %d\n", errno); return; } - strlist__for_each_entry(nd, bidlist) { - pcache = probe_cache__new(nd->s, NULL); + strlist__for_each_entry(bid_nd, bidlist) { + struct probe_cache *pcache; + struct probe_cache_entry *ent; + + pcache = probe_cache__new(bid_nd->s, NULL); if (!pcache) continue; list_for_each_entry(ent, &pcache->entries, node) { - if (!ent->sdt) - continue; - if (subsys_glob && - !strglobmatch(ent->pev.group, subsys_glob)) - continue; - if (event_glob && - !strglobmatch(ent->pev.event, event_glob)) - continue; - ret = asprintf(&buf, "%s:%s@%s", ent->pev.group, - ent->pev.event, nd->s); - if (ret > 0) - strlist__add(sdtlist, buf); + char buf[1024]; + + snprintf(buf, sizeof(buf), "%s:%s@%s", + ent->pev.group, ent->pev.event, bid_nd->s); + strlist__add(sdtlist, buf); } probe_cache__delete(pcache); } strlist__delete(bidlist); - strlist__for_each_entry(nd, sdtlist) { - buf = strchr(nd->s, '@'); - if (buf) - *(buf++) = '\0'; - if (name_only) { - printf("%s ", nd->s); - continue; - } - nd2 = strlist__next(nd); - if (nd2) { - ptr = strchr(nd2->s, '@'); - if (ptr) - *ptr = '\0'; - if (strcmp(nd->s, nd2->s) == 0) - show_detail = true; + strlist__for_each_entry(sdt_name, sdtlist) { + bool show_detail = false; + char *bid = strchr(sdt_name->s, '@'); + char *evt_name = NULL; + + if (bid) + *(bid++) = '\0'; + + if (last_sdt_name && !strcmp(last_sdt_name, sdt_name->s)) { + show_detail = true; + } else { + next_sdt_name = strlist__next(sdt_name); + if (next_sdt_name) { + char *bid2 = strchr(next_sdt_name->s, '@'); + + if (bid2) + *bid2 = '\0'; + if (strcmp(sdt_name->s, next_sdt_name->s) == 0) + show_detail = true; + if (bid2) + *bid2 = '@'; + } } + last_sdt_name = sdt_name->s; + if (show_detail) { - path = build_id_cache__origname(buf); - ret = asprintf(&buf, "%s@%s(%.12s)", nd->s, path, buf); - if (ret > 0) { - printf(" %-50s [%s]\n", buf, "SDT event"); - free(buf); + char *path = build_id_cache__origname(bid); + + if (path) { + asprintf(&evt_name, "%s@%s(%.12s)", sdt_name->s, path, bid); + free(path); } - free(path); - } else - printf(" %-50s [%s]\n", nd->s, "SDT event"); - if (nd2) { - if (strcmp(nd->s, nd2->s) != 0) - show_detail = false; - if (ptr) - *ptr = '@'; } + print_cb->print_event(print_state, + /*topic=*/NULL, + /*pmu_name=*/NULL, + evt_name ?: sdt_name->s, + /*event_alias=*/NULL, + /*deprecated=*/false, + "SDT event", + /*desc=*/NULL, + /*long_desc=*/NULL, + /*encoding_desc=*/NULL, + /*metric_name=*/NULL, + /*metric_expr=*/NULL); + + free(evt_name); } strlist__delete(sdtlist); } -int print_hwcache_events(const char *event_glob, bool name_only) +int print_hwcache_events(const struct print_callbacks *print_cb, void *print_state) { struct strlist *evt_name_list = strlist__new(NULL, NULL); struct str_node *nd; @@ -216,9 +221,6 @@ int print_hwcache_events(const char *event_glob, bool name_only) char name[64]; __evsel__hw_cache_type_op_res_name(type, op, i, name, sizeof(name)); - if (event_glob != NULL && !strglobmatch(name, event_glob)) - continue; - if (!perf_pmu__has_hybrid()) { if (is_event_supported(PERF_TYPE_HW_CACHE, type | (op << 8) | (i << 16))) @@ -240,55 +242,45 @@ int print_hwcache_events(const char *event_glob, bool name_only) } strlist__for_each_entry(nd, evt_name_list) { - if (name_only) { - printf("%s ", nd->s); - continue; - } - printf(" %-50s [%s]\n", nd->s, event_type_descriptors[PERF_TYPE_HW_CACHE]); + print_cb->print_event(print_state, + "cache", + /*pmu_name=*/NULL, + nd->s, + /*event_alias=*/NULL, + /*deprecated=*/false, + event_type_descriptors[PERF_TYPE_HW_CACHE], + /*desc=*/NULL, + /*long_desc=*/NULL, + /*encoding_desc=*/NULL, + /*metric_name=*/NULL, + /*metric_expr=*/NULL); } - if (!strlist__empty(evt_name_list) && pager_in_use()) - printf("\n"); - strlist__delete(evt_name_list); return 0; } -static void print_tool_event(const struct event_symbol *syms, const char *event_glob, - bool name_only) -{ - if (syms->symbol == NULL) - return; - - if (event_glob && !(strglobmatch(syms->symbol, event_glob) || - (syms->alias && strglobmatch(syms->alias, event_glob)))) - return; - - if (name_only) - printf("%s ", syms->symbol); - else { - char name[MAX_NAME_LEN]; - - if (syms->alias && strlen(syms->alias)) - snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias); - else - strlcpy(name, syms->symbol, MAX_NAME_LEN); - printf(" %-50s [%s]\n", name, "Tool event"); - } -} - -void print_tool_events(const char *event_glob, bool name_only) +void print_tool_events(const struct print_callbacks *print_cb, void *print_state) { // Start at 1 because the first enum entry means no tool event. - for (int i = 1; i < PERF_TOOL_MAX; ++i) - print_tool_event(event_symbols_tool + i, event_glob, name_only); - - if (pager_in_use()) - printf("\n"); + for (int i = 1; i < PERF_TOOL_MAX; ++i) { + print_cb->print_event(print_state, + "tool", + /*pmu_name=*/NULL, + event_symbols_tool[i].symbol, + event_symbols_tool[i].alias, + /*deprecated=*/false, + "Tool event", + /*desc=*/NULL, + /*long_desc=*/NULL, + /*encoding_desc=*/NULL, + /*metric_name=*/NULL, + /*metric_expr=*/NULL); + } } -void print_symbol_events(const char *event_glob, unsigned int type, - struct event_symbol *syms, unsigned int max, - bool name_only) +void print_symbol_events(const struct print_callbacks *print_cb, void *print_state, + unsigned int type, const struct event_symbol *syms, + unsigned int max) { struct strlist *evt_name_list = strlist__new(NULL, NULL); struct str_node *nd; @@ -305,10 +297,6 @@ void print_symbol_events(const char *event_glob, unsigned int type, if (syms[i].symbol == NULL) continue; - if (event_glob != NULL && !(strglobmatch(syms[i].symbol, event_glob) || - (syms[i].alias && strglobmatch(syms[i].alias, event_glob)))) - continue; - if (!is_event_supported(type, i)) continue; @@ -322,63 +310,88 @@ void print_symbol_events(const char *event_glob, unsigned int type, } strlist__for_each_entry(nd, evt_name_list) { - if (name_only) { - printf("%s ", nd->s); - continue; + char *alias = strstr(nd->s, " OR "); + + if (alias) { + *alias = '\0'; + alias += 4; } - printf(" %-50s [%s]\n", nd->s, event_type_descriptors[type]); + print_cb->print_event(print_state, + /*topic=*/NULL, + /*pmu_name=*/NULL, + nd->s, + alias, + /*deprecated=*/false, + event_type_descriptors[type], + /*desc=*/NULL, + /*long_desc=*/NULL, + /*encoding_desc=*/NULL, + /*metric_name=*/NULL, + /*metric_expr=*/NULL); } - if (!strlist__empty(evt_name_list) && pager_in_use()) - printf("\n"); - strlist__delete(evt_name_list); } /* * Print the help text for the event symbols: */ -void print_events(const char *event_glob, bool name_only, bool quiet_flag, - bool long_desc, bool details_flag, bool deprecated, - const char *pmu_name) +void print_events(const struct print_callbacks *print_cb, void *print_state) { - print_symbol_events(event_glob, PERF_TYPE_HARDWARE, - event_symbols_hw, PERF_COUNT_HW_MAX, name_only); - - print_symbol_events(event_glob, PERF_TYPE_SOFTWARE, - event_symbols_sw, PERF_COUNT_SW_MAX, name_only); - print_tool_events(event_glob, name_only); - - print_hwcache_events(event_glob, name_only); - - print_pmu_events(event_glob, name_only, quiet_flag, long_desc, - details_flag, deprecated, pmu_name); - - if (event_glob != NULL) - return; - - if (!name_only) { - printf(" %-50s [%s]\n", - "rNNN", - event_type_descriptors[PERF_TYPE_RAW]); - printf(" %-50s [%s]\n", - "cpu/t1=v1[,t2=v2,t3 ...]/modifier", - event_type_descriptors[PERF_TYPE_RAW]); - if (pager_in_use()) - printf(" (see 'man perf-list' on how to encode it)\n\n"); - - printf(" %-50s [%s]\n", - "mem:[/len][:access]", - event_type_descriptors[PERF_TYPE_BREAKPOINT]); - if (pager_in_use()) - printf("\n"); - } - - print_tracepoint_events(NULL, NULL, name_only); - - print_sdt_events(NULL, NULL, name_only); - - metricgroup__print(true, true, NULL, name_only, details_flag, - pmu_name); - - print_libpfm_events(name_only, long_desc); + print_symbol_events(print_cb, print_state, PERF_TYPE_HARDWARE, + event_symbols_hw, PERF_COUNT_HW_MAX); + print_symbol_events(print_cb, print_state, PERF_TYPE_SOFTWARE, + event_symbols_sw, PERF_COUNT_SW_MAX); + + print_tool_events(print_cb, print_state); + + print_hwcache_events(print_cb, print_state); + + print_pmu_events(print_cb, print_state); + + print_cb->print_event(print_state, + /*topic=*/NULL, + /*pmu_name=*/NULL, + "rNNN", + /*event_alias=*/NULL, + /*deprecated=*/false, + event_type_descriptors[PERF_TYPE_RAW], + /*desc=*/NULL, + /*long_desc=*/NULL, + /*encoding_desc=*/NULL, + /*metric_name=*/NULL, + /*metric_expr=*/NULL); + + print_cb->print_event(print_state, + /*topic=*/NULL, + /*pmu_name=*/NULL, + "cpu/t1=v1[,t2=v2,t3 ...]/modifier", + /*event_alias=*/NULL, + /*deprecated=*/false, + event_type_descriptors[PERF_TYPE_RAW], + "(see 'man perf-list' on how to encode it)", + /*long_desc=*/NULL, + /*encoding_desc=*/NULL, + /*metric_name=*/NULL, + /*metric_expr=*/NULL); + + print_cb->print_event(print_state, + /*topic=*/NULL, + /*pmu_name=*/NULL, + "mem:[/len][:access]", + /*event_alias=*/NULL, + /*deprecated=*/false, + event_type_descriptors[PERF_TYPE_BREAKPOINT], + /*desc=*/NULL, + /*long_desc=*/NULL, + /*encoding_desc=*/NULL, + /*metric_name=*/NULL, + /*metric_expr=*/NULL); + + print_tracepoint_events(print_cb, print_state); + + print_sdt_events(print_cb, print_state); + + metricgroup__print(print_cb, print_state); + + print_libpfm_events(print_cb, print_state); } diff --git a/tools/perf/util/print-events.h b/tools/perf/util/print-events.h index 1da9910d83a6..235c3e123079 100644 --- a/tools/perf/util/print-events.h +++ b/tools/perf/util/print-events.h @@ -2,21 +2,37 @@ #ifndef __PERF_PRINT_EVENTS_H #define __PERF_PRINT_EVENTS_H +#include #include struct event_symbol; -void print_events(const char *event_glob, bool name_only, bool quiet_flag, - bool long_desc, bool details_flag, bool deprecated, - const char *pmu_name); -int print_hwcache_events(const char *event_glob, bool name_only); -void print_sdt_events(const char *subsys_glob, const char *event_glob, - bool name_only); -void print_symbol_events(const char *event_glob, unsigned int type, - struct event_symbol *syms, unsigned int max, - bool name_only); -void print_tool_events(const char *event_glob, bool name_only); -void print_tracepoint_events(const char *subsys_glob, const char *event_glob, - bool name_only); +struct print_callbacks { + void (*print_start)(void *print_state); + void (*print_end)(void *print_state); + void (*print_event)(void *print_state, const char *topic, + const char *pmu_name, + const char *event_name, const char *event_alias, + bool deprecated, const char *event_type_desc, + const char *desc, const char *long_desc, + const char *encoding_desc, + const char *metric_name, const char *metric_expr); + void (*print_metric)(void *print_state, + const char *group, + const char *name, + const char *desc, + const char *long_desc, + const char *expr); +}; + +/** Print all events, the default when no options are specified. */ +void print_events(const struct print_callbacks *print_cb, void *print_state); +int print_hwcache_events(const struct print_callbacks *print_cb, void *print_state); +void print_sdt_events(const struct print_callbacks *print_cb, void *print_state); +void print_symbol_events(const struct print_callbacks *print_cb, void *print_state, + unsigned int type, const struct event_symbol *syms, + unsigned int max); +void print_tool_events(const struct print_callbacks *print_cb, void *print_state); +void print_tracepoint_events(const struct print_callbacks *print_cb, void *print_state); #endif /* __PERF_PRINT_EVENTS_H */ From patchwork Mon Nov 14 18:12:51 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Rogers X-Patchwork-Id: 19979 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:6687:0:0:0:0:0 with SMTP id l7csp2292532wru; Mon, 14 Nov 2022 10:20:22 -0800 (PST) X-Google-Smtp-Source: AA0mqf5cFtRjrqg6nUaNne2jBz2hahv05M0O/qefGJPMvQPdSlbouuJ7P4cc7D88/0qBDWHbv0AP X-Received: by 2002:a17:906:c251:b0:7ae:1874:3e09 with SMTP id bl17-20020a170906c25100b007ae18743e09mr10574178ejb.534.1668450022321; Mon, 14 Nov 2022 10:20:22 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1668450022; cv=none; d=google.com; s=arc-20160816; b=IZOy/NmebLSaEmuoIIKRjIQvagDbrAY8pjerIjd5gwOSZlW5bbLu9z/5bj2ubtVAhU wfT6oOd62Z08Vi5P6OWVBSQTWDtAL2E/Gb1C56YQXtAARe8TOBn+cCcI9uVhjP0TqUL4 dfsGmBFgUtGPUDhd3LwT/aSD/53a0ruQAub/27sb3J7XYhtGwLa+eP+JLTdOKYfFXik0 ZOKR3GO2WLXvqKoRMjkqESmtwLctkWGeEPKY4FePj0FU0D2X3uTaf8ZQkYoJC1BE0MRA wxvFOetELbIj3RCym53BkpoMhGzm+cwNdVMWmjisOEvCGPQW9Q7tUov0AfXu1lvCzt6C pA+w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:from:subject:references:mime-version :message-id:in-reply-to:date:dkim-signature; bh=nAX60ecFtxgT+PDunRPYKAFBfhjC2kUCNn7e5xMw2JM=; b=IcRJjtT82Q3s3mRgNGBRPr8TdD0tMYlWB7/JJhpVYX8cN/+xJ6wZFoCGwBpA3Ld5c2 iNvDdSn2/x4cXW4By4+M9SG8VDdc6Lq7WogwRQIAI72Q3tP/EJ03h4aCLapv7jgExIoJ kfOVO8zhTwDJZyriu+tNJO2g5j1NcsMmh+dJTxaKHSYHjEwYRzPFb4bhr3Yt5HxA0u3F 2vd2tdFYx/8B+tTCdWp9va+4gg9CvGTX+vNLFwj+bTqTqiRC9iuYr3mI4PGsLcXlCJbN 9zO/NPjUpleEJvR3PMvkkwLBkAvKnUPkkUMi/Sd2TkaugJrifJkppt5uofOWQjIjRasr F5LA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20210112 header.b=iF9G5NRA; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id qb23-20020a1709077e9700b0078dcf17c084si9646700ejc.728.2022.11.14.10.19.56; Mon, 14 Nov 2022 10:20:22 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20210112 header.b=iF9G5NRA; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238283AbiKNSQE (ORCPT + 99 others); Mon, 14 Nov 2022 13:16:04 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44598 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238376AbiKNSPl (ORCPT ); Mon, 14 Nov 2022 13:15:41 -0500 Received: from mail-pl1-x64a.google.com (mail-pl1-x64a.google.com [IPv6:2607:f8b0:4864:20::64a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 08DB545084 for ; Mon, 14 Nov 2022 10:14:30 -0800 (PST) Received: by mail-pl1-x64a.google.com with SMTP id b2-20020a170902d50200b001871a3c51afso9398103plg.8 for ; Mon, 14 Nov 2022 10:14:30 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:references:mime-version:message-id:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=nAX60ecFtxgT+PDunRPYKAFBfhjC2kUCNn7e5xMw2JM=; b=iF9G5NRA91tx9faK3iFNTr9LXSL/ZAQJq/NY4pO4LuBFVIcd09jwsextlDdC3YyBKR ErFC0E+3WxRGILlo2J5MlFPLGD2bkvE0maN3Y0lg1c5+FP7Eq5vFBGNEbkKoSJ7SMxvY B1coOsfgtotteEQ0GNXe3hMRw1+OxLZjb92Sf8L808aaLaR0dLOc+fZDT37XhADYf+a+ vLRD4w8FeQVEBo25h/6btw9CRcVDW8aaZwZolJMTbzAGmQXU8cY5stW9mYb21abWg/18 YG4MK+1SYf2AMq8lLtwS+GjSF5GNL65trUQC27YXr5qfPhWfGXvZ0g9TyFPb4BgBRD5i 43xA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:references:mime-version:message-id:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=nAX60ecFtxgT+PDunRPYKAFBfhjC2kUCNn7e5xMw2JM=; b=uj7OxZVwmYz9pDqI32sTh9sNrNV8Q2ImJWgvAqaoBjFj01wkuS4+RqXCE5aAn3V9W5 oNDCDcWUjdvEZYme2lmhTLlJPR3TmWvD/vPoY1m9Ocs/3/Mg6I97aglH4KsjBrn7i+W8 8bMkJdrynenj+VFowvtOV2oUPtX/73Hbn+1rwlB4n21OkhtC97oxHo+ZWwcY2Tnax1UT W4AUGFiuOhii5A3e8gCweDXcdlPicjHIS4MqyKfEmECS/sWEDx5j34kM1IGMhHkehi1j 1s8Z0J0IqPfHAFB9Dvj2iTphOJUWvrTlG03ba0qSzfDcLYLd/RJZZR9Lyx/HsPcxzjZ3 jp4g== X-Gm-Message-State: ANoB5plwAKuLBEHyUlRhTxzLHbI2WOWnkc5fnGhZJeogymKZCFLPWcOR iKPUCrDhBqQ+8AYv0YaFIC4Ai9qFqoYN X-Received: from irogers.svl.corp.google.com ([2620:15c:2d4:203:553:438f:b86a:87f]) (user=irogers job=sendgmr) by 2002:a17:90b:a10:b0:20a:eab5:cf39 with SMTP id gg16-20020a17090b0a1000b0020aeab5cf39mr1115442pjb.1.1668449669656; Mon, 14 Nov 2022 10:14:29 -0800 (PST) Date: Mon, 14 Nov 2022 10:12:51 -0800 In-Reply-To: <20221114181251.2683871-1-irogers@google.com> Message-Id: <20221114181251.2683871-10-irogers@google.com> Mime-Version: 1.0 References: <20221114181251.2683871-1-irogers@google.com> X-Mailer: git-send-email 2.38.1.431.g37b22c650d-goog Subject: [PATCH v2 9/9] perf list: Add json output option From: Ian Rogers To: Weilin Wang , Perry Taylor , Caleb Biggers , Leo Yan , Adrian Hunter , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Mark Rutland , Alexander Shishkin , Jiri Olsa , Namhyung Kim , Sandipan Das , Kajol Jain , Zhengjun Xing , Kan Liang , Ravi Bangoria , Xin Gao , Rob Herring , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org Cc: Stephane Eranian , Ian Rogers X-Spam-Status: No, score=-9.6 required=5.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1749496650249279894?= X-GMAIL-MSGID: =?utf-8?q?1749496650249279894?= Output events and metrics in a json format by overriding the print callbacks. Currently other command line options aren't supported and metrics are repeated once per metric group. Signed-off-by: Ian Rogers --- tools/perf/Documentation/perf-list.txt | 4 + tools/perf/builtin-list.c | 283 ++++++++++++++++++++----- 2 files changed, 229 insertions(+), 58 deletions(-) diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt index 44a819af573d..43263ca88ff7 100644 --- a/tools/perf/Documentation/perf-list.txt +++ b/tools/perf/Documentation/perf-list.txt @@ -43,6 +43,10 @@ Print deprecated events. By default the deprecated events are hidden. Print PMU events and metrics limited to the specific PMU name. (e.g. --unit cpu, --unit msr, --unit cpu_core, --unit cpu_atom) +-j:: +--json:: +Output in json format. + [[EVENT_MODIFIERS]] EVENT MODIFIERS --------------- diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c index 91e2b6f52548..910b5c3a7365 100644 --- a/tools/perf/builtin-list.c +++ b/tools/perf/builtin-list.c @@ -19,6 +19,7 @@ #include "util/strlist.h" #include #include +#include #include struct print_state { @@ -217,10 +218,165 @@ static void default_print_metric(void *ps, } } +struct json_print_state { + /** Should a separator be printed prior to the next item? */ + bool need_sep; +}; + +static void json_print_start(void *print_state __maybe_unused) +{ + printf("[\n"); +} + +static void json_print_end(void *ps) +{ + struct json_print_state *print_state = ps; + + printf("%s]\n", print_state->need_sep ? "\n" : ""); +} + +static void fix_escape_printf(const char *fmt, ...) +{ + va_list args; + char buf[2048]; + size_t buf_pos = 0; + + va_start(args, fmt); + for (size_t fmt_pos = 0; fmt_pos < strlen(fmt); fmt_pos++) { + switch (fmt[fmt_pos]) { + case '%': { + const char *s = va_arg(args, const char*); + + fmt_pos++; + assert(fmt[fmt_pos] == 's'); + for (size_t s_pos = 0; s_pos < strlen(s); s_pos++) { + switch (s[s_pos]) { + case '\\': + __fallthrough; + case '\"': + buf[buf_pos++] = '\\'; + assert(buf_pos < sizeof(buf)); + __fallthrough; + default: + buf[buf_pos++] = s[s_pos]; + assert(buf_pos < sizeof(buf)); + break; + } + } + break; + } + default: + buf[buf_pos++] = fmt[fmt_pos]; + assert(buf_pos < sizeof(buf)); + break; + } + } + va_end(args); + buf[buf_pos] = '\0'; + fputs(buf, stdout); +} + +static void json_print_event(void *ps, const char *pmu_name, const char *topic, + const char *event_name, const char *event_alias, + bool deprecated, const char *event_type_desc, + const char *desc, const char *long_desc, + const char *encoding_desc, + const char *metric_name, const char *metric_expr) +{ + struct json_print_state *print_state = ps; + bool need_sep = false; + + printf("%s{\n", print_state->need_sep ? ",\n" : ""); + print_state->need_sep = true; + if (pmu_name) { + fix_escape_printf("\t\"Unit\": \"%s\"", pmu_name); + need_sep = true; + } + if (topic) { + fix_escape_printf("%s\t\"Topic\": \"%s\"", need_sep ? ",\n" : "", topic); + need_sep = true; + } + if (event_name) { + fix_escape_printf("%s\t\"EventName\": \"%s\"", need_sep ? ",\n" : "", event_name); + need_sep = true; + } + if (event_alias && strlen(event_alias)) { + fix_escape_printf("%s\t\"EventAlias\": \"%s\"", need_sep ? ",\n" : "", event_alias); + need_sep = true; + } + if (event_type_desc) { + fix_escape_printf("%s\t\"EventType\": \"%s\"", need_sep ? ",\n" : "", + event_type_desc); + need_sep = true; + } + if (deprecated) { + fix_escape_printf("%s\t\"Deprecated\": \"%s\"", need_sep ? ",\n" : "", + deprecated ? "1" : "0"); + need_sep = true; + } + if (desc) { + fix_escape_printf("%s\t\"BriefDescription\": \"%s\"", need_sep ? ",\n" : "", desc); + need_sep = true; + } + if (long_desc) { + fix_escape_printf("%s\t\"PublicDescription\": \"%s\"", need_sep ? ",\n" : "", + long_desc); + need_sep = true; + } + if (encoding_desc) { + fix_escape_printf("%s\t\"Encoding\": \"%s\"", need_sep ? ",\n" : "", encoding_desc); + need_sep = true; + } + if (metric_name) { + fix_escape_printf("%s\t\"MetricName\": \"%s\"", need_sep ? ",\n" : "", metric_name); + need_sep = true; + } + if (metric_expr) { + fix_escape_printf("%s\t\"MetricExpr\": \"%s\"", need_sep ? ",\n" : "", metric_expr); + need_sep = true; + } + printf("%s}", need_sep ? "\n" : ""); +} + +static void json_print_metric(void *ps __maybe_unused, const char *group, + const char *name, const char *desc, + const char *long_desc, const char *expr) +{ + struct json_print_state *print_state = ps; + bool need_sep = false; + + printf("%s{\n", print_state->need_sep ? ",\n" : ""); + print_state->need_sep = true; + if (group) { + fix_escape_printf("\t\"MetricGroup\": \"%s\"", group); + need_sep = true; + } + if (name) { + fix_escape_printf("%s\t\"MetricName\": \"%s\"", need_sep ? ",\n" : "", name); + need_sep = true; + } + if (expr) { + fix_escape_printf("%s\t\"MetricExpr\": \"%s\"", need_sep ? ",\n" : "", expr); + need_sep = true; + } + if (desc) { + fix_escape_printf("%s\t\"BriefDescription\": \"%s\"", need_sep ? ",\n" : "", desc); + need_sep = true; + } + if (long_desc) { + fix_escape_printf("%s\t\"PublicDescription\": \"%s\"", need_sep ? ",\n" : "", + long_desc); + need_sep = true; + } + printf("%s}", need_sep ? "\n" : ""); +} + int cmd_list(int argc, const char **argv) { int i, ret = 0; - struct print_state ps = {}; + struct print_state default_ps = {}; + struct print_state json_ps = {}; + void *ps = &default_ps; struct print_callbacks print_cb = { .print_start = default_print_start, .print_end = default_print_end, @@ -229,15 +385,17 @@ int cmd_list(int argc, const char **argv) }; const char *hybrid_name = NULL; const char *unit_name = NULL; + bool json = false; struct option list_options[] = { - OPT_BOOLEAN(0, "raw-dump", &ps.name_only, "Dump raw events"), - OPT_BOOLEAN('d', "desc", &ps.desc, + OPT_BOOLEAN(0, "raw-dump", &default_ps.name_only, "Dump raw events"), + OPT_BOOLEAN('j', "json", &json, "JSON encode events and metrics"), + OPT_BOOLEAN('d', "desc", &default_ps.desc, "Print extra event descriptions. --no-desc to not print."), - OPT_BOOLEAN('v', "long-desc", &ps.long_desc, + OPT_BOOLEAN('v', "long-desc", &default_ps.long_desc, "Print longer event descriptions."), - OPT_BOOLEAN(0, "details", &ps.detailed, + OPT_BOOLEAN(0, "details", &default_ps.detailed, "Print information on the perf event names and expressions used internally by events."), - OPT_BOOLEAN(0, "deprecated", &ps.deprecated, + OPT_BOOLEAN(0, "deprecated", &default_ps.deprecated, "Print deprecated events."), OPT_STRING(0, "cputype", &hybrid_name, "hybrid cpu type", "Limit PMU or metric printing to the given hybrid PMU (e.g. core or atom)."), @@ -261,28 +419,37 @@ int cmd_list(int argc, const char **argv) setup_pager(); - if (!ps.name_only) + if (!default_ps.name_only) setup_pager(); - ps.desc = !ps.long_desc; - ps.last_topic = strdup(""); - assert(ps.last_topic); - ps.visited_metrics = strlist__new(NULL, NULL); - assert(ps.visited_metrics); - if (unit_name) - ps.pmu_glob = strdup(unit_name); - else if (hybrid_name) { - ps.pmu_glob = perf_pmu__hybrid_type_to_pmu(hybrid_name); - if (!ps.pmu_glob) - pr_warning("WARNING: hybrid cputype is not supported!\n"); + if (json) { + print_cb = (struct print_callbacks){ + .print_start = json_print_start, + .print_end = json_print_end, + .print_event = json_print_event, + .print_metric = json_print_metric, + }; + ps = &json_ps; + } else { + default_ps.desc = !default_ps.long_desc; + default_ps.last_topic = strdup(""); + assert(default_ps.last_topic); + default_ps.visited_metrics = strlist__new(NULL, NULL); + assert(default_ps.visited_metrics); + if (unit_name) + default_ps.pmu_glob = strdup(unit_name); + else if (hybrid_name) { + default_ps.pmu_glob = perf_pmu__hybrid_type_to_pmu(hybrid_name); + if (!default_ps.pmu_glob) + pr_warning("WARNING: hybrid cputype is not supported!\n"); + } } - print_cb.print_start(&ps); if (argc == 0) { - ps.metrics = true; - ps.metricgroups = true; - print_events(&print_cb, &ps); + default_ps.metrics = true; + default_ps.metricgroups = true; + print_events(&print_cb, ps); goto out; } @@ -290,32 +457,32 @@ int cmd_list(int argc, const char **argv) char *sep, *s; if (strcmp(argv[i], "tracepoint") == 0) - print_tracepoint_events(&print_cb, &ps); + print_tracepoint_events(&print_cb, ps); else if (strcmp(argv[i], "hw") == 0 || strcmp(argv[i], "hardware") == 0) - print_symbol_events(&print_cb, &ps, PERF_TYPE_HARDWARE, + print_symbol_events(&print_cb, ps, PERF_TYPE_HARDWARE, event_symbols_hw, PERF_COUNT_HW_MAX); else if (strcmp(argv[i], "sw") == 0 || strcmp(argv[i], "software") == 0) { - print_symbol_events(&print_cb, &ps, PERF_TYPE_SOFTWARE, + print_symbol_events(&print_cb, ps, PERF_TYPE_SOFTWARE, event_symbols_sw, PERF_COUNT_SW_MAX); - print_tool_events(&print_cb, &ps); + print_tool_events(&print_cb, ps); } else if (strcmp(argv[i], "cache") == 0 || strcmp(argv[i], "hwcache") == 0) - print_hwcache_events(&print_cb, &ps); + print_hwcache_events(&print_cb, ps); else if (strcmp(argv[i], "pmu") == 0) - print_pmu_events(&print_cb, &ps); + print_pmu_events(&print_cb, ps); else if (strcmp(argv[i], "sdt") == 0) - print_sdt_events(&print_cb, &ps); + print_sdt_events(&print_cb, ps); else if (strcmp(argv[i], "metric") == 0 || strcmp(argv[i], "metrics") == 0) { - ps.metricgroups = false; - ps.metrics = true; - metricgroup__print(&print_cb, &ps); + default_ps.metricgroups = false; + default_ps.metrics = true; + metricgroup__print(&print_cb, ps); } else if (strcmp(argv[i], "metricgroup") == 0 || strcmp(argv[i], "metricgroups") == 0) { - ps.metricgroups = true; - ps.metrics = false; - metricgroup__print(&print_cb, &ps); + default_ps.metricgroups = true; + default_ps.metrics = false; + metricgroup__print(&print_cb, ps); } else if ((sep = strchr(argv[i], ':')) != NULL) { int sep_idx; @@ -327,41 +494,41 @@ int cmd_list(int argc, const char **argv) } s[sep_idx] = '\0'; - ps.pmu_glob = s; - ps.event_glob = s + sep_idx + 1; - print_tracepoint_events(&print_cb, &ps); - print_sdt_events(&print_cb, &ps); - ps.metrics = true; - ps.metricgroups = true; - metricgroup__print(&print_cb, &ps); + default_ps.pmu_glob = s; + default_ps.event_glob = s + sep_idx + 1; + print_tracepoint_events(&print_cb, ps); + print_sdt_events(&print_cb, ps); + default_ps.metrics = true; + default_ps.metricgroups = true; + metricgroup__print(&print_cb, ps); free(s); } else { if (asprintf(&s, "*%s*", argv[i]) < 0) { printf("Critical: Not enough memory! Trying to continue...\n"); continue; } - ps.event_glob = s; - print_symbol_events(&print_cb, &ps, PERF_TYPE_HARDWARE, + default_ps.event_glob = s; + print_symbol_events(&print_cb, ps, PERF_TYPE_HARDWARE, event_symbols_hw, PERF_COUNT_HW_MAX); - print_symbol_events(&print_cb, &ps, PERF_TYPE_SOFTWARE, + print_symbol_events(&print_cb, ps, PERF_TYPE_SOFTWARE, event_symbols_sw, PERF_COUNT_SW_MAX); - print_tool_events(&print_cb, &ps); - print_hwcache_events(&print_cb, &ps); - print_pmu_events(&print_cb, &ps); - print_tracepoint_events(&print_cb, &ps); - print_sdt_events(&print_cb, &ps); - ps.metrics = true; - ps.metricgroups = true; - metricgroup__print(&print_cb, &ps); + print_tool_events(&print_cb, ps); + print_hwcache_events(&print_cb, ps); + print_pmu_events(&print_cb, ps); + print_tracepoint_events(&print_cb, ps); + print_sdt_events(&print_cb, ps); + default_ps.metrics = true; + default_ps.metricgroups = true; + metricgroup__print(&print_cb, ps); free(s); } } out: - print_cb.print_end(&ps); - free(ps.pmu_glob); - free(ps.last_topic); - free(ps.last_metricgroups); - strlist__delete(ps.visited_metrics); + print_cb.print_end(ps); + free(default_ps.pmu_glob); + free(default_ps.last_topic); + free(default_ps.last_metricgroups); + strlist__delete(default_ps.visited_metrics); return ret; }