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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.