public inbox for dwarves@vger.kernel.org
 help / color / mirror / Atom feed
From: Arnaldo Carvalho de Melo <acme@kernel.org>
To: Willy Tarreau <w@1wt.eu>
Cc: dwarves@vger.kernel.org, Alan Maguire <alan.maguire@oracle.com>,
	Jiri Olsa <jolsa@kernel.org>,
	Clark Williams <williams@redhat.com>,
	Kate Carcia <kcarcia@redhat.com>,
	Arnaldo Carvalho de Melo <acme@redhat.com>,
	"Gustavo A. R. Silva" <gustavoars@kernel.org>
Subject: [PATCH 2/3] fprintf: Show statistics about members with flexible arrays
Date: Tue,  8 Oct 2024 16:52:08 -0300	[thread overview]
Message-ID: <20241008195209.1094299-3-acme@kernel.org> (raw)
In-Reply-To: <20241008195209.1094299-1-acme@kernel.org>

From: Arnaldo Carvalho de Melo <acme@redhat.com>

For instance, this one has embedded flexible arrays:

  $ pahole lirc_fh
  struct lirc_fh {
  	struct list_head           list;                 /*     0    16 */
  	struct rc_dev *            rc;                   /*    16     8 */
  	int                        carrier_low;          /*    24     4 */

  	/* XXX 4 bytes hole, try to pack */

  	struct {
  		union {
  			struct __kfifo kfifo;            /*    32    24 */
  			unsigned int * type;             /*    32     8 */
  			const unsigned int  * const_type; /*    32     8 */
  			char *     rectype;              /*    32     8 */
  			unsigned int * ptr;              /*    32     8 */
  			const unsigned int  * ptr_const; /*    32     8 */
  		};                                       /*    32    24 */
  		unsigned int       buf[];                /*    56     0 */
  	} rawir;                                         /*    32    24 */

  	/* XXX last struct has a flexible array */

  	struct {
  		union {
  			struct __kfifo kfifo;            /*    56    24 */
  			struct lirc_scancode * type;     /*    56     8 */
  			const struct lirc_scancode  * const_type; /*    56     8 */
  			char *     rectype;              /*    56     8 */
  			struct lirc_scancode * ptr;      /*    56     8 */
  			const struct lirc_scancode  * ptr_const; /*    56     8 */
  		};                                       /*    56    24 */
  		/* --- cacheline 1 boundary (64 bytes) was 16 bytes ago --- */
  		struct lirc_scancode buf[];              /*    80     0 */
  	} scancodes;                                     /*    56    24 */

  	/* XXX last struct has a flexible array */

  	wait_queue_head_t          wait_poll;            /*    80    24 */
  	u8                         send_mode;            /*   104     1 */
  	u8                         rec_mode;             /*   105     1 */

  	/* size: 112, cachelines: 2, members: 8 */
  	/* sum members: 102, holes: 1, sum holes: 4 */
  	/* padding: 6 */
  	/* flexible array members: end: 2 */
  	/* last cacheline: 48 bytes */
  };
  $

'end' means that the members with flexible arrays have them in the
"classical" sense, i.e. the last member of those member types is a []
member.

When 'middle' appears it means another level, just like the above
'struct lirc_fh' has multiple members in its midle that are flexible
arrays.

If we use 'pahole --with_embedded_flexible_array' we'll see quite a few
in the Linux kernel (using BTF info from /sys/kernel/btf/vmlinux, mostly
available in most kernels these days), using --sizes so that we get just
one line per Linux kernel struct that have embedded flexible arrays (and
its sizes and number of alignment holes, as bonuses):

  $ pahole --sizes --with_embedded_flexible_array | head
  mem_cgroup	2240	10
  pglist_data	175424	7
  zone	1728	5
  cgroup	1984	3
  cgroup_root	6272	1
  page_counter	192	1
  cpu_hw_events	5200	6
  crypto_shash	40	1
  crypto_aead	40	0
  crypto_ahash	48	2
  $

  $ pahole crypto_shash
  struct crypto_shash {
  	unsigned int               descsize;             /*     0     4 */

  	/* XXX 4 bytes hole, try to pack */

  	struct crypto_tfm          base;                 /*     8    32 */

  	/* XXX last struct has a flexible array, 1 hole */

  	/* size: 40, cachelines: 1, members: 2 */
  	/* sum members: 36, holes: 1, sum holes: 4 */
  	/* member types with holes: 1, total: 1 */
  	/* flexible array members: end: 1 */
  	/* last cacheline: 40 bytes */
  };
  $

If we expand it all:

  $ pahole -E crypto_shash
  struct crypto_shash {
  	unsigned int               descsize;                                             /*     0     4 */

  	/* XXX 4 bytes hole, try to pack */

  	struct crypto_tfm {
  		/* typedef refcount_t */ struct refcount_struct {
  			/* typedef atomic_t */ struct {
  				int counter;                                             /*     8     4 */
  			} refs; /*     8     4 */
  		} refcnt; /*     8     4 */
  		/* typedef u32 -> __u32 */ unsigned int       crt_flags;                 /*    12     4 */
  		int                node;                                                 /*    16     4 */

  		/* XXX 4 bytes hole, try to pack */

  		void               (*exit)(struct crypto_tfm *);                         /*    24     8 */
  		struct crypto_alg * __crt_alg;                                           /*    32     8 */
  		void *             __crt_ctx[];                                          /*    40     0 */
  	} base; /*     8    32 */

  	/* XXX last struct has a flexible array, 1 hole */

  	/* size: 40, cachelines: 1, members: 2 */
  	/* sum members: 36, holes: 1, sum holes: 4 */
  	/* member types with holes: 1, total: 1 */
  	/* flexible array members: end: 1 */
  	/* last cacheline: 40 bytes */
  };
  $

Interesting, but we don't see the "middle" case...

Maybe 'struct cgroup'?

  $ pahole cgroup | tail
  	struct cgroup *            ancestors[];          /*  1984     0 */

  	/* size: 1984, cachelines: 31, members: 42 */
  	/* sum members: 1952, holes: 3, sum holes: 32 */
  	/* member types with holes: 3, total: 3 */
  	/* paddings: 1, sum paddings: 4 */
  	/* forced alignments: 1 */
  	/* flexible array members: end: 1 */
  };

  $

Humm, maybe some data structure embeds 'struct cgroup'? Lets see with:

  $ pahole --contains cgroup
  cgroup_root
  $

A-ha, finally that 'middle' stat:

  $ pahole cgroup_root
  struct cgroup_root {
  	struct kernfs_root *       kf_root;              /*     0     8 */
  	unsigned int               subsys_mask;          /*     8     4 */
  	int                        hierarchy_id;         /*    12     4 */
  	struct list_head           root_list;            /*    16    16 */
  	struct callback_head       rcu;                  /*    32    16 */

  	/* XXX 16 bytes hole, try to pack */

  	/* --- cacheline 1 boundary (64 bytes) --- */
  	struct cgroup              cgrp __attribute__((__aligned__(64))); /*    64  1984 */

  	/* XXX last struct has a flexible array, embedded flexible array(s), 3 holes */

  	/* --- cacheline 32 boundary (2048 bytes) --- */
  	struct cgroup *            cgrp_ancestor_storage; /*  2048     8 */
  	atomic_t                   nr_cgrps;             /*  2056     4 */
  	unsigned int               flags;                /*  2060     4 */
  	char                       release_agent_path[4096]; /*  2064  4096 */
  	/* --- cacheline 96 boundary (6144 bytes) was 16 bytes ago --- */
  	char                       name[64];             /*  6160    64 */

  	/* size: 6272, cachelines: 98, members: 11 */
  	/* sum members: 6208, holes: 1, sum holes: 16 */
  	/* padding: 48 */
  	/* member types with holes: 1, total: 3 */
  	/* forced alignments: 1, forced holes: 1, sum forced holes: 16 */
  	/* flexible array members: end: 1, middle: 1 */
  } __attribute__((__aligned__(64)));
  $

Cc: "Gustavo A. R. Silva" <gustavoars@kernel.org>
Cc: Willy Tarreau <w@1wt.eu>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 dwarves_fprintf.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/dwarves_fprintf.c b/dwarves_fprintf.c
index 0d642a318fd836ef..e16a6b4da65ed2cd 100644
--- a/dwarves_fprintf.c
+++ b/dwarves_fprintf.c
@@ -1502,6 +1502,8 @@ struct member_types_holes {
 	uint16_t nr_with_bit_holes;
 	uint16_t total_nr_holes;
 	uint16_t total_nr_bit_holes;
+	uint16_t nr_flexible_array_members;
+	uint16_t nr_embedded_flexible_array_members;
 	uint32_t sum_paddings;
 	uint32_t sum_bit_paddings;
 };
@@ -1540,11 +1542,13 @@ static size_t class__fprintf_member_type_holes(struct class *class, const struct
 
 	if (has_flexible_array) {
 		printed += fprintf(fp, " a flexible array");
+		++holes->nr_flexible_array_members;
 		first = false;
 	}
 
 	if (has_embedded_flexible_array) {
 		printed += fprintf(fp, "%s embedded flexible array(s)", first ? "" : ",");
+		++holes->nr_embedded_flexible_array_members;
 		first = false;
 	}
 
@@ -1985,6 +1989,22 @@ next_member:
 		}
 		printed += fprintf(fp, " */\n");
 	}
+	if (member_types_holes.nr_flexible_array_members > 0 ||
+	    member_types_holes.nr_embedded_flexible_array_members > 0) {
+		printed += fprintf(fp, "%.*s/* flexible array members: ",
+				   cconf.indent, tabs);
+
+		if (member_types_holes.nr_flexible_array_members > 0)
+			printed += fprintf(fp, "end: %u", member_types_holes.nr_flexible_array_members);
+
+		if (member_types_holes.nr_embedded_flexible_array_members > 0) {
+			printed += fprintf(fp, "%smiddle: %u",
+					   member_types_holes.nr_flexible_array_members ? ", " : "",
+					   member_types_holes.nr_embedded_flexible_array_members);
+		}
+
+		printed += fprintf(fp, " */\n");
+	}
 	cacheline = (cconf.base_offset + type->size) % conf_fprintf__cacheline_size(conf);
 	if (cacheline != 0)
 		printed += fprintf(fp, "%.*s/* last cacheline: %u bytes */\n",
-- 
2.46.0


  parent reply	other threads:[~2024-10-08 19:52 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-10-08 19:52 [PATCH 0/3] Differentiate embedded flexible arrays from flexible ones Arnaldo Carvalho de Melo
2024-10-08 19:52 ` [PATCH 1/3] fprintf: Differentiate embedded flexible arrays from flexible arrays Arnaldo Carvalho de Melo
2024-10-08 19:52 ` Arnaldo Carvalho de Melo [this message]
2024-10-08 19:52 ` [PATCH 3/3] tests: Add a test for the accounting of " Arnaldo Carvalho de Melo
2024-10-13  9:51 ` [PATCH 0/3] Differentiate embedded flexible arrays from flexible ones Willy Tarreau

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20241008195209.1094299-3-acme@kernel.org \
    --to=acme@kernel.org \
    --cc=acme@redhat.com \
    --cc=alan.maguire@oracle.com \
    --cc=dwarves@vger.kernel.org \
    --cc=gustavoars@kernel.org \
    --cc=jolsa@kernel.org \
    --cc=kcarcia@redhat.com \
    --cc=w@1wt.eu \
    --cc=williams@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox