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
next prev 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